<commit_before>function set_annotation_table() {
    $('#experiment_annotation_table').tablesorter({widgets: ['zebra']});
}

function get_experiment_info() {
    $.ajax({
        data: {
            fname: 'get_experiment_info',
            eid: EXPERIMENT_ID,
        },
        success : function (data) {
            $('#experiment_info').html(data);
        }
    });
}

function edit_experiment_info() {
    $.ajax({
        data: {
            fname: 'edit_experiment_info',
            eid: EXPERIMENT_ID,
        },
        success : function(data) {
            var obj = jQuery.parseJSON(data);
            $("#experiment_info_edit_box").html(obj.output).dialog('open');
        }
    });
}

function update_experiment_info () {
    var name = $('#edit_name').val();
    if (!name) {
        alert('Please specify a name.');
        return;
    }

    var version = $('#edit_version').val();
    if (!version) {
        alert('Please specify a version');
        return;
    }

    var source_id = parseInt( $('#edit_source_id').val() );
    if (!source_id) {
        alert('Please specify a source');
        return;
    }

    var desc = $('#edit_desc').val();

    $.ajax({
        data: {
            fname: 'update_experiment_info',
            eid: EXPERIMENT_ID,
            name: name,
            desc: desc,
            source_id: source_id,
            version: version
        },
        success : function(val) {
            get_experiment_info();
            $("#experiment_info_edit_box").dialog('close');
        }
    });
}

function get_sources () {
    $.ajax({
        data: {
            fname: 'get_sources'
        },
        success : function(data) {
            var items = jQuery.parseJSON(data);
            $("#edit_source").autocomplete("option", "source", items).autocomplete("search");
        }
    });
}

function make_experiment_public () {
    $.ajax({
        data: {
            fname: 'make_experiment_public',
            eid: EXPERIMENT_ID
        },
        success : function(val) {
            get_experiment_info();
        }
    });
}

function make_experiment_private () {
    $.ajax({
        data: {
            fname: 'make_experiment_private',
            eid: EXPERIMENT_ID
        },
        success : function(val) {
            get_experiment_info();
        }
    });
}

function add_experiment_type () {
    $.ajax({
        data: {
            fname: 'add_experiment_tag',
            eid: EXPERIMENT_ID
        },
        success : function(data) {
            $("#experiment_tag_edit_box").dialog({
                beforeClose:
                    function() {
                        $("#edit_tag_name").autocomplete('close');
                    }
            });
            $("#experiment_tag_edit_box").html(data).dialog('open');
        }
    });
}

function add_tag_to_experiment () {
    var name = $('#edit_tag_name').val();
    var description = $('#edit_tag_description').val();

    if (name) {
        $.ajax({
            data: {
                fname: 'add_tag_to_experiment',
                eid: EXPERIMENT_ID,
                name: name,
                description: description
            },
            success : function(val) {
                get_experiment_info();
                $("#experiment_tag_edit_box").dialog('close');
            },
        });
    }
    else { alert ('Error: Must have type name specified!');}
}

function reset_location() {
	window.history.pushState({}, "Title", PAGE_NAME + "?eid=" + EXPERIMENT_ID);
}

function download_files() {
    coge.progress.begin({
    	title: 'Preparing Download ...',
    	content: '
The download is being generated

',
    	width: '30em',
    	height: '10em'
    });

    $.ajax({
        data: {
            fname: "get_file_urls",
            eid: EXPERIMENT_ID
        },
        dataType: "json",
        success : function(json) {
            if (json.url) {  // finished successfully
                coge.progress.succeeded("File: " + json.filename);
                setTimeout(function() { coge.utils.open(json.url) }, 10);
            }
            else { // error occurred
                coge.progress.failed();
            }
        }
    });
}

function toggle_load_log() { // TODO: shared with GenomeInfo.pl, move to module
	var btn = $('#log_button');
	var log = $('#log_contents');
	var spinner = $('#log_spinner');

	var setVisible = function(visible) { // TODO: i want to use jQuery.toggle() instead, oh well
    	if (visible) {
			log.removeClass('hidden');
	    	btn.html('Hide');
	    	spinner.animate({opacity:0});
    	}
    	else {
    		log.addClass('hidden');
    		btn.html('Show');
    		spinner.animate({opacity:0});
    	}
	}

	if (log.is(":hidden")) {
		if (log.html() == '') {
			spinner.css({opacity:1});
			$.ajax({
		        data: {
		            fname: 'get_load_log',
		            eid: EXPERIMENT_ID
		        },
		        success: function(data) {
		        	if (data)
		        		log.html(data);
		        	else
		        		log.html('Error: log file not found');
		        	setVisible(true);
		        }
		    });
		}
		else
			setVisible(true);
	}
	else
		setVisible(false);
}

function export_data() {
    // Make sure user is still logged-in
    if (!check_and_report_login())
        return;

    coge.progress.begin({
    	title: 'Exporting ...',
    	content:
    		"
Copying this experiment's data files to

" +
    		''+IRODS_HOME+'',
    	width: '30em',
    	height: '10em'
    });

    $.ajax({
        data: {
            fname: 'export_experiment_irods',
            eid: EXPERIMENT_ID
        },
        success : function(filename) {
            if (filename) {  // finished successfully
            	coge.progress.succeeded('

File: ' + filename);
            }
            else { // error occurred
                coge.progress.failed();
            }
        }
    });
}

function render_template(template, container) {
    container.empty()
        .hide()
        .append(template)
        .show();//.slideDown();
}

var snpMenu = {
    init: function() {
    	var self = this;
    	this.dialog = $('

');
    	var template = $($("#snp-template2").html());

        var options_templates = {
            coge:     $($("#coge-snp-template").html()),
            samtools: $($("#samtools-snp-template").html()),
            platypus: $($("#platypus-snp-template").html()),
            gatk:     $($("#gatk-snp-template").html())
        };

        var options_container = template.find('#snp-container');
        options_container.removeClass('hidden');

        this.method = template.find('#snp-method');
        this.method.removeAttr("disabled");

    	var render = function() {
            var selected = self.method.val();
            render_template(options_templates[selected], options_container);
            render_template(template, self.dialog);
        };

        $(document).on('change', '#snp-method', render);

        render();

    	this.dialog.dialog({
    		title: "Select SNP Analysis Options",
    		width: '35em',
    		autoOpen: false,
    		buttons: [
    	        {
    	            text: " Identify SNPs ",
    	            "class": "coge-button", //FIXME isn't working
    	            click: function() {
    	            	self.close();
    	            	setTimeout($.proxy(self.submit, self), 0);
    	            }
    	        }
    	    ]
    	});
    },

    open: function() {
    	this.dialog.dialog("open");
    },

    close: function() {
    	this.dialog.dialog("close");
    },

	is_valid: function () {
		var method = this.method.val();

		//TODO this can be automated
	    if (method === "coge") {
	        return {
	            method: method,
	            'min-read-depth':   this.dialog.find("#min-read-depth").val(),
	            'min-base-quality': this.dialog.find("#min-base-quality").val(),
	            'min-allele-count': this.dialog.find("#min-allele-count").val(),
	            'min-allele-freq':  this.dialog.find("#min-allele-freq").val(),
	            scale: this.dialog.find("#scale").val()
	        };
	    }
	    else if (method === "samtools") {
	    	return {
	            method: method,
	            'min-read-depth': this.dialog.find("#min-read-depth").val(),
	            'max-read-depth': this.dialog.find("#max-read-depth").val(),
	        };
	    }
	    else if (method === "platypus") {
	    	return {
	            method: method
	        };
	    }
	    else if (method === "gatk") {
	    	return {
	            method: method
	        };
	    }
	    return;
	},

	submit: function() {
		// Prevent concurrent executions
		//if ( $("#progress_dialog").dialog( "isOpen" ) )
		//    return;

		// Make sure user is still logged-in
		//if (!check_and_report_login())
		//    return;

		var params = this.is_valid();

		coge.progress.begin({
			title: "Identifying SNPs ...",
			width: '60%',
	    	height: '50%'
		});
		newLoad = true;

		// Build request
		var request = {
			type: 'analyze_snps',
			requester: {
				page: PAGE_NAME,
				url: PAGE_NAME + "?eid=" + EXPERIMENT_ID,
				user_name: USER_NAME
			},
			parameters: {
				eid: EXPERIMENT_ID,
				snp_params: params
			}
		};

		// Submit request
		coge.services.submit_job(request)
			.done(function(response) {
		  		if (!response) {
		  			coge.progress.failed("Error: empty response from server");
		  			return;
		  		}
		  		else if (!response.success || !response.id) {
		  			coge.progress.failed("Error: failed to start workflow");
		  			return;
		  		}

		        // Start status update
		  		window.history.pushState({}, "Title", PAGE_NAME + "?eid=" + EXPERIMENT_ID + "&wid=" + response.id); // Add workflow id to browser URL
		  		coge.progress.update(response.id, response.site_url);
		    })
		    .fail(function(jqXHR, textStatus, errorThrown) {
		    	coge.progress.failed("Couldn't talk to the server: " + textStatus + ': ' + errorThrown);
		    });
	}
}

var expressionMenu = {
    init: function() {
    	var self = this;
    	this.dialog = $('

');
    	var template = $($("#expression-template").html()).find('#expression-container');
    	template.removeClass('hidden');

    	var render = function() {
            render_template(template, self.dialog);
        };

        render();

    	this.dialog.dialog({
    		title: "Select Expression Analysis Options",
    		width: '35em',
    		autoOpen: false,
    		buttons: [
    	        {
    	            text: " Measure Expression ",
    	            "class": "coge-button", //FIXME isn't working
    	            click: function() {
    	            	self.close();
    	            	setTimeout($.proxy(self.submit, self), 0);
    	            }
    	        }
    	    ]
    	});
    },

    open: function() {
    	this.dialog.dialog("open");
    },

    close: function() {
    	this.dialog.dialog("close");
    },

	is_valid: function () {
	    return true;
	},

	submit: function() {
		// Prevent concurrent executions
		//if ( $("#progress_dialog").dialog( "isOpen" ) )
		//    return;

		// Make sure user is still logged-in
		//if (!check_and_report_login())
		//    return;

		var params = this.is_valid();

		coge.progress.begin({
			title: "Measuring Expression ...",
			width: '60%',
	    	height: '50%'
		});
		newLoad = true;

		// Build request
		var request = {
			type: 'analyze_expression',
			requester: {
				page: PAGE_NAME,
				url: PAGE_NAME + "?eid=" + EXPERIMENT_ID,
				user_name: USER_NAME
			},
			parameters: {
				eid: EXPERIMENT_ID,
				expression_params: params
			}
		};

		// Submit request
		coge.services.submit_job(request)
			.done(function(response) {
		  		if (!response) {
		  			coge.progress.failed("Error: empty response from server");
		  			return;
		  		}
		  		else if (!response.success || !response.id) {
		  			coge.progress.failed("Error: failed to start workflow");
		  			return;
		  		}

		        // Start status update
		  		window.history.pushState({}, "Title", PAGE_NAME + "?eid=" + EXPERIMENT_ID + "&wid=" + response.id); // Add workflow id to browser URL
		  		coge.progress.update(response.id, response.site_url);
		    })
		    .fail(function(jqXHR, textStatus, errorThrown) {
		    	coge.progress.failed("Couldn't talk to the server: " + textStatus + ': ' + errorThrown);
		    });
	}
}

function check_login() {
    var logged_in = false;

    $.ajax({
        async: false,
        data: {
            fname: 'check_login'
        },
        success : function(rc) {
            logged_in = rc;
        }
    });

    return logged_in;
}

function check_and_report_login() {
    if (!check_login()) {
        alert('Your session has expired, please log in again.');
        location.reload(true);
        return false;
    }
    return true;
}

function remove_experiment_type (opts) {
    etid = opts.etid;
    $.ajax({
        data: {
            fname: 'remove_experiment_type',
            eid: EXPERIMENT_ID,
            etid: etid,
        },
        success : function(val) {
            get_experiment_info();
        },
    });
}

function remove_experiment_tag (opts) {
    etid = opts.etid;
    $.ajax({
        data: {
            fname: 'remove_experiment_tag',
            eid: EXPERIMENT_ID,
            etid: etid,
        },
        success : function(val) {
            get_experiment_info();
        },
    });
}

function get_annotations() {
    $.ajax({
        data: {
            fname: 'get_annotations',
            eid: EXPERIMENT_ID,
        },
        success : function(data) {
            $('#experiment_annotations').html(data);
            set_annotation_table();
        }
    });
}

function remove_annotation (eaid) {
    $.ajax({
        data: {
            fname: 'remove_annotation',
            eid: EXPERIMENT_ID,
            eaid: eaid,
        },
        success : function() {
            get_annotations();
        },
    });
}

function get_experiment_tags () {
    $.ajax({
        data: {
            fname: 'get_experiment_tags'
        },
        success : function(val) {
            var items = jQuery.parseJSON(val);
            $("#edit_tag_name").autocomplete("option", "source", items).autocomplete("search");
        },
    });
}

function get_tag_description (name) {
    $.ajax({
        data: {
            fname: 'get_tag_description',
            name: name
        },
        success : function(data) {
            $("#edit_tag_description").html(data);
        },
    });
}<commit_msg>Resize expression options dialog<commit_after>function set_annotation_table() {
    $('#experiment_annotation_table').tablesorter({widgets: ['zebra']});
}

function get_experiment_info() {
    $.ajax({
        data: {
            fname: 'get_experiment_info',
            eid: EXPERIMENT_ID,
        },
        success : function (data) {
            $('#experiment_info').html(data);
        }
    });
}

function edit_experiment_info() {
    $.ajax({
        data: {
            fname: 'edit_experiment_info',
            eid: EXPERIMENT_ID,
        },
        success : function(data) {
            var obj = jQuery.parseJSON(data);
            $("#experiment_info_edit_box").html(obj.output).dialog('open');
        }
    });
}

function update_experiment_info () {
    var name = $('#edit_name').val();
    if (!name) {
        alert('Please specify a name.');
        return;
    }

    var version = $('#edit_version').val();
    if (!version) {
        alert('Please specify a version');
        return;
    }

    var source_id = parseInt( $('#edit_source_id').val() );
    if (!source_id) {
        alert('Please specify a source');
        return;
    }

    var desc = $('#edit_desc').val();

    $.ajax({
        data: {
            fname: 'update_experiment_info',
            eid: EXPERIMENT_ID,
            name: name,
            desc: desc,
            source_id: source_id,
            version: version
        },
        success : function(val) {
            get_experiment_info();
            $("#experiment_info_edit_box").dialog('close');
        }
    });
}

function get_sources () {
    $.ajax({
        data: {
            fname: 'get_sources'
        },
        success : function(data) {
            var items = jQuery.parseJSON(data);
            $("#edit_source").autocomplete("option", "source", items).autocomplete("search");
        }
    });
}

function make_experiment_public () {
    $.ajax({
        data: {
            fname: 'make_experiment_public',
            eid: EXPERIMENT_ID
        },
        success : function(val) {
            get_experiment_info();
        }
    });
}

function make_experiment_private () {
    $.ajax({
        data: {
            fname: 'make_experiment_private',
            eid: EXPERIMENT_ID
        },
        success : function(val) {
            get_experiment_info();
        }
    });
}

function add_experiment_type () {
    $.ajax({
        data: {
            fname: 'add_experiment_tag',
            eid: EXPERIMENT_ID
        },
        success : function(data) {
            $("#experiment_tag_edit_box").dialog({
                beforeClose:
                    function() {
                        $("#edit_tag_name").autocomplete('close');
                    }
            });
            $("#experiment_tag_edit_box").html(data).dialog('open');
        }
    });
}

function add_tag_to_experiment () {
    var name = $('#edit_tag_name').val();
    var description = $('#edit_tag_description').val();

    if (name) {
        $.ajax({
            data: {
                fname: 'add_tag_to_experiment',
                eid: EXPERIMENT_ID,
                name: name,
                description: description
            },
            success : function(val) {
                get_experiment_info();
                $("#experiment_tag_edit_box").dialog('close');
            },
        });
    }
    else { alert ('Error: Must have type name specified!');}
}

function reset_location() {
	window.history.pushState({}, "Title", PAGE_NAME + "?eid=" + EXPERIMENT_ID);
}

function download_files() {
    coge.progress.begin({
    	title: 'Preparing Download ...',
    	content: '
The download is being generated

',
    	width: '30em',
    	height: '10em'
    });

    $.ajax({
        data: {
            fname: "get_file_urls",
            eid: EXPERIMENT_ID
        },
        dataType: "json",
        success : function(json) {
            if (json.url) {  // finished successfully
                coge.progress.succeeded("File: " + json.filename);
                setTimeout(function() { coge.utils.open(json.url) }, 10);
            }
            else { // error occurred
                coge.progress.failed();
            }
        }
    });
}

function toggle_load_log() { // TODO: shared with GenomeInfo.pl, move to module
	var btn = $('#log_button');
	var log = $('#log_contents');
	var spinner = $('#log_spinner');

	var setVisible = function(visible) { // TODO: i want to use jQuery.toggle() instead, oh well
    	if (visible) {
			log.removeClass('hidden');
	    	btn.html('Hide');
	    	spinner.animate({opacity:0});
    	}
    	else {
    		log.addClass('hidden');
    		btn.html('Show');
    		spinner.animate({opacity:0});
    	}
	}

	if (log.is(":hidden")) {
		if (log.html() == '') {
			spinner.css({opacity:1});
			$.ajax({
		        data: {
		            fname: 'get_load_log',
		            eid: EXPERIMENT_ID
		        },
		        success: function(data) {
		        	if (data)
		        		log.html(data);
		        	else
		        		log.html('Error: log file not found');
		        	setVisible(true);
		        }
		    });
		}
		else
			setVisible(true);
	}
	else
		setVisible(false);
}

function export_data() {
    // Make sure user is still logged-in
    if (!check_and_report_login())
        return;

    coge.progress.begin({
    	title: 'Exporting ...',
    	content:
    		"
Copying this experiment's data files to

" +
    		''+IRODS_HOME+'',
    	width: '30em',
    	height: '10em'
    });

    $.ajax({
        data: {
            fname: 'export_experiment_irods',
            eid: EXPERIMENT_ID
        },
        success : function(filename) {
            if (filename) {  // finished successfully
            	coge.progress.succeeded('

File: ' + filename);
            }
            else { // error occurred
                coge.progress.failed();
            }
        }
    });
}

function render_template(template, container) {
    container.empty()
        .hide()
        .append(template)
        .show();//.slideDown();
}

var snpMenu = {
    init: function() {
    	var self = this;
    	this.dialog = $('

');
    	var template = $($("#snp-template2").html());

        var options_templates = {
            coge:     $($("#coge-snp-template").html()),
            samtools: $($("#samtools-snp-template").html()),
            platypus: $($("#platypus-snp-template").html()),
            gatk:     $($("#gatk-snp-template").html())
        };

        var options_container = template.find('#snp-container');
        options_container.removeClass('hidden');

        this.method = template.find('#snp-method');
        this.method.removeAttr("disabled");

    	var render = function() {
            var selected = self.method.val();
            render_template(options_templates[selected], options_container);
            render_template(template, self.dialog);
        };

        $(document).on('change', '#snp-method', render);

        render();

    	this.dialog.dialog({
    		title: "Select SNP Analysis Options",
    		width: '35em',
    		autoOpen: false,
    		buttons: [
    	        {
    	            text: " Identify SNPs ",
    	            "class": "coge-button", //FIXME isn't working
    	            click: function() {
    	            	self.close();
    	            	setTimeout($.proxy(self.submit, self), 0);
    	            }
    	        }
    	    ]
    	});
    },

    open: function() {
    	this.dialog.dialog("open");
    },

    close: function() {
    	this.dialog.dialog("close");
    },

	is_valid: function () {
		var method = this.method.val();

		//TODO this can be automated
	    if (method === "coge") {
	        return {
	            method: method,
	            'min-read-depth':   this.dialog.find("#min-read-depth").val(),
	            'min-base-quality': this.dialog.find("#min-base-quality").val(),
	            'min-allele-count': this.dialog.find("#min-allele-count").val(),
	            'min-allele-freq':  this.dialog.find("#min-allele-freq").val(),
	            scale: this.dialog.find("#scale").val()
	        };
	    }
	    else if (method === "samtools") {
	    	return {
	            method: method,
	            'min-read-depth': this.dialog.find("#min-read-depth").val(),
	            'max-read-depth': this.dialog.find("#max-read-depth").val(),
	        };
	    }
	    else if (method === "platypus") {
	    	return {
	            method: method
	        };
	    }
	    else if (method === "gatk") {
	    	return {
	            method: method
	        };
	    }
	    return;
	},

	submit: function() {
		// Prevent concurrent executions
		//if ( $("#progress_dialog").dialog( "isOpen" ) )
		//    return;

		// Make sure user is still logged-in
		//if (!check_and_report_login())
		//    return;

		var params = this.is_valid();

		coge.progress.begin({
			title: "Identifying SNPs ...",
			width: '60%',
	    	height: '50%'
		});
		newLoad = true;

		// Build request
		var request = {
			type: 'analyze_snps',
			requester: {
				page: PAGE_NAME,
				url: PAGE_NAME + "?eid=" + EXPERIMENT_ID,
				user_name: USER_NAME
			},
			parameters: {
				eid: EXPERIMENT_ID,
				snp_params: params
			}
		};

		// Submit request
		coge.services.submit_job(request)
			.done(function(response) {
		  		if (!response) {
		  			coge.progress.failed("Error: empty response from server");
		  			return;
		  		}
		  		else if (!response.success || !response.id) {
		  			coge.progress.failed("Error: failed to start workflow");
		  			return;
		  		}

		        // Start status update
		  		window.history.pushState({}, "Title", PAGE_NAME + "?eid=" + EXPERIMENT_ID + "&wid=" + response.id); // Add workflow id to browser URL
		  		coge.progress.update(response.id, response.site_url);
		    })
		    .fail(function(jqXHR, textStatus, errorThrown) {
		    	coge.progress.failed("Couldn't talk to the server: " + textStatus + ': ' + errorThrown);
		    });
	}
}

var expressionMenu = {
    init: function() {
    	var self = this;
    	this.dialog = $('

');
    	var template = $($("#expression-template").html()).find('#expression-container');
    	template.removeClass('hidden');

    	var render = function() {
            render_template(template, self.dialog);
        };

        render();

    	this.dialog.dialog({
    		title: "Select Expression Analysis Options",
    		width: '30em',
    		autoOpen: false,
    		buttons: [
    	        {
    	            text: " Measure Expression ",
    	            "class": "coge-button", //FIXME isn't working
    	            click: function() {
    	            	self.close();
    	            	setTimeout($.proxy(self.submit, self), 0);
    	            }
    	        }
    	    ]
    	});
    },

    open: function() {
    	this.dialog.dialog("open");
    },

    close: function() {
    	this.dialog.dialog("close");
    },

	is_valid: function () {
	    return true;
	},

	submit: function() {
		// Prevent concurrent executions
		//if ( $("#progress_dialog").dialog( "isOpen" ) )
		//    return;

		// Make sure user is still logged-in
		//if (!check_and_report_login())
		//    return;

		var params = this.is_valid();

		coge.progress.begin({
			title: "Measuring Expression ...",
			width: '60%',
	    	height: '50%'
		});
		newLoad = true;

		// Build request
		var request = {
			type: 'analyze_expression',
			requester: {
				page: PAGE_NAME,
				url: PAGE_NAME + "?eid=" + EXPERIMENT_ID,
				user_name: USER_NAME
			},
			parameters: {
				eid: EXPERIMENT_ID,
				expression_params: params
			}
		};

		// Submit request
		coge.services.submit_job(request)
			.done(function(response) {
		  		if (!response) {
		  			coge.progress.failed("Error: empty response from server");
		  			return;
		  		}
		  		else if (!response.success || !response.id) {
		  			coge.progress.failed("Error: failed to start workflow");
		  			return;
		  		}

		        // Start status update
		  		window.history.pushState({}, "Title", PAGE_NAME + "?eid=" + EXPERIMENT_ID + "&wid=" + response.id); // Add workflow id to browser URL
		  		coge.progress.update(response.id, response.site_url);
		    })
		    .fail(function(jqXHR, textStatus, errorThrown) {
		    	coge.progress.failed("Couldn't talk to the server: " + textStatus + ': ' + errorThrown);
		    });
	}
}

function check_login() {
    var logged_in = false;

    $.ajax({
        async: false,
        data: {
            fname: 'check_login'
        },
        success : function(rc) {
            logged_in = rc;
        }
    });

    return logged_in;
}

function check_and_report_login() {
    if (!check_login()) {
        alert('Your session has expired, please log in again.');
        location.reload(true);
        return false;
    }
    return true;
}

function remove_experiment_type (opts) {
    etid = opts.etid;
    $.ajax({
        data: {
            fname: 'remove_experiment_type',
            eid: EXPERIMENT_ID,
            etid: etid,
        },
        success : function(val) {
            get_experiment_info();
        },
    });
}

function remove_experiment_tag (opts) {
    etid = opts.etid;
    $.ajax({
        data: {
            fname: 'remove_experiment_tag',
            eid: EXPERIMENT_ID,
            etid: etid,
        },
        success : function(val) {
            get_experiment_info();
        },
    });
}

function get_annotations() {
    $.ajax({
        data: {
            fname: 'get_annotations',
            eid: EXPERIMENT_ID,
        },
        success : function(data) {
            $('#experiment_annotations').html(data);
            set_annotation_table();
        }
    });
}

function remove_annotation (eaid) {
    $.ajax({
        data: {
            fname: 'remove_annotation',
            eid: EXPERIMENT_ID,
            eaid: eaid,
        },
        success : function() {
            get_annotations();
        },
    });
}

function get_experiment_tags () {
    $.ajax({
        data: {
            fname: 'get_experiment_tags'
        },
        success : function(val) {
            var items = jQuery.parseJSON(val);
            $("#edit_tag_name").autocomplete("option", "source", items).autocomplete("search");
        },
    });
}

function get_tag_description (name) {
    $.ajax({
        data: {
            fname: 'get_tag_description',
            name: name
        },
        success : function(data) {
            $("#edit_tag_description").html(data);
        },
    });
}<|endoftext|>


<commit_before>import PricingService from './pricing-service';
import ReferenceService from './reference-service';
import BlotterService from './blotter-service';
import ExecutionService from './execution-service';
import AnalyticsService from './analytics-service';

import transport from './transport';
import emitter from '../utils/emitter';
import utils from '../utils';

const DISCONNECT_SESSION_AFTER = 1000 * 60 * 15;

/**
 * @class ReactiveTrader
 * @singleton
 */
@utils.mixin(emitter)
class ReactiveTrader {

  /**
   * @constructs ReactiveTrader
   * @param {transport} transport
   */
  constructor(transport){
    transport.isConnected || transport.open();
    this.pricing = new PricingService(transport);
    this.reference = new ReferenceService(transport);
    this.blotter = new BlotterService(transport);
    this.execution = new ExecutionService(transport);
    this.analytics = new AnalyticsService(transport);

    this.transport = transport;

    this.transport
      .on('timeout', () => this.trigger('timeout'))
      .on('open', () =>{
        this.sessionDisconnectTimer = setTimeout(() =>{
          this.trigger('timeout');
          this.transport.close();
          this.transport.markEverythingAsDead();
        }, 5000);
      });
  }

}

export default new ReactiveTrader(transport);
<commit_msg>oups, wrong timeout for disconnect<commit_after>import PricingService from './pricing-service';
import ReferenceService from './reference-service';
import BlotterService from './blotter-service';
import ExecutionService from './execution-service';
import AnalyticsService from './analytics-service';

import transport from './transport';
import emitter from '../utils/emitter';
import utils from '../utils';

const DISCONNECT_SESSION_AFTER = 1000 * 60 * 15;

/**
 * @class ReactiveTrader
 * @singleton
 */
@utils.mixin(emitter)
class ReactiveTrader {

  /**
   * @constructs ReactiveTrader
   * @param {transport} transport
   */
  constructor(transport){
    transport.isConnected || transport.open();
    this.pricing = new PricingService(transport);
    this.reference = new ReferenceService(transport);
    this.blotter = new BlotterService(transport);
    this.execution = new ExecutionService(transport);
    this.analytics = new AnalyticsService(transport);

    this.transport = transport;

    this.transport
      .on('timeout', () => this.trigger('timeout'))
      .on('open', () =>{
        this.sessionDisconnectTimer = setTimeout(() =>{
          this.trigger('timeout');
          this.transport.close();
          this.transport.markEverythingAsDead();
        }, DISCONNECT_SESSION_AFTER);
      });
  }

}

export default new ReactiveTrader(transport);
<|endoftext|>


<commit_before>(function () {

    "use strict";

    /**
     * Simple singleton
     * @type {{log: log}}
     */
    var Singleton_simple = {
        /**
         * Prints text
         * @param text {string} - text to print
         */
        log: function (text) {
            print("Simple singleton says: " + text);
        }
    };

    /**Testing*/

    Singleton_simple.log("Hello!");
    Singleton_simple.log("World!");

})();<commit_msg>Small jsdoc fix<commit_after>(function () {

    "use strict";

    /**
     * Simple singleton
     * @type {{log: Function}}
     */
    var Singleton_simple = {
        /**
         * Prints text
         * @param text {string} - text to print
         */
        log: function (text) {
            print("Simple singleton says: " + text);
        }
    };

    /**Testing*/

    Singleton_simple.log("Hello!");
    Singleton_simple.log("World!");

})();<|endoftext|>


<commit_before>(function () {
    'use strict';

    angular
        .module('app')
        .factory('Auth', Auth);

    // @ngInject
    function Auth($window, $location, $interval, $q, $localStorage, Config, Api) {

        var factory = {};
        var user = false;

        var jwtInterval;
        var jwtIntervalTime = Config.jwtIntervalTime;
        factory.startTokenRenewInterval = function(runAtStart) {
            $interval.cancel(jwtInterval);
            jwtInterval = $interval(factory.getUser, jwtIntervalTime);
            if (runAtStart) {
                factory.getUser();
            }
        };

        factory.getUser = function(useCache) {
            var userDefer = $q.defer();
            if (useCache && user !== false) {
                userDefer.resolve(user);
            } else {
                Api.get('public/renew-token').then(function(data) {
                    factory.setUserAndToken(data);
                    userDefer.resolve(user);
                });
            }
            return userDefer.promise;
        };

        factory.setUserAndToken = function(data) {
            user = null;
            delete $localStorage.user;
            delete $localStorage.token;

            // set data if valid
            if (data && data.success && data.success.user) {
                user = data.success.user;
                $localStorage.user = data.success.user;

                // set token only if we're not using cookies
                if (!Config.jwtCookie) {
                    $localStorage.token = data.success.token;
                }
            }

            // return user so we know if successful or not
            return user;
        };

        factory.setUser = function(userData) {
            user = userData;
        };

        factory.setUserFromLocalStorage = function() {
            user = $localStorage.user;
            return user;
        };

        factory.getRefreshToken = function() {
            // note: this will return nothing if the frontend client is using cookies
            return $localStorage.refreshToken;
        };

        factory.requestRefreshToken = function() {
            return Api.get('public/request-refresh-token').then(function(data) {
                if (!Config.jwtCookie) {
                    $localStorage.refreshToken = data.success;
                }
                return data;
            });
        };

        factory.removeRefreshToken = function(callApi) {
            // remove token from local storage and cookie
            delete $localStorage.refreshToken;
            if (callApi) {
                return Api.get('public/remove-refresh-token').then(function(data) {
                    return data;
                });
            }
        };

        factory.useRefreshToken = function() {
            var params = $localStorage.refreshToken ? {refreshToken: $localStorage.refreshToken} : {};
            return Api.get('public/use-refresh-token', params).then(function(data) {
                factory.setUserAndToken(data);
                if (!user) {
                    factory.removeRefreshToken();
                }
                return data;
            });
        };

        factory.getAttribute = function(attribute, defaultValue) {
            return user ? user[attribute] : defaultValue;
        };

        factory.isLoggedIn = function() {
            return user ? true : false;
        };

        factory.login = function(data) {
            return Api.post('public/login', data).then(function(data) {
                factory.setUserAndToken(data);
                return data;
            });
        };

        factory.setLoginUrl = function(url) {
            $localStorage.loginUrl = url;
            return this;
        };

        factory.clearLoginUrl = function() {
            delete $localStorage.loginUrl;
            return this;
        };

        factory.redirect = function(url) {
            url = url ? url : '';
            $location.path(url).replace();
            return this;
        };

        // get login url via (1) local storage or (2) fallbackUrl
        factory.getLoginUrl = function(fallbackUrl) {
            return $localStorage.loginUrl || fallbackUrl || '';
        };

        factory.logout = function(logoutUrl) {
            return Api.post('public/logout').then(function(data) {
                factory.setUserAndToken(data);
                factory.removeRefreshToken();
                factory.redirect(logoutUrl);
                return data;
            });
        };

        factory.register = function(data) {
            return Api.post('public/register', data).then(function(data) {
                var userCheck = factory.setUserAndToken(data);
                if (userCheck) {
                    factory.startTokenRenewInterval();
                }
                return data;
            });
        };

        // set up recaptcha
        var recaptchaDefer = $q.defer();
        $window.recaptchaLoaded = function() {
            recaptchaDefer.resolve($window.grecaptcha);
        };
        factory.getRecaptcha = function() {
            return recaptchaDefer.promise;
        };

        return factory;
    }

})();<commit_msg>remove get/search params when redirecting in angular<commit_after>(function () {
    'use strict';

    angular
        .module('app')
        .factory('Auth', Auth);

    // @ngInject
    function Auth($window, $location, $interval, $q, $localStorage, Config, Api) {

        var factory = {};
        var user = false;

        var jwtInterval;
        var jwtIntervalTime = Config.jwtIntervalTime;
        factory.startTokenRenewInterval = function(runAtStart) {
            $interval.cancel(jwtInterval);
            jwtInterval = $interval(factory.getUser, jwtIntervalTime);
            if (runAtStart) {
                factory.getUser();
            }
        };

        factory.getUser = function(useCache) {
            var userDefer = $q.defer();
            if (useCache && user !== false) {
                userDefer.resolve(user);
            } else {
                Api.get('public/renew-token').then(function(data) {
                    factory.setUserAndToken(data);
                    userDefer.resolve(user);
                });
            }
            return userDefer.promise;
        };

        factory.setUserAndToken = function(data) {
            user = null;
            delete $localStorage.user;
            delete $localStorage.token;

            // set data if valid
            if (data && data.success && data.success.user) {
                user = data.success.user;
                $localStorage.user = data.success.user;

                // set token only if we're not using cookies
                if (!Config.jwtCookie) {
                    $localStorage.token = data.success.token;
                }
            }

            // return user so we know if successful or not
            return user;
        };

        factory.setUser = function(userData) {
            user = userData;
        };

        factory.setUserFromLocalStorage = function() {
            user = $localStorage.user;
            return user;
        };

        factory.getRefreshToken = function() {
            // note: this will return nothing if the frontend client is using cookies
            return $localStorage.refreshToken;
        };

        factory.requestRefreshToken = function() {
            return Api.get('public/request-refresh-token').then(function(data) {
                if (!Config.jwtCookie) {
                    $localStorage.refreshToken = data.success;
                }
                return data;
            });
        };

        factory.removeRefreshToken = function(callApi) {
            // remove token from local storage and cookie
            delete $localStorage.refreshToken;
            if (callApi) {
                return Api.get('public/remove-refresh-token').then(function(data) {
                    return data;
                });
            }
        };

        factory.useRefreshToken = function() {
            var params = $localStorage.refreshToken ? {refreshToken: $localStorage.refreshToken} : {};
            return Api.get('public/use-refresh-token', params).then(function(data) {
                factory.setUserAndToken(data);
                if (!user) {
                    factory.removeRefreshToken();
                }
                return data;
            });
        };

        factory.getAttribute = function(attribute, defaultValue) {
            return user ? user[attribute] : defaultValue;
        };

        factory.isLoggedIn = function() {
            return user ? true : false;
        };

        factory.login = function(data) {
            return Api.post('public/login', data).then(function(data) {
                factory.setUserAndToken(data);
                return data;
            });
        };

        factory.setLoginUrl = function(url) {
            $localStorage.loginUrl = url;
            return this;
        };

        factory.clearLoginUrl = function() {
            delete $localStorage.loginUrl;
            return this;
        };

        factory.redirect = function(url) {

            // clear get params, change path, and replace record
            // @link http://stackoverflow.com/a/26336011
            // @link http://stackoverflow.com/questions/17376416/angularjs-how-to-clear-query-parameters-in-the-url
            url = url ? url : '';
            $location.search({});
            $location.path(url).replace();
            return this;
        };

        // get login url via (1) local storage or (2) fallbackUrl
        factory.getLoginUrl = function(fallbackUrl) {
            return $localStorage.loginUrl || fallbackUrl || '';
        };

        factory.logout = function(logoutUrl) {
            return Api.post('public/logout').then(function(data) {
                factory.setUserAndToken(data);
                factory.removeRefreshToken();
                factory.redirect(logoutUrl);
                return data;
            });
        };

        factory.register = function(data) {
            return Api.post('public/register', data).then(function(data) {
                var userCheck = factory.setUserAndToken(data);
                if (userCheck) {
                    factory.startTokenRenewInterval();
                }
                return data;
            });
        };

        // set up recaptcha
        var recaptchaDefer = $q.defer();
        $window.recaptchaLoaded = function() {
            recaptchaDefer.resolve($window.grecaptcha);
        };
        factory.getRecaptcha = function() {
            return recaptchaDefer.promise;
        };

        return factory;
    }

})();<|endoftext|>


<commit_before>tQuery.registerStatic('createSkymap', function(opts){
	// handle parameters polymorphisms
	if( typeof(opts) === 'string' )	opts	= {textureCube: opts};
	// handle parameters
	opts	= tQuery.extend(opts, {
		cubeW		: 1000,
		cubeH		: 1000,
		cubeD		: 1000
	});
	console.assert(opts.textureCube);

	var textureCube	= tQuery.createCubeTexture(opts.textureCube);

	var shader	= THREE.ShaderUtils.lib[ "cube" ];
	shader.uniforms[ "tCube" ].value	= textureCube;

	var material = new THREE.ShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: shader.uniforms,
		depthWrite	: false,
		side		: THREE.BackSide
	});

	var geometry	= new THREE.CubeGeometry( opts.cubeW, opts.cubeH, opts.cubeD );
	var mesh	= new THREE.Mesh(geometry, material );

	return tQuery(mesh);
});<commit_msg>added THREE.texture in tQuery.createSkymap polymorphism<commit_after>tQuery.registerStatic('createSkymap', function(opts){
	// handle parameters polymorphisms
	if( typeof(opts) === 'string' )		opts	= {textureCube: opts};
	if( opts instanceof THREE.Texture )	opts	= {textureCube: opts};
	// handle parameters
	opts	= tQuery.extend(opts, {
		cubeW		: 1000,
		cubeH		: 1000,
		cubeD		: 1000
	});
	console.assert(opts.textureCube);

	var textureCube	= tQuery.createCubeTexture(opts.textureCube);

	var shader	= THREE.ShaderUtils.lib[ "cube" ];
	shader.uniforms[ "tCube" ].value	= textureCube;

	var material = new THREE.ShaderMaterial({
		fragmentShader	: shader.fragmentShader,
		vertexShader	: shader.vertexShader,
		uniforms	: shader.uniforms,
		depthWrite	: false,
		side		: THREE.BackSide
	});

	var geometry	= new THREE.CubeGeometry( opts.cubeW, opts.cubeH, opts.cubeD );
	var mesh	= new THREE.Mesh(geometry, material );

	return tQuery(mesh);
});<|endoftext|>


<commit_before>const cv = global.dut;
const {
  readTestImage,
  funcShouldRequireArgs
} = global.utils;

const { expect } = require('chai');

const expectImplementsMethods = (tracker) => {
  expect(tracker).to.have.property('clear').to.be.a('function');
  expect(tracker).to.have.property('init').to.be.a('function');
  expect(tracker).to.have.property('update').to.be.a('function');
  expect(tracker).to.have.property('getModel').to.be.a('function');
};

const TrackerTestGenerator = getTestImg => (trackerName) => {
  const newTracker = () => new cv[trackerName]();
  const newTrackerParams = () => new cv[`${trackerName}Params`]();

  describe(trackerName, () => {
    describe('constructor', () => {
      it('can be constructed with default params', () => {
        expectImplementsMethods(newTracker());
      });

      if (['TrackerBoosting', 'TrackerKCF', 'TrackerMIL'].some(name => name === trackerName)) {
        it('can be constructed with params', () => {
          expectImplementsMethods(newTracker(newTrackerParams()));
        });
      } else if (trackerName === 'TrackerMedianFlow') {
        it('can be constructed with params', () => {
          const pointsInGrid = 10;
          expectImplementsMethods(newTracker(pointsInGrid));
        });
      }
    });

    describe('init', () => {
      funcShouldRequireArgs(() => (newTracker()).init());

      it('can be called with frame and initial box', () => {
        const ret = newTracker().init(getTestImg(), new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });
    });

    describe('update', () => {
      funcShouldRequireArgs(() => (newTracker()).update());

      it('returns bounding box', () => {
        const tracker = newTracker();
        tracker.init(getTestImg(), new cv.Rect(0, 0, 10, 10));
        const rect = tracker.update(getTestImg());
        expect(rect).to.be.instanceOf(cv.Rect);
      });
    });

    describe('getModel', () => {

    });
  });
};

module.exports = () => {
  let testImg;

  before(() => {
    testImg = readTestImage();
  });

  const generateTrackerTests = TrackerTestGenerator(() => testImg);

  const trackerNames = [
    'TrackerBoosting',
    'TrackerMedianFlow',
    'TrackerMIL',
    'TrackerTLD'
  ];

  if (cv.version.minor > 0) {
    trackerNames.push('TrackerKCF');
  }

  if (cv.version.minor > 1) {
    // trackerNames.push('TrackerGOTURN'); TODO: sample goturn.prototxt
  }

  trackerNames.forEach((trackerName) => {
    generateTrackerTests(trackerName);
  });

  (cv.version.minor > 0 ? describe : describe.skip)('MultiTracker', () => {
    describe('add', () => {
      it('addMIL', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addMIL(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addBOOSTING', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addBOOSTING(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addMEDIANFLOW', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addMEDIANFLOW(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addTLD', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addTLD(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addKCF', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addKCF(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });
    });

    describe('update', () => {
      funcShouldRequireArgs(() => (new cv.MultiTracker()).update());

      it('returns bounding box', () => {
        const tracker = new cv.MultiTracker();
        ['addMIL', 'addBOOSTING', 'addMEDIANFLOW', 'addTLD', 'addKCF'].forEach((addMethod) => {
          tracker[addMethod](testImg, new cv.Rect(0, 0, 10, 10));
        });
        const rects = tracker.update(testImg);
        expect(rects).to.be.an('array').lengthOf(5);
        rects.forEach((rect) => {
          expect(rect).to.be.instanceOf(cv.Rect);
        });
      });
    });
  });
};
<commit_msg>fixed flaky medianflow tracker test<commit_after>const cv = global.dut;
const {
  readTestImage,
  funcShouldRequireArgs
} = global.utils;

const { expect } = require('chai');

const expectImplementsMethods = (tracker) => {
  expect(tracker).to.have.property('clear').to.be.a('function');
  expect(tracker).to.have.property('init').to.be.a('function');
  expect(tracker).to.have.property('update').to.be.a('function');
  expect(tracker).to.have.property('getModel').to.be.a('function');
};

const TrackerTestGenerator = getTestImg => (trackerName) => {
  const newTracker = () => new cv[trackerName]();
  const newTrackerParams = () => new cv[`${trackerName}Params`]();

  describe(trackerName, () => {
    describe('constructor', () => {
      it('can be constructed with default params', () => {
        expectImplementsMethods(newTracker());
      });

      if (['TrackerBoosting', 'TrackerKCF', 'TrackerMIL'].some(name => name === trackerName)) {
        it('can be constructed with params', () => {
          expectImplementsMethods(newTracker(newTrackerParams()));
        });
      } else if (trackerName === 'TrackerMedianFlow') {
        it('can be constructed with params', () => {
          const pointsInGrid = 10;
          expectImplementsMethods(newTracker(pointsInGrid));
        });
      }
    });

    describe('init', () => {
      funcShouldRequireArgs(() => (newTracker()).init());

      it('can be called with frame and initial box', () => {
        const ret = newTracker().init(getTestImg(), new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });
    });

    describe('update', () => {
      funcShouldRequireArgs(() => (newTracker()).update());

      it('returns bounding box', () => {
        const tracker = newTracker();
        tracker.init(getTestImg(), new cv.Rect(0, 0, 10, 10));
        const rect = tracker.update(getTestImg());
        if (rect !== null) {
          expect(rect).to.be.instanceOf(cv.Rect);
        }
      });
    });

    describe('getModel', () => {

    });
  });
};

module.exports = () => {
  let testImg;

  before(() => {
    testImg = readTestImage();
  });

  const generateTrackerTests = TrackerTestGenerator(() => testImg);

  const trackerNames = [
    'TrackerBoosting',
    'TrackerMedianFlow',
    'TrackerMIL',
    'TrackerTLD'
  ];

  if (cv.version.minor > 0) {
    trackerNames.push('TrackerKCF');
  }

  if (cv.version.minor > 1) {
    // trackerNames.push('TrackerGOTURN'); TODO: sample goturn.prototxt
  }

  trackerNames.forEach((trackerName) => {
    generateTrackerTests(trackerName);
  });

  (cv.version.minor > 0 ? describe : describe.skip)('MultiTracker', () => {
    describe('add', () => {
      it('addMIL', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addMIL(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addBOOSTING', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addBOOSTING(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addMEDIANFLOW', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addMEDIANFLOW(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addTLD', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addTLD(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });

      it('addKCF', () => {
        const tracker = new cv.MultiTracker();
        const ret = tracker.addKCF(testImg, new cv.Rect(0, 0, 10, 10));
        expect(ret).to.true;
      });
    });

    describe('update', () => {
      funcShouldRequireArgs(() => (new cv.MultiTracker()).update());

      it('returns bounding box', () => {
        const tracker = new cv.MultiTracker();
        ['addMIL', 'addBOOSTING', 'addMEDIANFLOW', 'addTLD', 'addKCF'].forEach((addMethod) => {
          tracker[addMethod](testImg, new cv.Rect(0, 0, 10, 10));
        });
        const rects = tracker.update(testImg);
        expect(rects).to.be.an('array').lengthOf(5);
        rects.forEach((rect) => {
          expect(rect).to.be.instanceOf(cv.Rect);
        });
      });
    });
  });
};
<|endoftext|>


<commit_before>/**
 * plugin.js
 *
 * Copyright, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/*global tinymce:true */

tinymce.PluginManager.add('nonbreaking', function(editor) {
	editor.addCommand('mceNonBreaking', function() {
		editor.insertContent(
			(editor.plugins.visualchars && editor.plugins.visualchars.state) ?
			' ' : ' '
		);
	});

	editor.addButton('nonbreaking', {
		title: 'Insert nonbreaking space',
		cmd: 'mceNonBreaking'
	});

	editor.addMenuItem('nonbreaking', {
		text: 'Nonbreaking space',
		cmd: 'mceNonBreaking',
		context: 'insert'
	});

	if (editor.getParam('nonbreaking_force_tab')) {
		editor.on('keydown', function(e) {
			if (e.keyCode == 9) {
				e.preventDefault();

				editor.execCommand('mceNonBreaking');
				editor.execCommand('mceNonBreaking');
				editor.execCommand('mceNonBreaking');
			}
		});
	}
});
<commit_msg>Change nonbreaking_force_tab configuration option<commit_after>/**
 * plugin.js
 *
 * Copyright, Moxiecode Systems AB
 * Released under LGPL License.
 *
 * License: http://www.tinymce.com/license
 * Contributing: http://www.tinymce.com/contributing
 */

/*global tinymce:true */

tinymce.PluginManager.add('nonbreaking', function(editor) {
	var setting = editor.getParam('nonbreaking_force_tab');

	editor.addCommand('mceNonBreaking', function() {
		editor.insertContent(
			(editor.plugins.visualchars && editor.plugins.visualchars.state) ?
			' ' : ' '
		);
	});

	editor.addButton('nonbreaking', {
		title: 'Insert nonbreaking space',
		cmd: 'mceNonBreaking'
	});

	editor.addMenuItem('nonbreaking', {
		text: 'Nonbreaking space',
		cmd: 'mceNonBreaking',
		context: 'insert'
	});

	if (setting) {
		var spaces = +setting > 1 ? +setting : 3;  // defaults to 3 spaces if setting is true (or 1)

		editor.on('keydown', function(e) {
			if (e.keyCode == 9) {

				if (e.shiftKey) {
					return;
				}

				e.preventDefault();
				for (var i = 0; i < spaces; i++) {
					editor.execCommand('mceNonBreaking');
				}
			}
		});
	}
});
<|endoftext|>


<commit_before>
import DBFactory from "../../compiled/DBFactory"
import DatabaseSchema from "../../compiled/schema/DatabaseSchema"
import ObjectStoreSchema from "../../compiled/schema/ObjectStoreSchema"

describe("ReadOnlyTransaction", () => {

  const DB_NAME = "testing database"
  const OBJECT_STORE_NAME = "fooBar"

  let database
  let transaction

  beforeEach((done) => {
    DBFactory.open(DB_NAME,
      new DatabaseSchema(1,
        new ObjectStoreSchema(OBJECT_STORE_NAME)
      )
    ).then((databaseInstance) => {
      database = databaseInstance
      transaction = database.startReadOnlyTransaction(OBJECT_STORE_NAME)
      done()
    }).catch((error) => fail(error))
  })

  afterEach((done) => {
    database.close()

    let request = indexedDB.deleteDatabase(DB_NAME)
    request.onsuccess = () => done()
    request.onerror = () => fail(request.error)
  })

  it("should provide promise resolved on completion", (done) => {
    transaction.completionPromise.
        then(done).
        catch(error => fail(error))
  })

  it("should provide promise rejected on abort", (done) => {
    transaction.completionPromise.
        then(() => fail("The transaction cannot complete if aborted")).
        catch(() => done())

    transaction.abort()
  })

  it("should provide promise rejected on error", (done) => {
    let transaction = database.startTransaction(OBJECT_STORE_NAME)
    transaction.completionPromise.
        then(() => fail("The transaction cannot complete if error occurrs")).
        catch(() => done())

    let objectStore = transaction.getObjectStore(OBJECT_STORE_NAME)
    objectStore.add(null, 1).then(() => {
      objectStore.add(null, 1)
    })
  })

  it("should execute completion listeners", (done) => {
    transaction.addCompleteListener(() => done())
  })

  it("should execute abort listeners on abort", (done) => {
    transaction.addAbortListener(() => done())

    transaction.abort()
  })

  it("should execute error listeners on error", (done) => {
    let transaction = database.startTransaction(OBJECT_STORE_NAME)
    transaction.addErrorListener(() => done())

    let objectStore = transaction.getObjectStore(OBJECT_STORE_NAME)
    objectStore.add(null, 1).then(() => {
      objectStore.add(null, 1)
    })
  })

  it("it should provide access to object stores", (done) => {
    let objectStore = transaction.getObjectStore(OBJECT_STORE_NAME)

    objectStore.count().then((count) => {
      expect(count).toBe(0)
      done()
    }).catch(error => fail(error))
  })

})
<commit_msg>updated the transaction test to prevent the expected errors to leak to the console<commit_after>
import DBFactory from "../../compiled/DBFactory"
import DatabaseSchema from "../../compiled/schema/DatabaseSchema"
import ObjectStoreSchema from "../../compiled/schema/ObjectStoreSchema"

describe("ReadOnlyTransaction", () => {

  const DB_NAME = "testing database"
  const OBJECT_STORE_NAME = "fooBar"

  let database
  let transaction

  beforeEach((done) => {
    DBFactory.open(DB_NAME,
      new DatabaseSchema(1,
        new ObjectStoreSchema(OBJECT_STORE_NAME)
      )
    ).then((databaseInstance) => {
      database = databaseInstance
      transaction = database.startReadOnlyTransaction(OBJECT_STORE_NAME)
      done()
    }).catch((error) => fail(error))
  })

  afterEach((done) => {
    database.close()

    let request = indexedDB.deleteDatabase(DB_NAME)
    request.onsuccess = () => done()
    request.onerror = () => fail(request.error)
  })

  it("should provide promise resolved on completion", (done) => {
    transaction.completionPromise.
        then(done).
        catch(error => fail(error))
  })

  it("should provide promise rejected on abort", (done) => {
    transaction.completionPromise.
        then(() => fail("The transaction cannot complete if aborted")).
        catch(() => done())

    transaction.abort()
  })

  it("should provide promise rejected on error", (done) => {
    let transaction = database.startTransaction(OBJECT_STORE_NAME)
    transaction.completionPromise.
        then(() => fail("The transaction cannot complete if error occurrs")).
        catch(() => done())

    let objectStore = transaction.getObjectStore(OBJECT_STORE_NAME)
    objectStore.add(null, 1).then(() => {
      objectStore.add(null, 1).
          catch(() => {})
    })
  })

  it("should execute completion listeners", (done) => {
    transaction.addCompleteListener(() => done())
  })

  it("should execute abort listeners on abort", (done) => {
    transaction.addAbortListener(() => done())
    transaction.completionPromise.catch(() => {})

    transaction.abort()
  })

  it("should execute error listeners on error", (done) => {
    let transaction = database.startTransaction(OBJECT_STORE_NAME)
    transaction.addErrorListener(() => done())
    transaction.completionPromise.catch(() => {})

    let objectStore = transaction.getObjectStore(OBJECT_STORE_NAME)
    objectStore.add(null, 1).then(() => {
      objectStore.add(null, 1).
          catch(() => {})
    })
  })

  it("it should provide access to object stores", (done) => {
    let objectStore = transaction.getObjectStore(OBJECT_STORE_NAME)

    objectStore.count().then((count) => {
      expect(count).toBe(0)
      done()
    }).catch(error => fail(error))
  })

})
<|endoftext|>


<commit_before>/**
 * Alloy
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * See LICENSE for more information on licensing.
 */

exports.cliVersion = '>=3.X';

exports.init = function (logger, config, cli, appc) {
	var path = require('path'),
		fs = require('fs'),
		afs = appc.fs,
		i18n = appc.i18n(__dirname),
		__ = i18n.__,
		__n = i18n.__n,
		pkginfo = appc.pkginfo.package(module),
		exec = require('child_process').exec,
		spawn = require('child_process').spawn,
		parallel = appc.async.parallel;

	function run(deviceFamily, deployType, target, finished) {
		var appDir = path.join(cli.argv['project-dir'], 'app');
		if (!afs.exists(appDir)) {
			logger.info(__('Project not an Alloy app, continuing'));
			finished();
			return;
		}
		logger.info(__('Found Alloy app in %s', appDir.cyan));

		// TODO: Make this check specific to a TiSDK version
		// create a .alloynewcli file to tell old plugins not to run
		var buildDir = path.join(cli.argv['project-dir'], 'build');
		if (!afs.exists(buildDir)) {
			fs.mkdirSync(buildDir);
		}
		fs.writeFileSync(path.join(buildDir, '.alloynewcli'), '');

		var cRequire = afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js'),
			config = {
				platform: /(?:iphone|ipad)/.test(cli.argv.platform) ? 'ios' : cli.argv.platform,
				version: '0',
				simtype: 'none',
				devicefamily: /(?:iphone|ios)/.test(cli.argv.platform) ? deviceFamily : 'none',
				deploytype: deployType || cli.argv['deploy-type'] || 'development',
				target: target
			};

		config = Object.keys(config).map(function (c) {
			return c + '=' + config[c];
		}).join(',');

		if (afs.exists(cRequire)) {
			// we're being invoked from the actual alloy directory!
			// no need to subprocess, just require() and run
			var origLimit = Error.stackTraceLimit;
			Error.stackTraceLimit = Infinity;
			try {
				require(cRequire)({}, {
					config: config,
					outputPath: cli.argv['project-dir'],
					_version: pkginfo.version
				});
			} catch (e) {
				logger.error(__('Alloy compiler failed'));
				e.toString().split('\n').forEach(function (line) {
					if (line) { logger.error(line); }
				});
				process.exit(1);
			}
			Error.stackTraceLimit = origLimit;
			finished();
		} else {
			// we have no clue where alloy is installed, so we're going to subprocess
			// alloy and hope it's in the system path or a well known place
			var paths = {};
			parallel(this, ['alloy', 'node'].map(function (bin) {
				return function (done) {
					var envName = 'ALLOY_' + (bin === 'node' ? 'NODE_' : '') + 'PATH';

					paths[bin] = process.env[envName];
					if (paths[bin]) {
						done();
					} else if (process.platform === 'win32') {
						paths.alloy = 'alloy.cmd';
						done();
					} else {
						exec('which ' + bin, function (err, stdout, strerr) {
							if (!err) {
								paths[bin] = stdout.trim();
								done();
							} else {
								parallel(this, [
									'/usr/local/bin/' + bin,
									'/opt/local/bin/' + bin,
									path.join(process.env.HOME, 'local/bin', bin),
									'/opt/bin/' + bin,
									'/usr/bin/' + bin
								].map(function (p) {
									return function (cb) {
										if (afs.exists(p)) { paths[bin] = p; }
										cb();
									};
								}), done);
							}
						});
					}
				};
			}), function () {
				var cmd = [paths.node, paths.alloy, 'compile', appDir, '--config', config];
				if (cli.argv['no-colors']) { cmd.push('--no-colors'); }
				if (process.platform === 'win32') { cmd.shift(); }
				logger.info(__('Executing Alloy compile: %s', cmd.join(' ').cyan));

				var child = spawn(cmd.shift(), cmd);

				function checkLine(line) {
					var re = new RegExp(
						'(?:\u001b\\[\\d+m)?\\[?(' +
						logger.getLevels().join('|') +
						')\\]?\s*(?:\u001b\\[\\d+m)?(.*)', 'i'
					);
					if (line) {
						var m = line.match(re);
						if (m) {
							logger[m[1].toLowerCase()](m[2].trim());
						} else {
							logger.debug(line);
						}
					}
				}

				child.stdout.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						checkLine(line);
					});
				});
				child.stderr.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						checkLine(line);
					});
				});
				child.on('exit', function (code) {
					if (code) {
						logger.error(__('Alloy compiler failed'));
						process.exit(1);
					} else {
						logger.info(__('Alloy compiler completed successfully'));
					}
					finished();
				});
			});
		}
	}

	cli.addHook('build.pre.compile', function (build, finished) {
		// TODO: Remove this workaround when the CLI reports the right deploy type for android
		var deployType = build.deployType;
		var target = build.target;

		if (cli.argv.platform === 'android') {
			switch(target) {
				case 'dist-playstore':
					deployType = 'production';
					break;
				case 'device':
					deployType = 'test';
					break;
				case 'emulator':
				default:
					deployType = 'development';
					break;
			}
		}
		run(build.deviceFamily, deployType, target, finished);
	});

	cli.addHook('codeprocessor.pre.run', function (build, finished) {
		run('none', 'development', undefined, finished);
	});
};
<commit_msg>alloy 버전을 1.3.1로 변경<commit_after>/**
 * Alloy
 * Copyright (c) 2012 by Appcelerator, Inc. All Rights Reserved.
 * See LICENSE for more information on licensing.
 */

exports.cliVersion = '>=3.X';

exports.init = function (logger, config, cli, appc) {
	var path = require('path'),
		fs = require('fs'),
		afs = appc.fs,
		i18n = appc.i18n(__dirname),
		__ = i18n.__,
		__n = i18n.__n,
		pkginfo = appc.pkginfo.package(module),
		exec = require('child_process').exec,
		spawn = require('child_process').spawn,
		parallel = appc.async.parallel;

	function run(deviceFamily, deployType, finished) {
		var appDir = path.join(cli.argv['project-dir'], 'app');
		if (!afs.exists(appDir)) {
			logger.info(__('Project not an Alloy app, continuing'));
			finished();
			return;
		}
		logger.info(__('Found Alloy app in %s', appDir.cyan));

		// TODO: Make this check specific to a TiSDK version
		// create a .alloynewcli file to tell old plugins not to run
		var buildDir = path.join(cli.argv['project-dir'], 'build');
		if (!afs.exists(buildDir)) {
			fs.mkdirSync(buildDir);
		}
		fs.writeFileSync(path.join(buildDir, '.alloynewcli'), '');

		var cRequire = afs.resolvePath(__dirname, '..', 'Alloy', 'commands', 'compile', 'index.js'),
			config = {
				platform: /(?:iphone|ipad)/.test(cli.argv.platform) ? 'ios' : cli.argv.platform,
				version: '0',
				simtype: 'none',
				devicefamily: /(?:iphone|ios)/.test(cli.argv.platform) ? deviceFamily : 'none',
				deploytype: deployType || cli.argv['deploy-type'] || 'development'
			};

		config = Object.keys(config).map(function (c) {
			return c + '=' + config[c];
		}).join(',');

		if (afs.exists(cRequire)) {
			// we're being invoked from the actual alloy directory!
			// no need to subprocess, just require() and run
			var origLimit = Error.stackTraceLimit;
			Error.stackTraceLimit = Infinity;
			try {
				require(cRequire)({}, {
					config: config,
					outputPath: cli.argv['project-dir'],
					_version: pkginfo.version
				});
			} catch (e) {
				logger.error(__('Alloy compiler failed'));
				e.toString().split('\n').forEach(function (line) {
					if (line) { logger.error(line); }
				});
				process.exit(1);
			}
			Error.stackTraceLimit = origLimit;
			finished();
		} else {
			// we have no clue where alloy is installed, so we're going to subprocess
			// alloy and hope it's in the system path or a well known place
			var paths = {};
			parallel(this, ['alloy', 'node'].map(function (bin) {
				return function (done) {
					var envName = 'ALLOY_' + (bin === 'node' ? 'NODE_' : '') + 'PATH';

					paths[bin] = process.env[envName];
					if (paths[bin]) {
						done();
					} else if (process.platform === 'win32') {
						paths.alloy = 'alloy.cmd';
						done();
					} else {
						exec('which ' + bin, function (err, stdout, strerr) {
							if (!err) {
								paths[bin] = stdout.trim();
								done();
							} else {
								parallel(this, [
									'/usr/local/bin/' + bin,
									'/opt/local/bin/' + bin,
									path.join(process.env.HOME, 'local/bin', bin),
									'/opt/bin/' + bin,
									'/usr/bin/' + bin
								].map(function (p) {
									return function (cb) {
										if (afs.exists(p)) { paths[bin] = p; }
										cb();
									};
								}), done);
							}
						});
					}
				};
			}), function () {
				var cmd = [paths.node, paths.alloy, 'compile', appDir, '--config', config];
				if (cli.argv['no-colors']) { cmd.push('--no-colors'); }
				if (process.platform === 'win32') { cmd.shift(); }
				logger.info(__('Executing Alloy compile: %s', cmd.join(' ').cyan));

				var child = spawn(cmd.shift(), cmd);

				function checkLine(line) {
					var re = new RegExp(
						'(?:\u001b\\[\\d+m)?\\[?(' +
						logger.getLevels().join('|') +
						')\\]?\s*(?:\u001b\\[\\d+m)?(.*)', 'i'
					);
					if (line) {
						var m = line.match(re);
						if (m) {
							logger[m[1].toLowerCase()](m[2].trim());
						} else {
							logger.debug(line);
						}
					}
				}

				child.stdout.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						checkLine(line);
					});
				});
				child.stderr.on('data', function (data) {
					data.toString().split('\n').forEach(function (line) {
						checkLine(line);
					});
				});
				child.on('exit', function (code) {
					if (code) {
						logger.error(__('Alloy compiler failed'));
						process.exit(1);
					} else {
						logger.info(__('Alloy compiler completed successfully'));
					}
					finished();
				});
			});
		}
	}

	cli.addHook('build.pre.compile', function (build, finished) {
		// TODO: Remove this workaround when the CLI reports the right deploy type for android
		var deployType = build.deployType;
		if (cli.argv.platform === 'android') {
			switch(cli.argv.target) {
				case 'dist-playstore':
					deployType = 'production';
					break;
				case 'device':
					deployType = 'test';
					break;
				case 'emulator':
				default:
					deployType = 'development';
					break;
			}
		}
		run(build.deviceFamily, deployType, finished);
	});

	cli.addHook('codeprocessor.pre.run', function (build, finished) {
		run('none', 'development', finished);
	});
};
<|endoftext|>


<commit_before>$(document).ready(function () {
    topnavbar();
    const queryString = window.location.search;
    const urlParams = new URLSearchParams(queryString);
    var url = baseApiUrl + "/books_read";
    if (urlParams.has("year")) {
        $.ajaxSetup({async: false});  // suppress async so the summary row is always at the bottom
        const year = urlParams.get('year');
        url = url + "/" + year
        var url1 = baseApiUrl + "/summary_books_read_by_year/" + year;
    }
    var idArray;
    $.getJSON(url, function (data) {
        var obj = data['data'];
        idArray = obj.map(function(x) {
            return x[0];
        });
        for (var i = 0; i < obj.length; i++) {
            var tr = "
" +
                "<button onclick=\"setval(" + obj[i][0] + ")\">" + obj[i][0].toString() + "</button>	" +
                "" + obj[i][1] + "	" +
                "" + obj[i][2] + "	" +
                "" + obj[i][3] + "	" +
                "" + obj[i][7] + "	" +
                "" + obj[i][13] + "
";
            $("#mytable").append(tr);
        }
    });
    if (urlParams.has("year")) {
        $.getJSON(url1, function (data) {
            var obj = data['data'];
            for (var i = 0; i < obj.length; i++) {
                var tr = "
" +
                    "" + obj[i][0] + "				" +
                    "" + obj[i][1] + "	" +
                    "" + obj[i][2] + "
";
                $("#mytable").append(tr);
            }
        });
    };
    const idArrayURLEnc = idArray.map(function(x) {return "idArray=" + x.toString();}).join("&");
    console.log(idArray);
    console.log(idArrayURLEnc);
    document.getElementById("updatereadnotesurl").innerHTML = '' +
        'Update book read notes for items in this list';
    createDetailTableRows();
});<commit_msg>fixed conditional async<commit_after>$(document).ready(function () {
    topnavbar();
    const queryString = window.location.search;
    const urlParams = new URLSearchParams(queryString);
    var url = baseApiUrl + "/books_read";
    $.ajaxSetup({async: false});  // suppress async so the summary row is always at the bottom
    if (urlParams.has("year")) {
        const year = urlParams.get('year');
        url = url + "/" + year
        const url1 = baseApiUrl + "/summary_books_read_by_year/" + year;
        $.getJSON(url1, function (data) {
            var obj = data['data'];
            for (var i = 0; i < obj.length; i++) {
                var tr = "
" +
                    "" + obj[i][0] + "				" +
                    "" + obj[i][1] + "	" +
                    "" + obj[i][2] + "
";
                $("#mytable").append(tr);
            }
        });
    }
    var idArray;
    $.getJSON(url, function (data) {
        var obj = data['data'];
        idArray = obj.map(function(x) {
            return x[0];
        });
        for (var i = 0; i < obj.length; i++) {
            var tr = "
" +
                "<button onclick=\"setval(" + obj[i][0] + ")\">" + obj[i][0].toString() + "</button>	" +
                "" + obj[i][1] + "	" +
                "" + obj[i][2] + "	" +
                "" + obj[i][3] + "	" +
                "" + obj[i][7] + "	" +
                "" + obj[i][13] + "
";
            $("#mytable").append(tr);
        }
    });
    const idArrayURLEnc = idArray.map(function(x) {return "idArray=" + x.toString();}).join("&");
    console.log(idArray);
    console.log(idArrayURLEnc);
    document.getElementById("updatereadnotesurl").innerHTML = '' +
        'Update book read notes for items in this list';
    createDetailTableRows();
});<|endoftext|>


<commit_before>import Realm from 'realm';

import { getTotal } from '../utilities';

export class StocktakeItem extends Realm.Object {
  destructor(database) {
    if (this.stocktake && this.stocktake.isFinalised) {
      throw new Error('Cannot delete a StocktakeItem belonging to a finalised stocktake');
    }
    database.delete('StocktakeBatch', this.batches);
  }

  get snapshotTotalQuantity() {
    return getTotal(this.batches, 'snapshotTotalQuantity');
  }

  get itemId() {
    return this.item ? this.item.id : '';
  }

  get itemName() {
    return this.item ? this.item.name : '';
  }

  get itemCode() {
    return this.item ? this.item.code : '';
  }

  get numberOfBatches() {
    return this.batches.length;
  }

  /**
   * If the stock has increased or not been changed since the item quantity was
   * snapshot, the minimum is 0. If the stock has reduced since the item was
   * snapshot, the minimum total quantity that can be sensibly considered as the
   * counted quantity is the snapshot quantity minus the current stock on hand.
   * This is because it doesn't make sense to count an amount that represents a
   * reduction greater than the current stock on hand, which would create negative
   * inventory.
   * @return {integer} The minimum total quantity that can be sensibly counted
   */
  get minimumTotalQuantity() {
    return this.item ? Math.max(0, this.snapshotTotalQuantity - this.item.totalQuantity) : 0;
  }

  /**
   * Returns true if this stocktake item's counted quantity would reduce the amount
   * of stock in inventory to negative levels, if it were finalised. This can happen
   * if, for example, an item is added to a stocktake with a snapshot quantity of
   * 10, then is counted to have a quantity of 8, but concurrently there has been
   * a reduction in the stock in inventory, e.g. a customer invoice for 9. In this
   * example, the stock on hand is now 1, so a reduction of 2 caused by this stocktake
   * item would result in negative inventory.
   * @return {Boolean} Whether the counted quantity is below the minimum for this item
   */
  get isReducedBelowMinimum() {
    return this.countedTotalQuantity < this.minimumTotalQuantity;
  }

  addBatch(stocktakeBatch) {
    this.batches.push(stocktakeBatch);
    if (!this.countedTotalQuantity) this.countedTotalQuantity = stocktakeBatch.countedTotalQuantity;
    else this.countedTotalQuantity += stocktakeBatch.countedTotalQuantity;
  }

  /**
   * Applies the adjustments to batches in the given transaction item to the batches
   * in this stocktake item
   * @param  {Realm}   database        App wide database
   * @param  {object}  transactionItem The transaction item
   * @return {none}
   */
  applyBatchAdjustments(database, transactionItem) {
    this.batches.forEach((stocktakeBatch) => {
      const transactionBatch = transactionItem.getBatch(stocktakeBatch.itemBatchId);
      let difference = 0;
      if (transactionBatch) { // If a matching transaction batch, work out the difference
        difference = transactionItem.transaction.isIncoming ?
                            transactionBatch.totalQuantity :
                            -transactionBatch.totalQuantity;
      }
      stocktakeBatch.countedTotalQuantity = stocktakeBatch.snapshotTotalQuantity + difference;
      database.save('StocktakeBatch', stocktakeBatch);
    });
  }

  /**
   * Deletes any batches from this stocktake item that had no stock and did not change
   * @param  {Realm} database  App wide database
   * @return {none}
   */
  pruneBatches(database) {
    database.delete(
      'StocktakeBatch',
      this.batches.filtered('snapshotNumberOfPacks == 0 AND countedNumberOfPacks == 0')
    );
  }
}

StocktakeItem.schema = {
  name: 'StocktakeItem',
  primaryKey: 'id',
  properties: {
    id: 'string',
    item: 'Item',
    stocktake: 'Stocktake',
    countedTotalQuantity: { type: 'double', optional: true },
    batches: { type: 'list', objectType: 'StocktakeBatch' },
  },
};
<commit_msg>Ensure no stocktake finalise error if not counted<commit_after>import Realm from 'realm';

import { getTotal } from '../utilities';

export class StocktakeItem extends Realm.Object {
  destructor(database) {
    if (this.stocktake && this.stocktake.isFinalised) {
      throw new Error('Cannot delete a StocktakeItem belonging to a finalised stocktake');
    }
    database.delete('StocktakeBatch', this.batches);
  }

  get snapshotTotalQuantity() {
    return getTotal(this.batches, 'snapshotTotalQuantity');
  }

  get itemId() {
    return this.item ? this.item.id : '';
  }

  get itemName() {
    return this.item ? this.item.name : '';
  }

  get itemCode() {
    return this.item ? this.item.code : '';
  }

  get numberOfBatches() {
    return this.batches.length;
  }

  /**
   * If the stock has increased or not been changed since the item quantity was
   * snapshot, the minimum is 0. If the stock has reduced since the item was
   * snapshot, the minimum total quantity that can be sensibly considered as the
   * counted quantity is the snapshot quantity minus the current stock on hand.
   * This is because it doesn't make sense to count an amount that represents a
   * reduction greater than the current stock on hand, which would create negative
   * inventory.
   * @return {integer} The minimum total quantity that can be sensibly counted
   */
  get minimumTotalQuantity() {
    return this.item ? Math.max(0, this.snapshotTotalQuantity - this.item.totalQuantity) : 0;
  }

  /**
   * Returns true if this stocktake item's counted quantity would reduce the amount
   * of stock in inventory to negative levels, if it were finalised. This can happen
   * if, for example, an item is added to a stocktake with a snapshot quantity of
   * 10, then is counted to have a quantity of 8, but concurrently there has been
   * a reduction in the stock in inventory, e.g. a customer invoice for 9. In this
   * example, the stock on hand is now 1, so a reduction of 2 caused by this stocktake
   * item would result in negative inventory.
   * @return {Boolean} Whether the counted quantity is below the minimum for this item
   */
  get isReducedBelowMinimum() {
    return this.countedTotalQuantity && this.countedTotalQuantity < this.minimumTotalQuantity;
  }

  addBatch(stocktakeBatch) {
    this.batches.push(stocktakeBatch);
    if (!this.countedTotalQuantity) this.countedTotalQuantity = stocktakeBatch.countedTotalQuantity;
    else this.countedTotalQuantity += stocktakeBatch.countedTotalQuantity;
  }

  /**
   * Applies the adjustments to batches in the given transaction item to the batches
   * in this stocktake item
   * @param  {Realm}   database        App wide database
   * @param  {object}  transactionItem The transaction item
   * @return {none}
   */
  applyBatchAdjustments(database, transactionItem) {
    this.batches.forEach((stocktakeBatch) => {
      const transactionBatch = transactionItem.getBatch(stocktakeBatch.itemBatchId);
      let difference = 0;
      if (transactionBatch) { // If a matching transaction batch, work out the difference
        difference = transactionItem.transaction.isIncoming ?
                            transactionBatch.totalQuantity :
                            -transactionBatch.totalQuantity;
      }
      stocktakeBatch.countedTotalQuantity = stocktakeBatch.snapshotTotalQuantity + difference;
      database.save('StocktakeBatch', stocktakeBatch);
    });
  }

  /**
   * Deletes any batches from this stocktake item that had no stock and did not change
   * @param  {Realm} database  App wide database
   * @return {none}
   */
  pruneBatches(database) {
    database.delete(
      'StocktakeBatch',
      this.batches.filtered('snapshotNumberOfPacks == 0 AND countedNumberOfPacks == 0')
    );
  }
}

StocktakeItem.schema = {
  name: 'StocktakeItem',
  primaryKey: 'id',
  properties: {
    id: 'string',
    item: 'Item',
    stocktake: 'Stocktake',
    countedTotalQuantity: { type: 'double', optional: true },
    batches: { type: 'list', objectType: 'StocktakeBatch' },
  },
};
<|endoftext|>


<commit_before>export default {
  presenceMessage: 'não pode ficar em branco',
  absenceMessage: 'deve estar em branco',
  inclusionMessage: 'não está incluso na lista de valores válidos',
  exclusionMessage: 'está incluso na lista de valores inválidos',

  // Numericality
  numericalityMessage: 'não é um número',
  numericalityOnlyIntegerMessage: 'deve ser um número inteiro',
  numericalityGreaterThanMessage: 'deve ser maior que {count}',
  numericalityGreaterThanOrEqualToMessage: 'deve ser maior ou igual a {count}',
  numericalityEqualToMessage: 'deve ser igual a {count}',
  numericalityLessThanMessage: 'deve ser menor que {count}',
  numericalityLessThanOrEqualToMessage: 'deve ser menor ou igual a {count}',
  numericalityOddMessage: 'deve ser par',
  numericalityEvenMessage: 'dever ser ímpar',

  mailMessage: 'não é um email válido',
  formatMessage: 'é inválido',
  colorMessage: 'deve ser um código de cor hexadecimal para CSS',
  subdomainMessage: 'deve ser um subdomínio válido',
  acceptanceMessage: 'precisa ser aceito',
  zipCodeMessage: 'não é um CEP válido',
  URLMessage: 'deve ser uma URL',
  wrongLengthMessage: 'comprimento de palavra errado (deve conter {count} caracteres)',
  tooShortMessage: 'muito curto (deve conter no minimo {count} caracteres)',
  tooLongMessage: 'muito longo (no maximo {count} caracteres)',
  mustContainNumberMessage: 'deve incluir um número',
  mustContainSpecialMessage: 'deve conter um desse caracteres especiais: {characters}',
  mustContainLowerMessage: 'deve conter uma letra em minusculo',
  mustContainCapitalMessage: 'deve contar uma letar em maisculo',
  customValidationMessage: 'está inválido',
  matchMessage: 'não corresponde ao formato {match}',

  dateMessage: 'não é uma data inválida',
  dateBeforeMessage: 'deve ser antes de {date}',
  dateAfterMessage: 'deve ser depois de {date}'
};
<commit_msg>fix pt-br dateMessage<commit_after>export default {
  presenceMessage: 'não pode ficar em branco',
  absenceMessage: 'deve estar em branco',
  inclusionMessage: 'não está incluso na lista de valores válidos',
  exclusionMessage: 'está incluso na lista de valores inválidos',

  // Numericality
  numericalityMessage: 'não é um número',
  numericalityOnlyIntegerMessage: 'deve ser um número inteiro',
  numericalityGreaterThanMessage: 'deve ser maior que {count}',
  numericalityGreaterThanOrEqualToMessage: 'deve ser maior ou igual a {count}',
  numericalityEqualToMessage: 'deve ser igual a {count}',
  numericalityLessThanMessage: 'deve ser menor que {count}',
  numericalityLessThanOrEqualToMessage: 'deve ser menor ou igual a {count}',
  numericalityOddMessage: 'deve ser par',
  numericalityEvenMessage: 'dever ser ímpar',

  mailMessage: 'não é um email válido',
  formatMessage: 'é inválido',
  colorMessage: 'deve ser um código de cor hexadecimal para CSS',
  subdomainMessage: 'deve ser um subdomínio válido',
  acceptanceMessage: 'precisa ser aceito',
  zipCodeMessage: 'não é um CEP válido',
  URLMessage: 'deve ser uma URL',
  wrongLengthMessage: 'comprimento de palavra errado (deve conter {count} caracteres)',
  tooShortMessage: 'muito curto (deve conter no minimo {count} caracteres)',
  tooLongMessage: 'muito longo (no maximo {count} caracteres)',
  mustContainNumberMessage: 'deve incluir um número',
  mustContainSpecialMessage: 'deve conter um desse caracteres especiais: {characters}',
  mustContainLowerMessage: 'deve conter uma letra em minusculo',
  mustContainCapitalMessage: 'deve contar uma letar em maisculo',
  customValidationMessage: 'está inválido',
  matchMessage: 'não corresponde ao formato {match}',

  dateMessage: 'não é uma data válida',
  dateBeforeMessage: 'deve ser antes de {date}',
  dateAfterMessage: 'deve ser depois de {date}'
};
<|endoftext|>