<commit_before>/**
* selection index form, calculation and presentation
* @author Isaak Y Tecle <iyt2@cornell.edu>
*
*/

JSAN.use('jquery.blockUI');

var solGS = solGS || function solGS () {};

solGS.sIndex = {

    listSelectionIndexPopulations: function()  {

	var modelData = this.getTrainingPopulationData();
	var trainingPopIdName = JSON.stringify(modelData);

	var  popsList =  '
'
            + '
 Choose a population
'
            + '

'
            + '
'
            + '' + modelData.name + '' + trainingPopIdName + ''
            + '
'
	    + '

';

	jQuery("#si_canvas #select_a_population_div").empty().append(popsList).show();

	var dbSelPopsList;
	if ( modelData.id.match(/list/) == null) {
            dbSelPopsList = this.addSelectionPopulations();
	}

	if (dbSelPopsList) {
            jQuery("#si_canvas #select_a_population_div ul").append(dbSelPopsList);
	}

	var listTypeSelPops = jQuery("#list_type_selection_pops_table").length;

	if (listTypeSelPops == true) {
            var listTypeSelPops = this.getListTypeSelPopulations();

	    if (listTypeSelPops) {
		jQuery("#si_canvas #select_a_population_div ul").append(listTypeSelPops);
            }
	}

	this.getSelectionPopTraits(modelData.id, modelData.id);

	jQuery(".si_dropdown dt a").click(function() {
            jQuery(".si_dropdown dd ul").toggle();
        });

	var selectedPopId;
	var selectedPopName;
	var selectedPopType;
	var modelId;

	jQuery(".si_dropdown dd ul li a").click(function() {

            var text = jQuery(this).html();

            jQuery(".si_dropdown dt a span").html(text);
            jQuery(".si_dropdown dd ul").hide();

            var idPopName = jQuery("#si_canvas #selected_population").find("dt a span.value").html();
            idPopName     = JSON.parse(idPopName);
            modelId = jQuery("#model_id").val();

            selectedPopId   = idPopName.id;
            selectedPopName = idPopName.name;
            selectedPopType = idPopName.pop_type;

            jQuery("#si_canvas #selected_population_name").val(selectedPopName);
            jQuery("#si_canvas #selected_population_id").val(selectedPopId);
            jQuery("#si_canvas #selected_population_type").val(selectedPopType);

	    solGS.sIndex.getSelectionPopTraits(modelId, selectedPopId);

	});

	jQuery(".si_dropdown").bind('click', function(e) {
            var clicked = jQuery(e.target);

            if (! clicked.parents().hasClass("si_dropdown"))
		jQuery(".si_dropdown dd ul").hide();

            e.preventDefault();
	});
    },

    addIndexedClustering: function() {

	var indexed = solGS.sIndex.indexed;
	var sIndexList = '';

	if (indexed) {

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

		var indexData = {
		    'id': indexed[i].sindex_id,
		    'name': indexed[i].sindex_name,
		    'pop_type': 'selection_index'
		};

		indexData = JSON.stringify(indexData);
		sIndexList += '
' + indexed[i].sindex_name + '' + indexData + '
';
	    }
	}

	return sIndexList;
    },

    saveIndexedPops: function(siId) {
	solGS.sIndex.indexed.push(siId);
    },

    addSelectionPopulations: function() {

	var selPopsTable = jQuery("#selection_pops_list").html();
	var selPopsRows;

	if (selPopsTable !== null) {
	    selPopsRows  = jQuery("#selection_pops_list").find("tbody > tr");
	}

	var predictedPop = [];
	var popsList = '';

	for (var i = 0; i < selPopsRows.length; i++) {
            var row    = selPopsRows[i];
            var popRow = row.innerHTML;

            predictedPop = popRow.match(/\/solgs\/selection\/|\/solgs\/combined\/model\/\d+\/selection/g);

            if (predictedPop) {
		if (predictedPop.length) {
                    var selPopsInput  = row.getElementsByTagName("input")[0];
                    var idPopName     = selPopsInput.value;
                    var idPopNameCopy = idPopName;
                    idPopNameCopy     = JSON.parse(idPopNameCopy);
                    var popName       = idPopNameCopy.name;

                    popsList += '
' + popName + '' + idPopName + '
';
		}
            }
	}

	return popsList;
    },

    getSelectionPopTraits: function(modelId, selectedPopId) {

	if (modelId === selectedPopId) {selectedPopId=undefined;}

	var protocolId = jQuery('#genotyping_protocol_id').val();
	var trainingTraitsIds = jQuery('#training_traits_ids').val();
    var traitsCode = jQuery('#training_traits_code').val();
	if (trainingTraitsIds) {
	    trainingTraitsIds = trainingTraitsIds.split(',');
	}

	var args = {
	    'selection_pop_id': selectedPopId,
	    'training_pop_id': modelId,
	    'training_traits_ids': trainingTraitsIds,
        'training_traits_code': traitsCode,
	    'genotyping_protocol_id': protocolId
	};

    args = JSON.stringify(args);

	jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: '/solgs/selection/index/form',
            data: {'arguments': args},
            success: function(res) {

		if (res.status == 'success') {
                    var table;
                    var traits = res.traits;

                    if (traits.length > 1) {
			table  = solGS.sIndex.selectionIndexForm(traits);
                    } else {
			var msg = 'There is only one trait with valid GEBV predictions.';
			jQuery("#si_canvas #select_a_population_div").empty();
			jQuery("#si_canvas #select_a_population_div_text").empty().append(msg);
                    }

                    jQuery('#si_canvas #selection_index_form').empty().append(table);

		}
            }
	});
    },

    selectionIndexForm: function(predictedTraits) {

	var trait = '
';
	for (var i=0; i < predictedTraits.length; i++) {
	    trait += '
'
		+ '
'
		+ '' + predictedTraits[i] + ''
		+ '
'
		+ '
'
		+ '<input class="form-control"  name="' + predictedTraits[i] + '" id="' + predictedTraits[i] + '" type="text" />'
		+ '
'
		+ '
';
	}

	trait += '
'
	    + '<input style="margin: 10px 0 10px 0;"' +
            'class="btn btn-success" type="submit"' +
            'value="Calculate" name= "rank" id="calculate_si"' + '/>'
	    + '
';

	trait += '
'

	return trait;
    },

    calcSelectionIndex: function(params, legend, trainingPopId, selectionPopId) {

	if (params) {
            jQuery.blockUI.defaults.applyPlatformOpacityRules = false;
            jQuery.blockUI({message: 'Please wait..'});

	    var trainingTraitsIds = jQuery('#training_traits_ids').val();
	    if (trainingTraitsIds) {
		trainingTraitsIds = trainingTraitsIds.split(',');
	    }
	    var protocolId = jQuery('#genotyping_protocol_id').val();
        var traitsCode = jQuery('#training_traits_code').val();

	    if (trainingPopId == selectionPopId) { selectionPopId = "";}

	    var siArgs = {
		'training_pop_id': trainingPopId,
		'selection_pop_id': selectionPopId,
		'rel_wts': params,
		'training_traits_ids': trainingTraitsIds,
        'training_traits_code': traitsCode,
		'genotyping_protocol_id': protocolId
	    };

        siArgs = JSON.stringify(siArgs);

            jQuery.ajax({
		type: 'POST',
		dataType: "json",
		data: {'arguments': siArgs},
		url: '/solgs/calculate/selection/index/',
		success: function(res){

                    if (res.status == 'success' ) {
                       let caption = `<br/>${res.download_link}<strong>Index Name:</strong> ${res.sindex_name} ${legend}`;
                       let histo = {
                           canvas: '#si_canvas',
                           plot_id: '#si_output',
                           namedValues: res.indices,
                           caption: indexName
                       };

                        solGS.histogram.plotHistogram(histo);

                        var popType = jQuery("#si_canvas #selected_population_type").val();
                        var popId   = jQuery("#si_canvas #selected_population_id").val();

                        solGS.correlation.formatGenCorInputData(popId, popType,  res.index_file);

        		    jQuery('#si_canvas #selected_pop').val('');

        		    var sIndexed = {
        			'sindex_id': popId,
        			'sindex_name': res.sindex_name
        		    };

        		    solGS.sIndex.saveIndexedPops(sIndexed);
        		    solGS.cluster.listClusterPopulations();
            }
		},
		error: function(res){
                    alert('error occured calculating selection index.');
                    jQuery.unblockUI();
		}
            });
	}
    },

    validateRelativeWts: function(nm, val) {

	if (isNaN(val) && nm != 'all') {
            alert('the relative weight of trait ' + nm + ' must be a number.');
            return;
	} else if (!val && nm != 'all') {
            alert('You need to assign a relative weight to trait ' + nm + '.'
		  + ' If you want to exclude the trait assign 0 to it.');
            return;
	    // }// else if (val < 0 && nm != 'all') {
	    //   alert('The relative weight to trait '+nm+
	    //         ' must be a positive number.'
	    //         );
	    //    return;
	} else if (nm == 'all' && val == 0) {
            alert('At least two traits must be assigned relative weight.');
            return;
	} else {
            return true;
	}

    },

     sumElements: function(elements) {
	 var sum = 0;
	 for (var i=0; i<elements.length; i++) {
             if (!isNaN(elements[i])) {
		 sum = parseFloat(sum) +  parseFloat(elements[i]);
             }
	 }

	 return sum;
     },

    selectionIndex: function(trainingPopId, selectionPopId) {

	var legendValues = this.legendParams();

	var legend   = legendValues.legend;
	var params   = legendValues.params;
	var validate = legendValues.validate;

	if (params && validate) {
            this.calcSelectionIndex(params, legend, trainingPopId, selectionPopId);
	}

    },

    legendParams: function() {

	var selectedPopName   = jQuery("#si_canvas #selected_population_name").val();

	if (!selectedPopName) {
            selectedPopName = jQuery("#si_canvas #default_selected_population_name").val();
	}

	var rel_form = document.getElementById('selection_index_form');
	var all = rel_form.getElementsByTagName('input');

	var params = {};
	var validate;
	var allValues = [];

	var trRelWts= 'Relative weights:';

	for (var i = 0; i < all.length; i++) {
            var nm = all[i].name;
            var val = all[i].value;

            if (val != 'Calculate')  {
		if (nm != 'selection_pop_name') {

                    allValues.push(val);
                    validate = this.validateRelativeWts(nm, val);

                    if (validate) {
			params[nm] = val;
			trRelWts += ' ' + nm + '' + ': '+ val;
                    }
		}
            }
	}

	params = JSON.stringify(params);
	var sum = this.sumElements(allValues);
	validate = this.validateRelativeWts('all', sum);

	for (var i=0;  i<allValues.length; i++)  {
	    // (isNaN(allValues[i]) || allValues[i] < 0)
            if (isNaN(allValues[i])) {
		params = undefined;
            }
	}
        var legend;
	if (selectedPopName) {
	    var popName = 'Population name: ' + selectedPopName;
	    var divId = selectedPopName.replace(/\s/g, "");
	    legend = '
'
		+ popName + ' | ' +  trRelWts
		+ '
';
	}

	return {
	    'legend' : legend,
	    'params': params,
	    'validate' : validate
        };

    },

    getListTypeSelPopulations: function()  {

	var listTypeSelPopsDiv   = document.getElementById("list_type_selection_populations");
	var listTypeSelPopsTable = listTypeSelPopsDiv.getElementsByTagName("table");
	var listTypeSelPopsRows  = listTypeSelPopsTable[0].rows;
	var predictedListTypePops = [];

	var popsList ='';
	for (var i = 1; i < listTypeSelPopsRows.length; i++) {
            var row    = listTypeSelPopsRows[i];
            var popRow = row.innerHTML;

            predictedListTypePops = popRow.match(/\/solgs\/selection\/|\/solgs\/combined\/model\/\d+\/selection/g);

            if (predictedListTypePops) {
		var selPopsInput  = row.getElementsByTagName("input")[0];
		var idPopName     = selPopsInput.value;
		var idPopNameCopy = idPopName;
		idPopNameCopy     = JSON.parse(idPopNameCopy);
		var popName       = idPopNameCopy.name;

		popsList += '
'
                    + '' + popName + '' + idPopName + ''
                    + '
';
            } else {
		popsList = undefined;
            }
	}

	return popsList;

    },

    getTrainingPopulationData: function() {

	var modelId   = jQuery("#si_canvas #model_id").val();
	var modelName = jQuery("#si_canvas #model_name").val();

	return {
	    'id' : modelId,
	    'name' : modelName,
	    'pop_type': 'training'
	};

    },

/////
}
////

solGS.sIndex.indexed = [];

jQuery(document).ready( function() {

    setTimeout(function (){
	solGS.sIndex.listSelectionIndexPopulations()
    }, 5000);

});

jQuery(document).on("click", "#calculate_si", function() {
    var modelId = jQuery("#si_canvas #model_id").val();
    var selectionPopId = jQuery("#si_canvas #selected_population_id").val();
    var popType = jQuery("#si_canvas #selected_population_type").val();

    solGS.sIndex.selectionIndex(modelId, selectionPopId);
});
<commit_msg>change legend property name to caption<commit_after>/**
* selection index form, calculation and presentation
* @author Isaak Y Tecle <iyt2@cornell.edu>
*
*/

JSAN.use('jquery.blockUI');

var solGS = solGS || function solGS () {};

solGS.sIndex = {

    listSelectionIndexPopulations: function()  {

	var modelData = this.getTrainingPopulationData();
	var trainingPopIdName = JSON.stringify(modelData);

	var  popsList =  '
'
            + '
 Choose a population
'
            + '

'
            + '
'
            + '' + modelData.name + '' + trainingPopIdName + ''
            + '
'
	    + '

';

	jQuery("#si_canvas #select_a_population_div").empty().append(popsList).show();

	var dbSelPopsList;
	if ( modelData.id.match(/list/) == null) {
            dbSelPopsList = this.addSelectionPopulations();
	}

	if (dbSelPopsList) {
            jQuery("#si_canvas #select_a_population_div ul").append(dbSelPopsList);
	}

	var listTypeSelPops = jQuery("#list_type_selection_pops_table").length;

	if (listTypeSelPops == true) {
            var listTypeSelPops = this.getListTypeSelPopulations();

	    if (listTypeSelPops) {
		jQuery("#si_canvas #select_a_population_div ul").append(listTypeSelPops);
            }
	}

	this.getSelectionPopTraits(modelData.id, modelData.id);

	jQuery(".si_dropdown dt a").click(function() {
            jQuery(".si_dropdown dd ul").toggle();
        });

	var selectedPopId;
	var selectedPopName;
	var selectedPopType;
	var modelId;

	jQuery(".si_dropdown dd ul li a").click(function() {

            var text = jQuery(this).html();

            jQuery(".si_dropdown dt a span").html(text);
            jQuery(".si_dropdown dd ul").hide();

            var idPopName = jQuery("#si_canvas #selected_population").find("dt a span.value").html();
            idPopName     = JSON.parse(idPopName);
            modelId = jQuery("#model_id").val();

            selectedPopId   = idPopName.id;
            selectedPopName = idPopName.name;
            selectedPopType = idPopName.pop_type;

            jQuery("#si_canvas #selected_population_name").val(selectedPopName);
            jQuery("#si_canvas #selected_population_id").val(selectedPopId);
            jQuery("#si_canvas #selected_population_type").val(selectedPopType);

	    solGS.sIndex.getSelectionPopTraits(modelId, selectedPopId);

	});

	jQuery(".si_dropdown").bind('click', function(e) {
            var clicked = jQuery(e.target);

            if (! clicked.parents().hasClass("si_dropdown"))
		jQuery(".si_dropdown dd ul").hide();

            e.preventDefault();
	});
    },

    addIndexedClustering: function() {

	var indexed = solGS.sIndex.indexed;
	var sIndexList = '';

	if (indexed) {

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

		var indexData = {
		    'id': indexed[i].sindex_id,
		    'name': indexed[i].sindex_name,
		    'pop_type': 'selection_index'
		};

		indexData = JSON.stringify(indexData);
		sIndexList += '
' + indexed[i].sindex_name + '' + indexData + '
';
	    }
	}

	return sIndexList;
    },

    saveIndexedPops: function(siId) {
	solGS.sIndex.indexed.push(siId);
    },

    addSelectionPopulations: function() {

	var selPopsTable = jQuery("#selection_pops_list").html();
	var selPopsRows;

	if (selPopsTable !== null) {
	    selPopsRows  = jQuery("#selection_pops_list").find("tbody > tr");
	}

	var predictedPop = [];
	var popsList = '';

	for (var i = 0; i < selPopsRows.length; i++) {
            var row    = selPopsRows[i];
            var popRow = row.innerHTML;

            predictedPop = popRow.match(/\/solgs\/selection\/|\/solgs\/combined\/model\/\d+\/selection/g);

            if (predictedPop) {
		if (predictedPop.length) {
                    var selPopsInput  = row.getElementsByTagName("input")[0];
                    var idPopName     = selPopsInput.value;
                    var idPopNameCopy = idPopName;
                    idPopNameCopy     = JSON.parse(idPopNameCopy);
                    var popName       = idPopNameCopy.name;

                    popsList += '
' + popName + '' + idPopName + '
';
		}
            }
	}

	return popsList;
    },

    getSelectionPopTraits: function(modelId, selectedPopId) {

	if (modelId === selectedPopId) {selectedPopId=undefined;}

	var protocolId = jQuery('#genotyping_protocol_id').val();
	var trainingTraitsIds = jQuery('#training_traits_ids').val();
    var traitsCode = jQuery('#training_traits_code').val();
	if (trainingTraitsIds) {
	    trainingTraitsIds = trainingTraitsIds.split(',');
	}

	var args = {
	    'selection_pop_id': selectedPopId,
	    'training_pop_id': modelId,
	    'training_traits_ids': trainingTraitsIds,
        'training_traits_code': traitsCode,
	    'genotyping_protocol_id': protocolId
	};

    args = JSON.stringify(args);

	jQuery.ajax({
            type: 'POST',
            dataType: "json",
            url: '/solgs/selection/index/form',
            data: {'arguments': args},
            success: function(res) {

		if (res.status == 'success') {
                    var table;
                    var traits = res.traits;

                    if (traits.length > 1) {
			table  = solGS.sIndex.selectionIndexForm(traits);
                    } else {
			var msg = 'There is only one trait with valid GEBV predictions.';
			jQuery("#si_canvas #select_a_population_div").empty();
			jQuery("#si_canvas #select_a_population_div_text").empty().append(msg);
                    }

                    jQuery('#si_canvas #selection_index_form').empty().append(table);

		}
            }
	});
    },

    selectionIndexForm: function(predictedTraits) {

	var trait = '
';
	for (var i=0; i < predictedTraits.length; i++) {
	    trait += '
'
		+ '
'
		+ '' + predictedTraits[i] + ''
		+ '
'
		+ '
'
		+ '<input class="form-control"  name="' + predictedTraits[i] + '" id="' + predictedTraits[i] + '" type="text" />'
		+ '
'
		+ '
';
	}

	trait += '
'
	    + '<input style="margin: 10px 0 10px 0;"' +
            'class="btn btn-success" type="submit"' +
            'value="Calculate" name= "rank" id="calculate_si"' + '/>'
	    + '
';

	trait += '
'

	return trait;
    },

    calcSelectionIndex: function(params, legend, trainingPopId, selectionPopId) {

	if (params) {
            jQuery.blockUI.defaults.applyPlatformOpacityRules = false;
            jQuery.blockUI({message: 'Please wait..'});

	    var trainingTraitsIds = jQuery('#training_traits_ids').val();
	    if (trainingTraitsIds) {
		trainingTraitsIds = trainingTraitsIds.split(',');
	    }
	    var protocolId = jQuery('#genotyping_protocol_id').val();
        var traitsCode = jQuery('#training_traits_code').val();

	    if (trainingPopId == selectionPopId) { selectionPopId = "";}

	    var siArgs = {
		'training_pop_id': trainingPopId,
		'selection_pop_id': selectionPopId,
		'rel_wts': params,
		'training_traits_ids': trainingTraitsIds,
        'training_traits_code': traitsCode,
		'genotyping_protocol_id': protocolId
	    };

        siArgs = JSON.stringify(siArgs);

            jQuery.ajax({
		type: 'POST',
		dataType: "json",
		data: {'arguments': siArgs},
		url: '/solgs/calculate/selection/index/',
		success: function(res){

                    if (res.status == 'success' ) {
                       let caption = `<br/>${res.download_link}<strong>Index Name:</strong> ${res.sindex_name} ${legend}`;
                       let histo = {
                           canvas: '#si_canvas',
                           plot_id: '#si_output',
                           namedValues: res.indices,
                           caption: caption
                       };

                        solGS.histogram.plotHistogram(histo);

                        var popType = jQuery("#si_canvas #selected_population_type").val();
                        var popId   = jQuery("#si_canvas #selected_population_id").val();

                        solGS.correlation.formatGenCorInputData(popId, popType,  res.index_file);

        		    jQuery('#si_canvas #selected_pop').val('');

        		    var sIndexed = {
        			'sindex_id': popId,
        			'sindex_name': res.sindex_name
        		    };

        		    solGS.sIndex.saveIndexedPops(sIndexed);
        		    solGS.cluster.listClusterPopulations();
            }
		},
		error: function(res){
                    alert('error occured calculating selection index.');
                    jQuery.unblockUI();
		}
            });
	}
    },

    validateRelativeWts: function(nm, val) {

	if (isNaN(val) && nm != 'all') {
            alert('the relative weight of trait ' + nm + ' must be a number.');
            return;
	} else if (!val && nm != 'all') {
            alert('You need to assign a relative weight to trait ' + nm + '.'
		  + ' If you want to exclude the trait assign 0 to it.');
            return;
	    // }// else if (val < 0 && nm != 'all') {
	    //   alert('The relative weight to trait '+nm+
	    //         ' must be a positive number.'
	    //         );
	    //    return;
	} else if (nm == 'all' && val == 0) {
            alert('At least two traits must be assigned relative weight.');
            return;
	} else {
            return true;
	}

    },

     sumElements: function(elements) {
	 var sum = 0;
	 for (var i=0; i<elements.length; i++) {
             if (!isNaN(elements[i])) {
		 sum = parseFloat(sum) +  parseFloat(elements[i]);
             }
	 }

	 return sum;
     },

    selectionIndex: function(trainingPopId, selectionPopId) {

	var legendValues = this.legendParams();

	var legend   = legendValues.legend;
	var params   = legendValues.params;
	var validate = legendValues.validate;

	if (params && validate) {
            this.calcSelectionIndex(params, legend, trainingPopId, selectionPopId);
	}

    },

    legendParams: function() {

	var selectedPopName   = jQuery("#si_canvas #selected_population_name").val();

	if (!selectedPopName) {
            selectedPopName = jQuery("#si_canvas #default_selected_population_name").val();
	}

	var rel_form = document.getElementById('selection_index_form');
	var all = rel_form.getElementsByTagName('input');

	var params = {};
	var validate;
	var allValues = [];

	var trRelWts= 'Relative weights:';

	for (var i = 0; i < all.length; i++) {
            var nm = all[i].name;
            var val = all[i].value;

            if (val != 'Calculate')  {
		if (nm != 'selection_pop_name') {

                    allValues.push(val);
                    validate = this.validateRelativeWts(nm, val);

                    if (validate) {
			params[nm] = val;
			trRelWts += ' ' + nm + '' + ': '+ val;
                    }
		}
            }
	}

	params = JSON.stringify(params);
	var sum = this.sumElements(allValues);
	validate = this.validateRelativeWts('all', sum);

	for (var i=0;  i<allValues.length; i++)  {
	    // (isNaN(allValues[i]) || allValues[i] < 0)
            if (isNaN(allValues[i])) {
		params = undefined;
            }
	}
        var legend;
	if (selectedPopName) {
	    var popName = 'Population name: ' + selectedPopName;
	    var divId = selectedPopName.replace(/\s/g, "");
	    legend = '
'
		+ popName + ' | ' +  trRelWts
		+ '
';
	}

	return {
	    'legend' : legend,
	    'params': params,
	    'validate' : validate
        };

    },

    getListTypeSelPopulations: function()  {

	var listTypeSelPopsDiv   = document.getElementById("list_type_selection_populations");
	var listTypeSelPopsTable = listTypeSelPopsDiv.getElementsByTagName("table");
	var listTypeSelPopsRows  = listTypeSelPopsTable[0].rows;
	var predictedListTypePops = [];

	var popsList ='';
	for (var i = 1; i < listTypeSelPopsRows.length; i++) {
            var row    = listTypeSelPopsRows[i];
            var popRow = row.innerHTML;

            predictedListTypePops = popRow.match(/\/solgs\/selection\/|\/solgs\/combined\/model\/\d+\/selection/g);

            if (predictedListTypePops) {
		var selPopsInput  = row.getElementsByTagName("input")[0];
		var idPopName     = selPopsInput.value;
		var idPopNameCopy = idPopName;
		idPopNameCopy     = JSON.parse(idPopNameCopy);
		var popName       = idPopNameCopy.name;

		popsList += '
'
                    + '' + popName + '' + idPopName + ''
                    + '
';
            } else {
		popsList = undefined;
            }
	}

	return popsList;

    },

    getTrainingPopulationData: function() {

	var modelId   = jQuery("#si_canvas #model_id").val();
	var modelName = jQuery("#si_canvas #model_name").val();

	return {
	    'id' : modelId,
	    'name' : modelName,
	    'pop_type': 'training'
	};

    },

/////
}
////

solGS.sIndex.indexed = [];

jQuery(document).ready( function() {

    setTimeout(function (){
	solGS.sIndex.listSelectionIndexPopulations()
    }, 5000);

});

jQuery(document).on("click", "#calculate_si", function() {
    var modelId = jQuery("#si_canvas #model_id").val();
    var selectionPopId = jQuery("#si_canvas #selected_population_id").val();
    var popType = jQuery("#si_canvas #selected_population_type").val();

    solGS.sIndex.selectionIndex(modelId, selectionPopId);
});
<|endoftext|>


<commit_before>/**
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// [START drive_upload_to_folder]

/**
 * Upload a file to the specified folder
 * @param{string} folderId folder ID
 * @return{obj} file Id
 * */
async function uploadToFolder(folderId) {
  const fs = require('fs');
  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app
  const auth = new GoogleAuth({scopes: 'https://www.googleapis.com/auth/drive'});
  const service = google.drive({version: 'v3', auth});

  // TODO(developer): set folder Id
  // folderId = '1lWo8HghUBd-3mN4s98ArNFMdqmhqCXH7';
  const fileMetadata = {
    'title': 'photo.jpg',
    'parents': [{id: folderId}],
  };
  const media = {
    mimeType: 'image/jpeg',
    body: fs.createReadStream('photo.jpg'),
  };

  try {
    const file = await service.files.create({
      resource: fileMetadata,
      media: media,
      fields: 'id',
    });
    console.log('File Id:', file.data.id);
    return file.data.id;
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}
// [END drive_upload_to_folder]

uploadToFolder('1lWo8HghUBd-3mN4s98ArNFMdqmhqCXH7');
<commit_msg>Update upload_to_folder.js<commit_after>/**
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
// [START drive_upload_to_folder]

/**
 * Upload a file to the specified folder
 * @param{string} folderId folder ID
 * @return{obj} file Id
 * */
async function uploadToFolder(folderId) {
  const fs = require('fs');
  const {GoogleAuth} = require('google-auth-library');
  const {google} = require('googleapis');

  // Get credentials and build service
  // TODO (developer) - Use appropriate auth mechanism for your app
  const auth = new GoogleAuth({scopes: 'https://www.googleapis.com/auth/drive'});
  const service = google.drive({version: 'v3', auth});

  // TODO(developer): set folder Id
  // folderId = '1lWo8HghUBd-3mN4s98ArNFMdqmhqCXH7';
  const fileMetadata = {
    'title': 'photo.jpg',
    'parents': [{id: folderId}],
  };
  const media = {
    mimeType: 'image/jpeg',
    body: fs.createReadStream('photo.jpg'),
  };

  try {
    const file = await service.files.create({
      resource: fileMetadata,
      media: media,
      fields: 'id',
    });
    console.log('File Id:', file.data.id);
    return file.data.id;
  } catch (err) {
    // TODO(developer) - Handle error
    throw err;
  }
}
// [END drive_upload_to_folder]

uploadToFolder('1lWo8HghUBd-3mN4s98ArNFMdqmhqCXH7');
<|endoftext|>


<commit_before>// Had to copy this from unexpected's lib/defaultDepth.js because the value is not exposed to plugins :/
let defaultDepth = 3;
if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
  const m = window.location.search.match(/[?&]depth=(\d+)(?:$|&)/);
  if (m) {
    defaultDepth = parseInt(m[1], 10);
  }
} else if (typeof process !== 'undefined' && process.env.UNEXPECTED_DEPTH) {
  defaultDepth = parseInt(process.env.UNEXPECTED_DEPTH, 10);
}

module.exports = {
  name: 'unexpected-set',
  version: require('../package.json').version,
  installInto: function unexpectedSet(expect) {
    expect.addType({
      name: 'Set',
      base: 'object',
      indent: true,
      identify(obj) {
        return obj instanceof Set;
      },
      equal(a, b) {
        if (a.size !== b.size) {
          return false;
        }
        for (const value of a) {
          if (!b.has(value)) {
            return false;
          }
        }
        return true;
      },
      prefix(output) {
        return output.jsKeyword('Set').text('([');
      },
      suffix(output) {
        return output.text('])');
      },
      inspect(set, depth, output, inspect) {
        // Mostly copied from array-like's inspect:
        const prefixOutput = this.prefix(output.clone(), set);
        const suffixOutput = this.suffix(output.clone(), set);
        if (set.size === 0) {
          return output.append(prefixOutput).append(suffixOutput);
        }

        if (depth === 1 && set.size > 10) {
          return output.append(prefixOutput).text('...').append(suffixOutput);
        }

        const inspectedItems = [];
        set.forEach((item) => {
          inspectedItems.push(inspect(item));
        });

        const currentDepth = defaultDepth - Math.min(defaultDepth, depth);
        const maxLineLength =
          output.preferredWidth -
          20 -
          currentDepth * output.indentationWidth -
          2;
        let width = 0;
        const multipleLines = inspectedItems.some((o) => {
          if (o.isMultiline()) {
            return true;
          }

          const size = o.size();
          width += size.width;
          return width > maxLineLength;
        });

        const type = this;
        inspectedItems.forEach((inspectedItem, index) => {
          inspectedItem.amend(
            type.delimiter(output.clone(), index, inspectedItems.length)
          );
        });

        output.append(prefixOutput);
        if (this.forceMultipleLines || multipleLines) {
          if (!prefixOutput.isEmpty()) {
            output.nl();
          }
          if (this.indent) {
            output.indentLines();
          }
          inspectedItems.forEach((inspectedItem, index) => {
            output
              .nl(index > 0 ? 1 : 0)
              .i()
              .block(inspectedItem);
          });
          if (this.indent) {
            output.outdentLines();
          }
          if (!suffixOutput.isEmpty()) {
            output.nl();
          }
        } else {
          output.sp(prefixOutput.isEmpty() ? 0 : 1);
          inspectedItems.forEach((inspectedItem, index) => {
            output.append(inspectedItem);
            const lastIndex = index === inspectedItems.length - 1;
            if (!lastIndex) {
              output.sp();
            }
          });
          output.sp(suffixOutput.isEmpty() ? 0 : 1);
        }
        output.append(suffixOutput);
      },
      diff(actual, expected, output, diff, inspect, equal) {
        output.inline = true;
        const prefixOutput = this.prefix(output.clone(), actual);
        const suffixOutput = this.suffix(output.clone(), actual);

        output.append(prefixOutput).nl(prefixOutput.isEmpty() ? 0 : 1);
        if (this.indent) {
          output.indentLines();
        }
        const type = this;
        let index = 0;
        actual.forEach((actualElement) => {
          output
            .nl(index > 0 ? 1 : 0)
            .i()
            .block(function () {
              this.appendInspected(actualElement);
              type.delimiter(this, index, actual.size);
              if (!expected.has(actualElement)) {
                this.sp().annotationBlock(function () {
                  this.error('should be removed');
                });
              }
            });
          index += 1;
        });
        expected.forEach((expectedElement) => {
          if (!actual.has(expectedElement)) {
            output
              .nl(index > 0 ? 1 : 0)
              .i()
              .annotationBlock(function () {
                this.error('missing').sp().appendInspected(expectedElement);
              });
            index += 1;
          }
        });
        if (this.indent) {
          output.outdentLines();
        }
        output.nl(suffixOutput.isEmpty() ? 0 : 1).append(suffixOutput);

        return output;
      },
    });

    expect.addAssertion(
      '<array-like> with set semantics <assertion?>',
      (expect, subject) => expect.shift(new Set(subject))
    );

    expect.addAssertion(
      '<Set> [not] to contain <any>',
      (expect, subject, value) => {
        expect.withError(
          () => {
            expect(subject.has(value), '[not] to be true');
          },
          () => {
            expect.fail({
              diff(output, diff, inspect, equal) {
                output.inline = true;
                expect.subjectType.prefix(output, subject);
                output.nl().indentLines();

                const subjectElements = [];
                subject.forEach((element) => {
                  subjectElements.push(element);
                });

                subjectElements.forEach((subjectElement, subjectIndex) => {
                  output
                    .i()
                    .block(function () {
                      this.appendInspected(subjectElement);
                      expect.subjectType.delimiter(
                        this,
                        subjectIndex,
                        subjectElements.length
                      );
                      if (expect.flags.not && subjectElement === value) {
                        this.sp().annotationBlock(function () {
                          this.error('should be removed');
                        });
                      }
                    })
                    .nl();
                });
                if (!expect.flags.not) {
                  output
                    .i()
                    .block(function () {
                      this.annotationBlock(function () {
                        this.error('missing').sp().appendInspected(value);
                      });
                    })
                    .nl();
                }

                output.outdentLines();
                expect.subjectType.suffix(output, subject);

                return output;
              },
            });
          }
        );
      }
    );

    expect.addAssertion('<Set> [not] to be empty', (expect, subject) => {
      expect(subject.size, '[not] to equal', 0);
    });

    expect.addAssertion(
      [
        '<Set> to have items [exhaustively] satisfying <any>',
        '<Set> to have items [exhaustively] satisfying <assertion>',
      ],
      (expect, subject, nextArg) => {
        expect.errorMode = 'nested';
        expect(subject, 'not to be empty');
        expect.errorMode = 'bubble';

        const subjectElements = [];
        subject.forEach((element) => {
          subjectElements.push(element);
        });

        const expected = [];
        subjectElements.forEach((subjectElement) => {
          if (typeof nextArg === 'string') {
            expected.push(expect.it((s) => expect.shift(s, 0)));
          } else {
            expected.push(nextArg);
          }
        });

        return expect.withError(
          () => expect(subjectElements, 'to [exhaustively] satisfy', expected),
          (err) => {
            expect.fail({
              message(output) {
                output.append(
                  expect.standardErrorMessage(output.clone(), { compact: true })
                );
              },
              diff(output) {
                output.inline = true;
                return output
                  .jsKeyword('Set')
                  .text('(')
                  .append(err.getDiff({ output }))
                  .text(')');
              },
            });
          }
        );
      }
    );

    expect.addAssertion(
      [
        '<Set> to have an item [exhaustively] satisfying <any>',
        '<Set> to have an item [exhaustively] satisfying <assertion>',
      ],
      (expect, subject, nextArg) => {
        expect.errorMode = 'nested';
        expect(subject, 'not to be empty');
        expect.errorMode = 'bubble';

        const subjectElements = [];
        subject.forEach((element) => {
          subjectElements.push(element);
        });

        const expected =
          typeof nextArg === 'string'
            ? expect.it((s) => expect.shift(s, 0))
            : nextArg;
        const expectedType = expect.findTypeOf(expected);
        const results = new Array(subjectElements.length);
        subjectElements.forEach((subjectElement, subjectIndex) => {
          results[subjectIndex] = expect.promise(() => {
            if (expectedType.is('expect.it')) {
              expect.context.thisObject = subject;
              return expected(subjectElement, expect.context);
            } else {
              return expect(
                subjectElement,
                'to [exhaustively] satisfy',
                nextArg
              );
            }
          });
        });

        return expect.promise.settle(results).then(function () {
          if (results.every((result) => !result.isFulfilled())) {
            expect.fail({
              message(output) {
                output.append(
                  expect.standardErrorMessage(output.clone(), { compact: true })
                );
              },
              diff(output, diff, inspect, equal) {
                output.inline = true;
                const prefixOutput = expect.subjectType.prefix(
                  output.clone(),
                  subject
                );
                const suffixOutput = expect.subjectType.suffix(
                  output.clone(),
                  subject
                );

                output.append(prefixOutput);
                if (!prefixOutput.isEmpty()) {
                  output.nl();
                }
                if (expect.subjectType.indent) {
                  output.indentLines();
                }

                let index = 0;
                subjectElements.forEach((subjectElement, subjectIndex) => {
                  output.omitSubject = subject;
                  output
                    .nl(index > 0 ? 1 : 0)
                    .i()
                    .block(function () {
                      const delimiterOutput = expect.subjectType.delimiter(
                        output.clone(),
                        subjectIndex,
                        subjectElements.length
                      );

                      const err = results[subjectIndex].reason();
                      const diff = err.getDiff({ output: output.clone() });

                      if (diff && diff.inline) {
                        this.append(diff).amend(delimiterOutput);
                      } else {
                        this.appendInspected(subjectElement)
                          .amend(delimiterOutput)
                          .sp()
                          .annotationBlock(function () {
                            this.omitSubject = subjectElement;
                            const label = err.getLabel();
                            if (label) {
                              this.error(label).sp().block(inspect(nextArg));
                              if (diff) {
                                this.nl(2).append(diff);
                              }
                            } else {
                              this.appendErrorMessage(err);
                            }
                          });
                      }
                    });
                  index += 1;
                });

                if (expect.subjectType.indent) {
                  output.outdentLines();
                }
                if (!suffixOutput.isEmpty()) {
                  output.nl();
                }
                output.append(suffixOutput);

                return output;
              },
            });
          }
        });
      }
    );

    expect.addAssertion(
      '<Set> to [exhaustively] satisfy <Set>',
      (expect, subject, value) => {
        const subjectElements = [];
        subject.forEach((element) => {
          subjectElements.push(element);
        });
        const valueElements = [];
        value.forEach((element) => {
          valueElements.push(element);
        });

        const promiseBySubjectIndexAndValueIndex = subjectElements.map(
          () => new Array(valueElements.length)
        );

        const promiseByValueIndexAndSubjectIndex = valueElements.map(
          (valueElement, valueIndex) =>
            subjectElements.map((subjectElement, subjectIndex) => {
              const promise = expect.promise(() => {
                const valueElementType = expect.findTypeOf(valueElement);
                if (valueElementType.is('function')) {
                  return valueElement(subjectElement);
                } else {
                  return expect(
                    subjectElement,
                    'to [exhaustively] satisfy',
                    valueElement
                  );
                }
              });
              promiseBySubjectIndexAndValueIndex[subjectIndex][
                valueIndex
              ] = promise;
              return promise;
            })
        );

        return expect.promise
          .settle(promiseByValueIndexAndSubjectIndex)
          .then(() => {
            if (
              !promiseByValueIndexAndSubjectIndex.every((row) =>
                row.some((promise) => promise.isFulfilled())
              ) ||
              !subjectElements.every((subjectElement, i) =>
                promiseByValueIndexAndSubjectIndex.some((row) =>
                  row[i].isFulfilled()
                )
              )
            ) {
              expect.fail({
                diff(output, diff, inspect, equal) {
                  output.inline = true;
                  const prefixOutput = expect.subjectType.prefix(
                    output.clone(),
                    subject
                  );
                  const suffixOutput = expect.subjectType.suffix(
                    output.clone(),
                    subject
                  );

                  output.append(prefixOutput);
                  if (!prefixOutput.isEmpty()) {
                    output.nl();
                  }
                  if (expect.subjectType.indent) {
                    output.indentLines();
                  }

                  let index = 0;
                  subjectElements.forEach((subjectElement, subjectIndex) => {
                    output
                      .nl(index > 0 ? 1 : 0)
                      .i()
                      .block(function () {
                        this.appendInspected(subjectElement);
                        expect.subjectType.delimiter(
                          this,
                          subjectIndex,
                          subjectElements.length
                        );
                        if (
                          !promiseBySubjectIndexAndValueIndex[
                            subjectIndex
                          ].some((promise, valueIndex) =>
                            promiseBySubjectIndexAndValueIndex[subjectIndex][
                              valueIndex
                            ].isFulfilled()
                          )
                        ) {
                          this.sp().annotationBlock(function () {
                            this.error('should be removed');
                          });
                        }
                      });
                    index += 1;
                  });
                  valueElements.forEach((valueElement, valueIndex) => {
                    if (
                      promiseByValueIndexAndSubjectIndex[
                        valueIndex
                      ].every((promise) => promise.isRejected())
                    ) {
                      output
                        .nl(index > 0 ? 1 : 0)
                        .i()
                        .annotationBlock(function () {
                          if (expect.findTypeOf(valueElement).is('function')) {
                            this.omitSubject = subjectElements[0];
                            this.error('missing:')
                              .sp()
                              .appendErrorMessage(
                                promiseByValueIndexAndSubjectIndex[
                                  valueIndex
                                ][0].reason()
                              );
                          } else {
                            this.error('missing')
                              .sp()
                              .appendInspected(valueElement);
                          }
                        });
                      index += 1;
                    }
                  });

                  if (expect.subjectType.indent) {
                    output.outdentLines();
                  }
                  if (!suffixOutput.isEmpty()) {
                    output.nl();
                  }
                  output.append(suffixOutput);

                  return output;
                },
              });
            }
          });
      }
    );

    expect.addAssertion(
      '<Set> [not] to have size <number>',
      (expect, subject, value) => {
        expect(subject.size, '[not] to equal', value);
      }
    );
  },
};
<commit_msg>Remove unnecessary if<commit_after>// Had to copy this from unexpected's lib/defaultDepth.js because the value is not exposed to plugins :/
let defaultDepth = 3;
if (typeof window !== 'undefined' && typeof window.location !== 'undefined') {
  const m = window.location.search.match(/[?&]depth=(\d+)(?:$|&)/);
  if (m) {
    defaultDepth = parseInt(m[1], 10);
  }
} else if (typeof process !== 'undefined' && process.env.UNEXPECTED_DEPTH) {
  defaultDepth = parseInt(process.env.UNEXPECTED_DEPTH, 10);
}

module.exports = {
  name: 'unexpected-set',
  version: require('../package.json').version,
  installInto: function unexpectedSet(expect) {
    expect.addType({
      name: 'Set',
      base: 'object',
      indent: true,
      identify(obj) {
        return obj instanceof Set;
      },
      equal(a, b) {
        if (a.size !== b.size) {
          return false;
        }
        for (const value of a) {
          if (!b.has(value)) {
            return false;
          }
        }
        return true;
      },
      prefix(output) {
        return output.jsKeyword('Set').text('([');
      },
      suffix(output) {
        return output.text('])');
      },
      inspect(set, depth, output, inspect) {
        // Mostly copied from array-like's inspect:
        const prefixOutput = this.prefix(output.clone(), set);
        const suffixOutput = this.suffix(output.clone(), set);
        if (set.size === 0) {
          return output.append(prefixOutput).append(suffixOutput);
        }

        if (depth === 1 && set.size > 10) {
          return output.append(prefixOutput).text('...').append(suffixOutput);
        }

        const inspectedItems = [];
        set.forEach((item) => {
          inspectedItems.push(inspect(item));
        });

        const currentDepth = defaultDepth - Math.min(defaultDepth, depth);
        const maxLineLength =
          output.preferredWidth -
          20 -
          currentDepth * output.indentationWidth -
          2;
        let width = 0;
        const multipleLines = inspectedItems.some((o) => {
          if (o.isMultiline()) {
            return true;
          }

          const size = o.size();
          width += size.width;
          return width > maxLineLength;
        });

        const type = this;
        inspectedItems.forEach((inspectedItem, index) => {
          inspectedItem.amend(
            type.delimiter(output.clone(), index, inspectedItems.length)
          );
        });

        output.append(prefixOutput);
        if (this.forceMultipleLines || multipleLines) {
          if (!prefixOutput.isEmpty()) {
            output.nl();
          }
          if (this.indent) {
            output.indentLines();
          }
          inspectedItems.forEach((inspectedItem, index) => {
            output
              .nl(index > 0 ? 1 : 0)
              .i()
              .block(inspectedItem);
          });
          if (this.indent) {
            output.outdentLines();
          }
          if (!suffixOutput.isEmpty()) {
            output.nl();
          }
        } else {
          output.sp(prefixOutput.isEmpty() ? 0 : 1);
          inspectedItems.forEach((inspectedItem, index) => {
            output.append(inspectedItem);
            const lastIndex = index === inspectedItems.length - 1;
            if (!lastIndex) {
              output.sp();
            }
          });
          output.sp(suffixOutput.isEmpty() ? 0 : 1);
        }
        output.append(suffixOutput);
      },
      diff(actual, expected, output, diff, inspect, equal) {
        output.inline = true;
        const prefixOutput = this.prefix(output.clone(), actual);
        const suffixOutput = this.suffix(output.clone(), actual);

        output.append(prefixOutput).nl(prefixOutput.isEmpty() ? 0 : 1);
        if (this.indent) {
          output.indentLines();
        }
        const type = this;
        let index = 0;
        actual.forEach((actualElement) => {
          output
            .nl(index > 0 ? 1 : 0)
            .i()
            .block(function () {
              this.appendInspected(actualElement);
              type.delimiter(this, index, actual.size);
              if (!expected.has(actualElement)) {
                this.sp().annotationBlock(function () {
                  this.error('should be removed');
                });
              }
            });
          index += 1;
        });
        expected.forEach((expectedElement) => {
          if (!actual.has(expectedElement)) {
            output
              .nl(index > 0 ? 1 : 0)
              .i()
              .annotationBlock(function () {
                this.error('missing').sp().appendInspected(expectedElement);
              });
            index += 1;
          }
        });
        if (this.indent) {
          output.outdentLines();
        }
        output.nl(suffixOutput.isEmpty() ? 0 : 1).append(suffixOutput);

        return output;
      },
    });

    expect.addAssertion(
      '<array-like> with set semantics <assertion?>',
      (expect, subject) => expect.shift(new Set(subject))
    );

    expect.addAssertion(
      '<Set> [not] to contain <any>',
      (expect, subject, value) => {
        expect.withError(
          () => {
            expect(subject.has(value), '[not] to be true');
          },
          () => {
            expect.fail({
              diff(output, diff, inspect, equal) {
                output.inline = true;
                expect.subjectType.prefix(output, subject);
                output.nl().indentLines();

                const subjectElements = [];
                subject.forEach((element) => {
                  subjectElements.push(element);
                });

                subjectElements.forEach((subjectElement, subjectIndex) => {
                  output
                    .i()
                    .block(function () {
                      this.appendInspected(subjectElement);
                      expect.subjectType.delimiter(
                        this,
                        subjectIndex,
                        subjectElements.length
                      );
                      if (expect.flags.not && subjectElement === value) {
                        this.sp().annotationBlock(function () {
                          this.error('should be removed');
                        });
                      }
                    })
                    .nl();
                });
                if (!expect.flags.not) {
                  output
                    .i()
                    .block(function () {
                      this.annotationBlock(function () {
                        this.error('missing').sp().appendInspected(value);
                      });
                    })
                    .nl();
                }

                output.outdentLines();
                expect.subjectType.suffix(output, subject);

                return output;
              },
            });
          }
        );
      }
    );

    expect.addAssertion('<Set> [not] to be empty', (expect, subject) => {
      expect(subject.size, '[not] to equal', 0);
    });

    expect.addAssertion(
      [
        '<Set> to have items [exhaustively] satisfying <any>',
        '<Set> to have items [exhaustively] satisfying <assertion>',
      ],
      (expect, subject, nextArg) => {
        expect.errorMode = 'nested';
        expect(subject, 'not to be empty');
        expect.errorMode = 'bubble';

        const subjectElements = [];
        subject.forEach((element) => {
          subjectElements.push(element);
        });

        const expected = [];
        subjectElements.forEach((subjectElement) => {
          if (typeof nextArg === 'string') {
            expected.push(expect.it((s) => expect.shift(s, 0)));
          } else {
            expected.push(nextArg);
          }
        });

        return expect.withError(
          () => expect(subjectElements, 'to [exhaustively] satisfy', expected),
          (err) => {
            expect.fail({
              message(output) {
                output.append(
                  expect.standardErrorMessage(output.clone(), { compact: true })
                );
              },
              diff(output) {
                output.inline = true;
                return output
                  .jsKeyword('Set')
                  .text('(')
                  .append(err.getDiff({ output }))
                  .text(')');
              },
            });
          }
        );
      }
    );

    expect.addAssertion(
      [
        '<Set> to have an item [exhaustively] satisfying <any>',
        '<Set> to have an item [exhaustively] satisfying <assertion>',
      ],
      (expect, subject, nextArg) => {
        expect.errorMode = 'nested';
        expect(subject, 'not to be empty');
        expect.errorMode = 'bubble';

        const subjectElements = [];
        subject.forEach((element) => {
          subjectElements.push(element);
        });

        const expected =
          typeof nextArg === 'string'
            ? expect.it((s) => expect.shift(s, 0))
            : nextArg;
        const expectedType = expect.findTypeOf(expected);
        const results = new Array(subjectElements.length);
        subjectElements.forEach((subjectElement, subjectIndex) => {
          results[subjectIndex] = expect.promise(() => {
            if (expectedType.is('expect.it')) {
              expect.context.thisObject = subject;
              return expected(subjectElement, expect.context);
            } else {
              return expect(
                subjectElement,
                'to [exhaustively] satisfy',
                nextArg
              );
            }
          });
        });

        return expect.promise.settle(results).then(function () {
          if (results.every((result) => !result.isFulfilled())) {
            expect.fail({
              message(output) {
                output.append(
                  expect.standardErrorMessage(output.clone(), { compact: true })
                );
              },
              diff(output, diff, inspect, equal) {
                output.inline = true;
                const prefixOutput = expect.subjectType.prefix(
                  output.clone(),
                  subject
                );
                const suffixOutput = expect.subjectType.suffix(
                  output.clone(),
                  subject
                );

                output.append(prefixOutput);
                if (!prefixOutput.isEmpty()) {
                  output.nl();
                }
                if (expect.subjectType.indent) {
                  output.indentLines();
                }

                let index = 0;
                subjectElements.forEach((subjectElement, subjectIndex) => {
                  output.omitSubject = subject;
                  output
                    .nl(index > 0 ? 1 : 0)
                    .i()
                    .block(function () {
                      const delimiterOutput = expect.subjectType.delimiter(
                        output.clone(),
                        subjectIndex,
                        subjectElements.length
                      );

                      const err = results[subjectIndex].reason();
                      const diff = err.getDiff({ output: output.clone() });

                      if (diff && diff.inline) {
                        this.append(diff).amend(delimiterOutput);
                      } else {
                        this.appendInspected(subjectElement)
                          .amend(delimiterOutput)
                          .sp()
                          .annotationBlock(function () {
                            this.omitSubject = subjectElement;
                            this.appendErrorMessage(err);
                          });
                      }
                    });
                  index += 1;
                });

                if (expect.subjectType.indent) {
                  output.outdentLines();
                }
                if (!suffixOutput.isEmpty()) {
                  output.nl();
                }
                output.append(suffixOutput);

                return output;
              },
            });
          }
        });
      }
    );

    expect.addAssertion(
      '<Set> to [exhaustively] satisfy <Set>',
      (expect, subject, value) => {
        const subjectElements = [];
        subject.forEach((element) => {
          subjectElements.push(element);
        });
        const valueElements = [];
        value.forEach((element) => {
          valueElements.push(element);
        });

        const promiseBySubjectIndexAndValueIndex = subjectElements.map(
          () => new Array(valueElements.length)
        );

        const promiseByValueIndexAndSubjectIndex = valueElements.map(
          (valueElement, valueIndex) =>
            subjectElements.map((subjectElement, subjectIndex) => {
              const promise = expect.promise(() => {
                const valueElementType = expect.findTypeOf(valueElement);
                if (valueElementType.is('function')) {
                  return valueElement(subjectElement);
                } else {
                  return expect(
                    subjectElement,
                    'to [exhaustively] satisfy',
                    valueElement
                  );
                }
              });
              promiseBySubjectIndexAndValueIndex[subjectIndex][
                valueIndex
              ] = promise;
              return promise;
            })
        );

        return expect.promise
          .settle(promiseByValueIndexAndSubjectIndex)
          .then(() => {
            if (
              !promiseByValueIndexAndSubjectIndex.every((row) =>
                row.some((promise) => promise.isFulfilled())
              ) ||
              !subjectElements.every((subjectElement, i) =>
                promiseByValueIndexAndSubjectIndex.some((row) =>
                  row[i].isFulfilled()
                )
              )
            ) {
              expect.fail({
                diff(output, diff, inspect, equal) {
                  output.inline = true;
                  const prefixOutput = expect.subjectType.prefix(
                    output.clone(),
                    subject
                  );
                  const suffixOutput = expect.subjectType.suffix(
                    output.clone(),
                    subject
                  );

                  output.append(prefixOutput);
                  if (!prefixOutput.isEmpty()) {
                    output.nl();
                  }
                  if (expect.subjectType.indent) {
                    output.indentLines();
                  }

                  let index = 0;
                  subjectElements.forEach((subjectElement, subjectIndex) => {
                    output
                      .nl(index > 0 ? 1 : 0)
                      .i()
                      .block(function () {
                        this.appendInspected(subjectElement);
                        expect.subjectType.delimiter(
                          this,
                          subjectIndex,
                          subjectElements.length
                        );
                        if (
                          !promiseBySubjectIndexAndValueIndex[
                            subjectIndex
                          ].some((promise, valueIndex) =>
                            promiseBySubjectIndexAndValueIndex[subjectIndex][
                              valueIndex
                            ].isFulfilled()
                          )
                        ) {
                          this.sp().annotationBlock(function () {
                            this.error('should be removed');
                          });
                        }
                      });
                    index += 1;
                  });
                  valueElements.forEach((valueElement, valueIndex) => {
                    if (
                      promiseByValueIndexAndSubjectIndex[
                        valueIndex
                      ].every((promise) => promise.isRejected())
                    ) {
                      output
                        .nl(index > 0 ? 1 : 0)
                        .i()
                        .annotationBlock(function () {
                          if (expect.findTypeOf(valueElement).is('function')) {
                            this.omitSubject = subjectElements[0];
                            this.error('missing:')
                              .sp()
                              .appendErrorMessage(
                                promiseByValueIndexAndSubjectIndex[
                                  valueIndex
                                ][0].reason()
                              );
                          } else {
                            this.error('missing')
                              .sp()
                              .appendInspected(valueElement);
                          }
                        });
                      index += 1;
                    }
                  });

                  if (expect.subjectType.indent) {
                    output.outdentLines();
                  }
                  if (!suffixOutput.isEmpty()) {
                    output.nl();
                  }
                  output.append(suffixOutput);

                  return output;
                },
              });
            }
          });
      }
    );

    expect.addAssertion(
      '<Set> [not] to have size <number>',
      (expect, subject, value) => {
        expect(subject.size, '[not] to equal', value);
      }
    );
  },
};
<|endoftext|>


<commit_before>define(function(require) {
    var $ = require("jquery");
    var Firebase = require("firebase");

  //handlebars templates
    var templates = require("3-loadtemplates");
    var userStorage = require("5-user-data-storage");
    var populateNewUserView = require("populateNewUserView");
    var populateUserHomeView = require("populateUserHomeView");

    return {
        findMovie: function(title) {
            $.ajax({
                type: "GET",
                dataType: "json",
                url: "http://img.omdbapi.com/?apikey=7c212437&t=" + title,
                success: function(data){
                console.log("data returned", data);
                return $.get(data.Poster);
                },
            async:false,
            error: function() {
                return "Image not found.";
            }
            });
        }
    };
});<commit_msg>last changes made at cafe<commit_after>define(function(require) {
    var $ = require("jquery");
    var Firebase = require("firebase");
    var q = "q";

  //handlebars templates
    var templates = require("3-loadtemplates");
    var userStorage = require("5-user-data-storage");
    var populateNewUserView = require("populateNewUserView");
    var populateUserHomeView = require("populateUserHomeView");

    return {
        //set up a few variables

        findMovie: function(title) {
        var data;
        var title = $("#movieToSearch").val;
        console.log("title",title );

            $.ajax({
                type: "GET",
                dataType: "json",
                url: "http://www.omdbapi.com/?t=" + title,
                success: function(data){
                console.log("data returned", data);
                return $.get(data.Poster);
                },
            async:false,
            error: function() {
                return "Image not found.";
        }
            })
            }
    }
});

<|endoftext|>


<commit_before>import { get, set } from '@vueuse/core';
import { computed, getCurrentInstance, ref, watch } from 'kolibri.lib.vueCompositionApi';
import { ContentNodeResource } from 'kolibri.resources';
import { AllCategories, NoCategories } from 'kolibri.coreVue.vuex.constants';
import { normalizeContentNode } from '../modules/coreLearn/utils';

const searchKeys = [
  'learning_activities',
  'categories',
  'learner_needs',
  'channels',
  'accessibility_labels',
  'languages',
  'grade_levels',
];

export default function useSearch(store, router) {
  // Get store and router references from the curent instance
  // but allow them to be passed in to allow for dependency
  // injection, primarily for tests.
  store = store || getCurrentInstance().proxy.$store;
  router = router || getCurrentInstance().proxy.$router;
  const route = computed(() => store.state.route);

  const searchLoading = ref(false);
  const moreLoading = ref(false);
  const results = ref([]);
  const more = ref(null);
  const labels = ref(null);

  let descendant;

  function setSearchWithinDescendant(d) {
    descendant = d;
  }

  const searchTerms = computed({
    get() {
      const searchTerms = {};
      const query = get(route).query;
      for (let key of searchKeys) {
        const obj = {};
        if (query[key]) {
          for (let value of query[key].split(',')) {
            obj[value] = true;
          }
        }
        searchTerms[key] = obj;
      }
      searchTerms.keywords = query.keywords || '';
      return searchTerms;
    },
    set(value) {
      const query = { ...get(route).query };
      for (let key of searchKeys) {
        const val = Object.keys(value[key] || {})
          .filter(Boolean)
          .join(',');
        if (val.length) {
          query[key] = Object.keys(value[key]).join(',');
        } else {
          delete query[key];
        }
      }
      if (value.keywords && value.keywords.length) {
        query.keywords = value.keywords;
      } else {
        delete query.keywords;
      }
      // Just catch an error from making a redundant navigation rather
      // than try to precalculate this.
      router.push({ ...get(route), query }).catch(() => {});
    },
  });

  const displayingSearchResults = computed(() =>
    // Happily this works even for keywords, because calling Object.keys
    // on a string value will give an array of the indexes of a string
    // for an empty string, this array will be empty, meaning that this
    // check still works!
    Object.values(get(searchTerms)).some(v => Object.keys(v).length)
  );

  function search() {
    const getParams = {};
    if (descendant) {
      getParams.tree_id = descendant.tree_id;
      getParams.lft__gt = descendant.lft;
      getParams.rght__lt = descendant.rght;
    }
    if (get(displayingSearchResults)) {
      getParams.max_results = 25;
      const terms = get(searchTerms);
      set(searchLoading, true);
      for (let key of searchKeys) {
        if (key === 'categories') {
          if (terms[key][AllCategories]) {
            getParams['categories__isnull'] = false;
            continue;
          } else if (terms[key][NoCategories]) {
            getParams['categories__isnull'] = true;
            continue;
          }
        }
        if (key === 'channels' && descendant) {
          continue;
        }
        const keys = Object.keys(terms[key]);
        if (keys.length) {
          getParams[key] = keys;
        }
      }
      if (terms.keywords) {
        getParams.keywords = terms.keywords;
      }
      ContentNodeResource.fetchCollection({ getParams }).then(data => {
        set(results, (data.results || []).map(normalizeContentNode));
        set(more, data.more);
        set(labels, data.labels);
        set(searchLoading, false);
      });
    } else if (descendant) {
      getParams.max_results = 1;
      ContentNodeResource.fetchCollection({ getParams }).then(data => {
        set(labels, data.labels);
        set(more, null);
      });
    } else {
      // Clear labels if no search results displaying
      // and we're not gathering labels from the descendant
      set(more, null);
      set(labels, null);
    }
  }

  function searchMore() {
    if (get(displayingSearchResults) && get(more) && !get(moreLoading)) {
      set(moreLoading, true);
      return ContentNodeResource.fetchCollection({ getParams: get(more) }).then(data => {
        set(results, [...get(results), ...(data.results || []).map(normalizeContentNode)]);
        set(more, data.more);
        set(labels, data.labels);
        set(moreLoading, false);
      });
    }
  }

  function removeFilterTag({ value, key }) {
    if (key === 'keywords') {
      set(searchTerms, {
        ...get(searchTerms),
        [key]: '',
      });
    } else {
      const keyObject = get(searchTerms)[key];
      delete keyObject[value];
      set(searchTerms, {
        ...get(searchTerms),
        [key]: keyObject,
      });
    }
  }

  function clearSearch() {
    set(searchTerms, {});
  }

  function setCategory(category) {
    set(searchTerms, { ...get(searchTerms), categories: { [category]: true } });
  }

  watch(searchTerms, search);

  return {
    searchTerms,
    displayingSearchResults,
    searchLoading,
    moreLoading,
    results,
    more,
    labels,
    search,
    searchMore,
    removeFilterTag,
    clearSearch,
    setCategory,
    setSearchWithinDescendant,
  };
}
<commit_msg>Fetch progress when searching.<commit_after>import { get, set } from '@vueuse/core';
import { computed, getCurrentInstance, ref, watch } from 'kolibri.lib.vueCompositionApi';
import { ContentNodeResource } from 'kolibri.resources';
import { AllCategories, NoCategories } from 'kolibri.coreVue.vuex.constants';
import { normalizeContentNode } from '../modules/coreLearn/utils';
import useContentNodeProgress from './useContentNodeProgress';

const searchKeys = [
  'learning_activities',
  'categories',
  'learner_needs',
  'channels',
  'accessibility_labels',
  'languages',
  'grade_levels',
];

const { fetchContentNodeProgress } = useContentNodeProgress();

export default function useSearch(store, router) {
  // Get store and router references from the curent instance
  // but allow them to be passed in to allow for dependency
  // injection, primarily for tests.
  store = store || getCurrentInstance().proxy.$store;
  router = router || getCurrentInstance().proxy.$router;
  const route = computed(() => store.state.route);

  const searchLoading = ref(false);
  const moreLoading = ref(false);
  const results = ref([]);
  const more = ref(null);
  const labels = ref(null);

  let descendant;

  function setSearchWithinDescendant(d) {
    descendant = d;
  }

  const searchTerms = computed({
    get() {
      const searchTerms = {};
      const query = get(route).query;
      for (let key of searchKeys) {
        const obj = {};
        if (query[key]) {
          for (let value of query[key].split(',')) {
            obj[value] = true;
          }
        }
        searchTerms[key] = obj;
      }
      searchTerms.keywords = query.keywords || '';
      return searchTerms;
    },
    set(value) {
      const query = { ...get(route).query };
      for (let key of searchKeys) {
        const val = Object.keys(value[key] || {})
          .filter(Boolean)
          .join(',');
        if (val.length) {
          query[key] = Object.keys(value[key]).join(',');
        } else {
          delete query[key];
        }
      }
      if (value.keywords && value.keywords.length) {
        query.keywords = value.keywords;
      } else {
        delete query.keywords;
      }
      // Just catch an error from making a redundant navigation rather
      // than try to precalculate this.
      router.push({ ...get(route), query }).catch(() => {});
    },
  });

  const displayingSearchResults = computed(() =>
    // Happily this works even for keywords, because calling Object.keys
    // on a string value will give an array of the indexes of a string
    // for an empty string, this array will be empty, meaning that this
    // check still works!
    Object.values(get(searchTerms)).some(v => Object.keys(v).length)
  );

  function search() {
    const getParams = {};
    if (descendant) {
      getParams.tree_id = descendant.tree_id;
      getParams.lft__gt = descendant.lft;
      getParams.rght__lt = descendant.rght;
    }
    if (get(displayingSearchResults)) {
      getParams.max_results = 25;
      const terms = get(searchTerms);
      set(searchLoading, true);
      for (let key of searchKeys) {
        if (key === 'categories') {
          if (terms[key][AllCategories]) {
            getParams['categories__isnull'] = false;
            continue;
          } else if (terms[key][NoCategories]) {
            getParams['categories__isnull'] = true;
            continue;
          }
        }
        if (key === 'channels' && descendant) {
          continue;
        }
        const keys = Object.keys(terms[key]);
        if (keys.length) {
          getParams[key] = keys;
        }
      }
      if (terms.keywords) {
        getParams.keywords = terms.keywords;
      }
      if (store.getters.isUserLoggedIn) {
        fetchContentNodeProgress(getParams);
      }
      ContentNodeResource.fetchCollection({ getParams }).then(data => {
        set(results, (data.results || []).map(normalizeContentNode));
        set(more, data.more);
        set(labels, data.labels);
        set(searchLoading, false);
      });
    } else if (descendant) {
      getParams.max_results = 1;
      ContentNodeResource.fetchCollection({ getParams }).then(data => {
        set(labels, data.labels);
        set(more, null);
      });
    } else {
      // Clear labels if no search results displaying
      // and we're not gathering labels from the descendant
      set(more, null);
      set(labels, null);
    }
  }

  function searchMore() {
    if (get(displayingSearchResults) && get(more) && !get(moreLoading)) {
      set(moreLoading, true);
      if (store.getters.isUserLoggedIn) {
        fetchContentNodeProgress(get(more));
      }
      return ContentNodeResource.fetchCollection({ getParams: get(more) }).then(data => {
        set(results, [...get(results), ...(data.results || []).map(normalizeContentNode)]);
        set(more, data.more);
        set(labels, data.labels);
        set(moreLoading, false);
      });
    }
  }

  function removeFilterTag({ value, key }) {
    if (key === 'keywords') {
      set(searchTerms, {
        ...get(searchTerms),
        [key]: '',
      });
    } else {
      const keyObject = get(searchTerms)[key];
      delete keyObject[value];
      set(searchTerms, {
        ...get(searchTerms),
        [key]: keyObject,
      });
    }
  }

  function clearSearch() {
    set(searchTerms, {});
  }

  function setCategory(category) {
    set(searchTerms, { ...get(searchTerms), categories: { [category]: true } });
  }

  watch(searchTerms, search);

  return {
    searchTerms,
    displayingSearchResults,
    searchLoading,
    moreLoading,
    results,
    more,
    labels,
    search,
    searchMore,
    removeFilterTag,
    clearSearch,
    setCategory,
    setSearchWithinDescendant,
  };
}
<|endoftext|>


<commit_before>'use strict';

var util = require('util');
var ElementWrapper = require('./element-wrapper');
var Q = require('q');
var _ = require('lodash');
var assert = require('assert');   // TODO: remove

var VertexWrapper = module.exports = function (gremlin, el) {
  ElementWrapper.call(this, gremlin, el);
};

util.inherits(VertexWrapper, ElementWrapper);

// public Iterable<Edge> getEdges(Direction direction, String... labels);
// public Iterable<Vertex> getVertices(Direction direction, String... labels);
// public VertexQuery query();
// public Edge addEdge(String label, Vertex inVertex);

VertexWrapper.prototype.addEdge = function (label, inVertex, properties, callback) {
  // TinkerPop3 changed the API for addEdge() from that used in TinkerPop2.
  // We currently use asserts to detect cases where addEdge is called with the TP2 API.
  var self = this;
  assert(_.isObject(properties));
  var propArray = _.flatten(_.pairs(properties));
  var arrayList = self.gremlin.java.newArray('java.lang.String', propArray);
  assert(inVertex instanceof VertexWrapper);
  return Q.nbind(self.el.addEdge, self.el)(label, inVertex.unwrap(), propArray)
    .then(function (e) { return self.gremlin.wrapEdge(e); })
    .nodeify(callback);
};

VertexWrapper.prototype.setProperty = function (key, value, callback) {
  return Q.nbind(this.el.singleProperty, this.el)(key, value, this.gremlin.emptyArrayList).nodeify(callback);
};

function simplifyVertexProperties(obj) {
  // Given *obj* which is a javascript object derived from a vertex, return a simplified object,
  // by flattening the object.properties.
  obj.properties = _.mapValues(obj.properties, function (propValue) {
    var values = _.pluck(propValue, 'value');
    return (values.length === 1) ? values[0] : values;
  });
  return obj;
}

VertexWrapper.prototype.jsonStringifySync = function (options) {
//   console.log('VertexWrapper.prototype.jsonStringifySync options:', options);
  // Return a json-formatted string (synchronously) for this vertex.
  var self = this;
  var stream = new self.gremlin.ByteArrayOutputStream();
  var builder = self.gremlin.java.callStaticMethodSync('com.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter', 'build');
  var writer = builder.createSync();
  writer.writeVertexSync(stream, self.unwrap());
  var vertexAsString = stream.toStringSync(self.gremlin.UTF8);
  var vertexAsObject = JSON.parse(vertexAsString);
  var simplifiedVertex = options.fullVertexProperties ? vertexAsObject : simplifyVertexProperties(vertexAsObject);
//   console.log('VertexWrapper.prototype.jsonStringifySync simplifiedVertex:', simplifiedVertex);
  var resultString = JSON.stringify(simplifiedVertex);
  return resultString;
};

<commit_msg>Remove commented out console.log lines.<commit_after>'use strict';

var util = require('util');
var ElementWrapper = require('./element-wrapper');
var Q = require('q');
var _ = require('lodash');
var assert = require('assert');   // TODO: remove

var VertexWrapper = module.exports = function (gremlin, el) {
  ElementWrapper.call(this, gremlin, el);
};

util.inherits(VertexWrapper, ElementWrapper);

// public Iterable<Edge> getEdges(Direction direction, String... labels);
// public Iterable<Vertex> getVertices(Direction direction, String... labels);
// public VertexQuery query();
// public Edge addEdge(String label, Vertex inVertex);

VertexWrapper.prototype.addEdge = function (label, inVertex, properties, callback) {
  // TinkerPop3 changed the API for addEdge() from that used in TinkerPop2.
  // We currently use asserts to detect cases where addEdge is called with the TP2 API.
  var self = this;
  assert(_.isObject(properties));
  var propArray = _.flatten(_.pairs(properties));
  var arrayList = self.gremlin.java.newArray('java.lang.String', propArray);
  assert(inVertex instanceof VertexWrapper);
  return Q.nbind(self.el.addEdge, self.el)(label, inVertex.unwrap(), propArray)
    .then(function (e) { return self.gremlin.wrapEdge(e); })
    .nodeify(callback);
};

VertexWrapper.prototype.setProperty = function (key, value, callback) {
  return Q.nbind(this.el.singleProperty, this.el)(key, value, this.gremlin.emptyArrayList).nodeify(callback);
};

function simplifyVertexProperties(obj) {
  // Given *obj* which is a javascript object derived from a vertex, return a simplified object,
  // by flattening the object.properties.
  obj.properties = _.mapValues(obj.properties, function (propValue) {
    var values = _.pluck(propValue, 'value');
    return (values.length === 1) ? values[0] : values;
  });
  return obj;
}

VertexWrapper.prototype.jsonStringifySync = function (options) {
  // Return a json-formatted string (synchronously) for this vertex.
  var self = this;
  var stream = new self.gremlin.ByteArrayOutputStream();
  var builder = self.gremlin.java.callStaticMethodSync('com.tinkerpop.gremlin.structure.io.graphson.GraphSONWriter', 'build');
  var writer = builder.createSync();
  writer.writeVertexSync(stream, self.unwrap());
  var vertexAsString = stream.toStringSync(self.gremlin.UTF8);
  var vertexAsObject = JSON.parse(vertexAsString);
  var simplifiedVertex = options.fullVertexProperties ? vertexAsObject : simplifyVertexProperties(vertexAsObject);
  var resultString = JSON.stringify(simplifiedVertex);
  return resultString;
};

<|endoftext|>


<commit_before>import { ContentNodeResource } from 'kolibri.resources';
import { currentUserId, getChannelObject, isUserLoggedIn } from 'kolibri.coreVue.vuex.getters';

import {
  samePageCheckGenerator,
  setChannelInfo,
  handleApiError,
} from 'kolibri.coreVue.vuex.actions';

import { PageNames } from '../../constants';
import { contentState, setAndCheckChannels } from './main';

import ConditionalPromise from 'kolibri.lib.conditionalPromise';
import uniqBy from 'lodash/uniqBy';
import { createTranslator } from 'kolibri.utils.i18n';

const name = 'learnerRecommendationPageTitles';

const messages = {
  popularPageTitle: 'Popular',
  resumePageTitle: 'Resume',
  nextStepsPageTitle: 'Next Steps',
  featuredInChannelPageTitle: 'Featured - { currentChannel }',
  learnContentPageTitle: '{ currentContent } - { currentChannel }',
  learnPageTitle: 'Learn',
};

const translator = createTranslator(name, messages);

// User-agnostic recommendations

function _getPopular() {
  const popularPayload = { popular: 'true' };
  return ContentNodeResource.getCollection(popularPayload).fetch();
}

function _getFeatured(state, channelId) {
  return ContentNodeResource.getAllContentCollection({ channel_id: channelId }).fetch();
}

// User-specific recommendations
function _getNextSteps(state) {
  const nextStepsPayload = { next_steps: currentUserId(state) };

  if (isUserLoggedIn(state)) {
    return ContentNodeResource.getCollection(nextStepsPayload).fetch();
  }
  return Promise.resolve([]);
}

function _getResume(state) {
  const resumePayload = { resume: currentUserId(state) };

  if (isUserLoggedIn(state)) {
    return ContentNodeResource.getCollection(resumePayload).fetch();
  }
  return Promise.resolve([]);
}

function _mapContentSet(contentSet) {
  return uniqBy(contentSet, 'content_id').map(contentState);
}

function _showRecSubpage(store, getContentPromise, pageName, windowTitleId, channelId = null) {
  const state = store.state;
  // promise that resolves with content array, already mapped to state
  const pagePrep = Promise.all([
    getContentPromise(state, channelId),
    setAndCheckChannels(store),
    // resolves to mapped content set because then resolves to its function's return value
  ]).then(([content, channels]) => [_mapContentSet(content), channels]);

  pagePrep.then(
    ([recommendations, channels]) => {
      if (!channels.length) {
        return;
      }
      const recPageState = {
        recommendations,
      };
      let pageTitle;
      if (channelId) {
        const currentChannel = getChannelObject(store.state, channelId);
        const channelTitle = currentChannel.title;
        recPageState.channelTitle = channelTitle;
        pageTitle = translator.$tr(windowTitleId, { currentChannel: channelTitle });
      } else {
        pageTitle = translator.$tr(windowTitleId);
      }
      store.dispatch('SET_PAGE_STATE', recPageState);
      store.dispatch('SET_PAGE_NAME', pageName);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_TITLE', pageTitle);
    },
    error => handleApiError(error)
  );
}

function showLearn(store) {
  store.dispatch('SET_EMPTY_LOGGING_STATE');
  // Special case for when only the page number changes:
  // Don't set the 'page loading' boolean, to prevent flash and loss of keyboard focus.
  const state = store.state;
  if (state.pageName !== PageNames.RECOMMENDED) {
    store.dispatch('CORE_SET_PAGE_LOADING', true);
  }

  const channelsPromise = setAndCheckChannels(store);
  ConditionalPromise.all([
    _getNextSteps(state),
    _getPopular(),
    _getResume(state),
    channelsPromise,
  ]).only(
    samePageCheckGenerator(store),
    ([nextSteps, popular, resume, channels]) => {
      if (!channels.length) {
        return;
      }
      const featuredChannels = channels.slice(0, 3);
      const pageState = {
        // Hard to guarantee this uniqueness on the database side, so
        // do a uniqBy content_id here, to prevent confusing repeated
        // content items.
        nextSteps: _mapContentSet(nextSteps),
        popular: _mapContentSet(popular),
        resume: _mapContentSet(resume),
        featured: {},
      };
      featuredChannels.forEach(channel => {
        pageState.featured[channel.id] = [];
      });

      store.dispatch('SET_PAGE_STATE', pageState);

      featuredChannels.forEach(channel => {
        _getFeatured(state, channel.id).only(samePageCheckGenerator(store), featured => {
          store.dispatch('SET_FEATURED_CHANNEL_CONTENTS', channel.id, _mapContentSet(featured));
        });
      });

      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_PAGE_NAME', PageNames.RECOMMENDED);

      store.dispatch('CORE_SET_TITLE', translator.$tr('learnPageTitle'));
    },
    error => {
      handleApiError(store, error);
    }
  );
}

function showPopularPage(store) {
  _showRecSubpage(store, _getPopular, PageNames.RECOMMENDED_POPULAR, 'popularPageTitle');
}

function showResumePage(store) {
  _showRecSubpage(store, _getResume, PageNames.RECOMMENDED_RESUME, 'resumePageTitle');
}

function showNextStepsPage(store) {
  _showRecSubpage(store, _getNextSteps, PageNames.RECOMMENDED_NEXT_STEPS, 'nextStepsPageTitle');
}

function showFeaturedPage(store, channelId) {
  _showRecSubpage(
    store,
    _getFeatured,
    PageNames.RECOMMENDED_FEATURED,
    'featuredInChannelPageTitle',
    channelId
  );
}

function showLearnContent(store, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.RECOMMENDED_CONTENT);
  const contentPromise = ContentNodeResource.getModel(id).fetch();
  const recommendedPromise = ContentNodeResource.getCollection({
    recommendations_for: id,
  }).fetch();
  const channelsPromise = setChannelInfo(store);
  const nextContentPromise = ContentNodeResource.fetchNextContent(id);
  ConditionalPromise.all([contentPromise, nextContentPromise, channelsPromise]).only(
    samePageCheckGenerator(store),
    ([content, nextContent]) => {
      const pageState = {
        content: contentState(content, nextContent),
        recommended: store.state.pageState.recommended,
      };
      const currentChannel = getChannelObject(store.state, content.channel_id);
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch(
        'CORE_SET_TITLE',
        translator.$tr('learnContentPageTitle', {
          currentContent: pageState.content.title,
          currentChannel: currentChannel.title,
        })
      );
    },
    error => {
      handleApiError(store, error);
    }
  );
  recommendedPromise.only(
    samePageCheckGenerator(store),
    recommended => {
      const pageState = {
        content: store.state.pageState.content,
        recommended: recommended.map(contentState),
      };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_ERROR', null);
    },
    error => {
      handleApiError(store, error);
    }
  );
}

export {
  showLearn,
  showPopularPage,
  showNextStepsPage,
  showResumePage,
  showFeaturedPage,
  showLearnContent,
};
<commit_msg>Delete temp variables and use named resources in recommended actions<commit_after>import { ContentNodeResource } from 'kolibri.resources';
import { currentUserId, getChannelObject, isUserLoggedIn } from 'kolibri.coreVue.vuex.getters';
import {
  samePageCheckGenerator,
  setChannelInfo,
  handleApiError,
} from 'kolibri.coreVue.vuex.actions';
import { PageNames } from '../../constants';
import { contentState, setAndCheckChannels } from './main';
import ConditionalPromise from 'kolibri.lib.conditionalPromise';
import uniqBy from 'lodash/uniqBy';
import { createTranslator } from 'kolibri.utils.i18n';

const translator = createTranslator('learnerRecommendationPageTitles', {
  popularPageTitle: 'Popular',
  resumePageTitle: 'Resume',
  nextStepsPageTitle: 'Next Steps',
  featuredInChannelPageTitle: 'Featured - { currentChannel }',
  learnContentPageTitle: '{ currentContent } - { currentChannel }',
  learnPageTitle: 'Learn',
});

// User-agnostic recommendations
function _getPopular() {
  return ContentNodeResource.getCollection({ popular: 'true' }).fetch();
}

function _getFeatured(state, channelId) {
  return ContentNodeResource.getAllContentCollection({ channel_id: channelId }).fetch();
}

// User-specific recommendations
function _getNextSteps(state) {
  if (isUserLoggedIn(state)) {
    return ContentNodeResource.getCollection({ next_steps: currentUserId(state) }).fetch();
  }
  return Promise.resolve([]);
}

function _getResume(state) {
  if (isUserLoggedIn(state)) {
    return ContentNodeResource.getCollection({ resume: currentUserId(state) }).fetch();
  }
  return Promise.resolve([]);
}

function _mapContentSet(contentSet) {
  return uniqBy(contentSet, 'content_id').map(contentState);
}

function _showRecSubpage(store, getContentPromise, pageName, windowTitleId, channelId = null) {
  // promise that resolves with content array, already mapped to state
  const pagePrep = Promise.all([
    getContentPromise(store.state, channelId),
    setAndCheckChannels(store),
    // resolves to mapped content set because then resolves to its function's return value
  ]).then(([content, channels]) => [_mapContentSet(content), channels]);

  pagePrep.then(
    ([recommendations, channels]) => {
      if (!channels.length) {
        return;
      }
      const recPageState = {
        recommendations,
      };
      let pageTitle;
      if (channelId) {
        const currentChannel = getChannelObject(store.state, channelId);
        const channelTitle = currentChannel.title;
        recPageState.channelTitle = channelTitle;
        pageTitle = translator.$tr(windowTitleId, { currentChannel: channelTitle });
      } else {
        pageTitle = translator.$tr(windowTitleId);
      }
      store.dispatch('SET_PAGE_STATE', recPageState);
      store.dispatch('SET_PAGE_NAME', pageName);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('CORE_SET_TITLE', pageTitle);
    },
    error => handleApiError(error)
  );
}

export function showLearn(store) {
  store.dispatch('SET_EMPTY_LOGGING_STATE');
  // Special case for when only the page number changes:
  // Don't set the 'page loading' boolean, to prevent flash and loss of keyboard focus.
  const state = store.state;
  if (state.pageName !== PageNames.RECOMMENDED) {
    store.dispatch('CORE_SET_PAGE_LOADING', true);
  }

  return ConditionalPromise.all([
    _getNextSteps(state),
    _getPopular(),
    _getResume(state),
    setAndCheckChannels(store),
  ]).only(
    samePageCheckGenerator(store),
    ([nextSteps, popular, resume, channels]) => {
      if (!channels.length) {
        return;
      }
      const featuredChannels = channels.slice(0, 3);
      const pageState = {
        // Hard to guarantee this uniqueness on the database side, so
        // do a uniqBy content_id here, to prevent confusing repeated
        // content items.
        nextSteps: _mapContentSet(nextSteps),
        popular: _mapContentSet(popular),
        resume: _mapContentSet(resume),
        featured: {},
      };
      featuredChannels.forEach(channel => {
        pageState.featured[channel.id] = [];
      });

      store.dispatch('SET_PAGE_STATE', pageState);

      featuredChannels.forEach(channel => {
        _getFeatured(state, channel.id).only(samePageCheckGenerator(store), featured => {
          store.dispatch('SET_FEATURED_CHANNEL_CONTENTS', channel.id, _mapContentSet(featured));
        });
      });

      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch('SET_PAGE_NAME', PageNames.RECOMMENDED);

      store.dispatch('CORE_SET_TITLE', translator.$tr('learnPageTitle'));
    },
    error => {
      handleApiError(store, error);
    }
  );
}

export function showPopularPage(store) {
  _showRecSubpage(store, _getPopular, PageNames.RECOMMENDED_POPULAR, 'popularPageTitle');
}

export function showResumePage(store) {
  _showRecSubpage(store, _getResume, PageNames.RECOMMENDED_RESUME, 'resumePageTitle');
}

export function showNextStepsPage(store) {
  _showRecSubpage(store, _getNextSteps, PageNames.RECOMMENDED_NEXT_STEPS, 'nextStepsPageTitle');
}

export function showFeaturedPage(store, channelId) {
  _showRecSubpage(
    store,
    _getFeatured,
    PageNames.RECOMMENDED_FEATURED,
    'featuredInChannelPageTitle',
    channelId
  );
}

export function showLearnContent(store, id) {
  store.dispatch('CORE_SET_PAGE_LOADING', true);
  store.dispatch('SET_PAGE_NAME', PageNames.RECOMMENDED_CONTENT);
  const contentPromise = ContentNodeResource.getModel(id).fetch();
  const recommendedPromise = ContentNodeResource.getCollection({
    recommendations_for: id,
  }).fetch();
  const channelsPromise = setChannelInfo(store);
  const nextContentPromise = ContentNodeResource.fetchNextContent(id);
  ConditionalPromise.all([contentPromise, nextContentPromise, channelsPromise]).only(
    samePageCheckGenerator(store),
    ([content, nextContent]) => {
      const pageState = {
        content: contentState(content, nextContent),
        recommended: store.state.pageState.recommended,
      };
      const currentChannel = getChannelObject(store.state, content.channel_id);
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_PAGE_LOADING', false);
      store.dispatch('CORE_SET_ERROR', null);
      store.dispatch(
        'CORE_SET_TITLE',
        translator.$tr('learnContentPageTitle', {
          currentContent: pageState.content.title,
          currentChannel: currentChannel.title,
        })
      );
    },
    error => {
      handleApiError(store, error);
    }
  );
  recommendedPromise.only(
    samePageCheckGenerator(store),
    recommended => {
      const pageState = {
        content: store.state.pageState.content,
        recommended: recommended.map(contentState),
      };
      store.dispatch('SET_PAGE_STATE', pageState);
      store.dispatch('CORE_SET_ERROR', null);
    },
    error => {
      handleApiError(store, error);
    }
  );
}
<|endoftext|>