<commit_before>class MCProcessesGraphComponentController {
    /*@ngInject*/
    constructor(experimentsService, templates, $stateParams, toast, $mdDialog) {
        this.experimentsService = experimentsService;
        this.templates = templates;
        this.toast = toast;
        this.cy = null;
        this.displayGraph = 'all_processes';
        this.projectId = $stateParams.project_id;
        this.experimentId = $stateParams.experiment_id;
        this.$mdDialog = $mdDialog;
        this.selectedProcess = null;
    }

    $onInit() {
        this.allProcessesGraph();
    }

    addProcess(templateId) {
        this.experimentsService.createProcessFromTemplate(this.projectId, this.experimentId, `global_${templateId}`)
            .then(
                (process) => {
                    let p = this.templates.loadTemplateFromProcess(process.template_name, process);
                    this.$mdDialog.show({
                        templateUrl: 'app/global.components/graph/new-process-dialog.html',
                        controllerAs: '$ctrl',
                        controller: NewProcessDialogController,
                        bindToController: true,
                        locals: {
                            process: p
                        }
                    }).then(
                        () => {
                            this.experimentsService.getProcessesForExperiment(this.projectId, this.experimentId)
                                .then(
                                    (processes) => {
                                        this.processes = processes;
                                        this.allProcessesGraph();
                                    },
                                    () => this.toast.error('Error retrieving processes for experiment')
                                );
                        }
                    );
                },
                () => this.toast.error('Unable to add samples')
            );
    }

    onChange() {
        this.experimentsService.getProcessesForExperiment(this.projectId, this.experimentId)
            .then(
                (processes) => {
                    this.processes = processes;
                    this.allProcessesGraph();
                },
                () => this.toast.error('Error retrieving processes for experiment')
            );
    }

    allProcessesGraph() {
        let sample2InputProcesses = {};
        let sample2OutputProcesses = {};

        this.processes.forEach(p => {
            p.input_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                if (!(id in sample2InputProcesses)) {
                    sample2InputProcesses[id] = [];
                }
                sample2InputProcesses[id].push(p);
            });

            p.output_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                if (!(id in sample2OutputProcesses)) {
                    sample2OutputProcesses[id] = [];
                }
                sample2OutputProcesses[id].push(p);
            })
        });

        // Draw all processes
        let elements = this.processes.map(p => {
            //console.log(p.name, p);
            return {
                data: {
                    id: p.id,
                    name: p.name,
                    color: p.does_transform ? 'red' : '#999999'
                }
            };
        });
        this.processes.filter(p => p.does_transform).forEach(p => {
            p.output_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                let processes = sample2InputProcesses[id];
                if (processes && processes.length) {
                    processes.forEach(proc => {
                        elements.push({
                            data: {
                                id: `${proc.id}_${p.id}`,
                                source: p.id,
                                target: proc.id
                            }
                        });
                    });
                }
            });
        });

        let sampleName2Sample = {};
        this.processes.forEach(p => {
            p.input_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
            p.output_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
        });
        this.samples = _.values(sampleName2Sample);
        this.cy = cytoscape({
            container: document.getElementById('processesGraph'),
            elements: elements,
            style: [
                {
                    selector: 'node',
                    style: {
                        'label': 'data(name)',
                        'background-color': 'data(color)'
                    }
                },
                {
                    selector: 'edge',
                    style: {
                        'width': 4,
                        'target-arrow-shape': 'triangle',
                        //'target-arrow-color': '#9dbaea',
                        'curve-style': 'bezier'
                    }
                }
            ]
        });
        this.cy.on('click', event => {
            let target = event.cyTarget;
            if (target.isNode()) {
                let processId = target.data('id');
                this.experimentsService.getProcessForExperiment(this.projectId, this.experimentId, processId)
                    .then(
                        (process) => {
                            this.selectedProcess = this.templates.loadProcess(process);
                        },
                        () => {
                            this.toast.error('Unable to retrieve process details');
                            this.selectedProcess = null;
                        }
                    );
            }
        });
        this.cy.layout({name: 'dagre'});
    }

    showSelectedGraph() {
        console.log('selected graph', this.displayGraph);
    }

    onlyTransformationProcessesGraph() {
        console.log('onlyTransformationProcessesGraph');
    }

    sampleTransformationGraph() {
        console.log('sampleTransformationGraph');
    }

    filterOnSample(sample) {
        //console.log('filterOnSample', sample);
        let matches = [];
        this.cy.nodes().forEach(node => {
            console.log(node.data('id'));
        });
        console.log('matches', matches);
    }

}

class NewProcessDialogController {
    /*@ngInject*/
    constructor($mdDialog) {
        this.$mdDialog = $mdDialog;
    }

    done() {
        this.$mdDialog.hide();
    }

    cancel() {
        this.$mdDialog.cancel();
    }
}

angular.module('materialscommons').component('mcProcessesGraph', {
    templateUrl: 'app/global.components/graph/mc-processes-graph.html',
    controller: MCProcessesGraphComponentController,
    bindings: {
        processes: '<'
    }
});
<commit_msg>Change colors of nodes. Change node style so that name moves to center of node. Set background outline for text. When a node is selected add a border to it so user can see which node was selected.<commit_after>class MCProcessesGraphComponentController {
    /*@ngInject*/
    constructor(experimentsService, templates, $stateParams, toast, $mdDialog) {
        this.experimentsService = experimentsService;
        this.templates = templates;
        this.toast = toast;
        this.cy = null;
        this.displayGraph = 'all_processes';
        this.projectId = $stateParams.project_id;
        this.experimentId = $stateParams.experiment_id;
        this.$mdDialog = $mdDialog;
        this.selectedProcess = null;
    }

    $onInit() {
        this.allProcessesGraph();
    }

    addProcess(templateId) {
        this.experimentsService.createProcessFromTemplate(this.projectId, this.experimentId, `global_${templateId}`)
            .then(
                (process) => {
                    let p = this.templates.loadTemplateFromProcess(process.template_name, process);
                    this.$mdDialog.show({
                        templateUrl: 'app/global.components/graph/new-process-dialog.html',
                        controllerAs: '$ctrl',
                        controller: NewProcessDialogController,
                        bindToController: true,
                        locals: {
                            process: p
                        }
                    }).then(
                        () => {
                            this.experimentsService.getProcessesForExperiment(this.projectId, this.experimentId)
                                .then(
                                    (processes) => {
                                        this.processes = processes;
                                        this.allProcessesGraph();
                                    },
                                    () => this.toast.error('Error retrieving processes for experiment')
                                );
                        }
                    );
                },
                () => this.toast.error('Unable to add samples')
            );
    }

    onChange() {
        this.experimentsService.getProcessesForExperiment(this.projectId, this.experimentId)
            .then(
                (processes) => {
                    this.processes = processes;
                    this.allProcessesGraph();
                },
                () => this.toast.error('Error retrieving processes for experiment')
            );
    }

    allProcessesGraph() {
        let sample2InputProcesses = {};
        let sample2OutputProcesses = {};

        this.processes.forEach(p => {
            p.input_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                if (!(id in sample2InputProcesses)) {
                    sample2InputProcesses[id] = [];
                }
                sample2InputProcesses[id].push(p);
            });

            p.output_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                if (!(id in sample2OutputProcesses)) {
                    sample2OutputProcesses[id] = [];
                }
                sample2OutputProcesses[id].push(p);
            })
        });

        // Draw all processes
        let elements = this.processes.map(p => {
            //console.log(p.name, p);
            return {
                data: {
                    id: p.id,
                    name: p.name,
                    color: p.does_transform ? 'red' : '#facd37'
                }
            };
        });
        this.processes.filter(p => p.does_transform).forEach(p => {
            p.output_samples.forEach(s => {
                let id = `${s.id}/${s.property_set_id}`;
                let processes = sample2InputProcesses[id];
                if (processes && processes.length) {
                    processes.forEach(proc => {
                        elements.push({
                            data: {
                                id: `${proc.id}_${p.id}`,
                                source: p.id,
                                target: proc.id
                            }
                        });
                    });
                }
            });
        });

        let sampleName2Sample = {};
        this.processes.forEach(p => {
            p.input_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
            p.output_samples.forEach(s => {
                sampleName2Sample[s.name] = s;
            });
        });
        this.samples = _.values(sampleName2Sample);
        this.cy = cytoscape({
            container: document.getElementById('processesGraph'),
            elements: elements,
            style: [
                {
                    selector: 'node',
                    style: {
                        'content': 'data(name)',
                        'text-valign': 'center',
                        'text-halign': 'center',
                        'background-color': 'data(color)',
                        color: 'black',
                        'text-outline-color': 'data(color)',
                        'font-size': '16px',
                        'font-weight': 'bold',
                        'text-outline-width': '4px',
                        'text-outline-opacity': 1,
                        'overlay-padding': '6px',
                        width: '80px',
                        height: '80px'
                    }
                },
                {
                    selector: 'edge',
                    style: {
                        'width': 4,
                        'target-arrow-shape': 'triangle',
                        //'target-arrow-color': '#9dbaea',
                        'curve-style': 'bezier'
                    }
                },
                {
                    selector: 'node:selected',
                    style: {
                        'border-width': '8px',
                        'border-color': '#1565c0',
                        'text-outline-color': '#1565c0'
                    }
                }
            ]
        });
        this.cy.on('click', event => {
            let target = event.cyTarget;
            if (target.isNode()) {
                let processId = target.data('id');
                this.experimentsService.getProcessForExperiment(this.projectId, this.experimentId, processId)
                    .then(
                        (process) => {
                            this.selectedProcess = this.templates.loadProcess(process);
                        },
                        () => {
                            this.toast.error('Unable to retrieve process details');
                            this.selectedProcess = null;
                        }
                    );
            }
        });
        this.cy.layout({name: 'dagre'});
    }

    showSelectedGraph() {
        console.log('selected graph', this.displayGraph);
    }

    onlyTransformationProcessesGraph() {
        console.log('onlyTransformationProcessesGraph');
    }

    sampleTransformationGraph() {
        console.log('sampleTransformationGraph');
    }

    filterOnSample(sample) {
        //console.log('filterOnSample', sample);
        let matches = [];
        this.cy.nodes().forEach(node => {
            console.log(node.data('id'));
        });
        console.log('matches', matches);
    }

}

class NewProcessDialogController {
    /*@ngInject*/
    constructor($mdDialog) {
        this.$mdDialog = $mdDialog;
    }

    done() {
        this.$mdDialog.hide();
    }

    cancel() {
        this.$mdDialog.cancel();
    }
}

angular.module('materialscommons').component('mcProcessesGraph', {
    templateUrl: 'app/global.components/graph/mc-processes-graph.html',
    controller: MCProcessesGraphComponentController,
    bindings: {
        processes: '<'
    }
});
<|endoftext|>


<commit_before>document.addEventListener('DOMContentLoaded', function() {
	'use strict';

	var FSPHYS_LOCALE = "de-DE";
	var DATE = '2017-09-11';
	var ER_VERSION = 'WS 2016/2017';
	var ID_PREFIX = 'fsphys_gc_';
	var INPUT_FIELDS = [
		'physics_1',
		'physics_2',
		'physics_3',
		'math_2',
		'math_3',
		'minor_1',
		'minor_2',
		'minor_3',
		'minor_1_weight',
		'minor_2_weight',
		'minor_3_weight',
		'quantum_mechanics',
		'signal_processing',
		'computational_physics',
		'structure_of_matter',
		'lab_course_1',
		'lab_course_2',
		'statistical_physics',
		'bachelor_thesis'
	]
	var DEFAULT_WEIGHTS = {
			"2016-11-17" : {
				minor:               12,
				quantum_mechanics:    7,
				signal_processing:    7,
				computational_physics:    0,
				structure_of_matter: 12,
				lab_course_1:         0,
				lab_course_2:         9,
				statistical_physics: 10,
				bachelor_thesis:     10,
				physics_X: 11,
				math_X: 11,
			},
			"2021-04-12" : {
				minor:               10,
				quantum_mechanics:    7,
				signal_processing:    6,
				computational_physics:   4,
				structure_of_matter: 10,
				lab_course_1:         4,
				lab_course_2:         9,
				statistical_physics: 10,
				bachelor_thesis:     10,
				physics_X: 10,
				physics_3: 10,
				math_2: 5,
				math_3: 5,
			},
	};

	var total_grade = 0;
	var exams = {
		// weights of the individual module grades towards the total grade
		// (percentages)
		weights: {
				minor:               12,
				quantum_mechanics:    7,
				signal_processing:    7,
				structure_of_matter: 12,
				lab_course_2:         9,
				statistical_physics: 10,
				bachelor_thesis:     10
		},
		version : "2016-11-17",

		update: function(user_input) {
			var e = document.getElementById("fsphys_gc_version");
			var version = e.value;

			this.weights = DEFAULT_WEIGHTS[version];

			var weights = this.weights;
			// special cases: Physics I–III, Math II–III and the minor
			var physics_weights;
			if(version == "2016-11-17") {
			 	physics_weights= this.best_of(
				['physics_1', 'physics_2', 'physics_3'], 2, this.weights["physics_X"], user_input);
				var math_weights = this.best_of(
				['math_2', 'math_3'], 1, this.weights["math_X"], user_input);
				for (name in math_weights) {
					weights[name] = math_weights[name];
				}
			}
			else if(version =="2021-04-12") {
			 	physics_weights= this.best_of(
				['physics_1', 'physics_2'], 1, this.weights["physics_X"], user_input);
			}
			for (name in physics_weights) {
				weights[name] = physics_weights[name];
			}

			weights.minor_1 = user_input.minor_1_weight;
			weights.minor_2 = user_input.minor_2_weight;
			weights.minor_3 = user_input.minor_3_weight;
		},

		best_of: function(exam_set, count, weight, user_input) {
			var weights = this.weights;
			// turn subset of user_input object into an array of key–value pairs
			// to be able to do sorting
			var grades = exam_set.map(function(key) {
				return {exam: key, grade: user_input[key]};
			});
			grades.sort(function(a, b) {
				return a.grade - b.grade;
			});
			var weights_set = {};
			grades.forEach(function(el, idx) {
				// exams up to entry number “count” get “weight”, others 0
				weights_set[el.exam] = idx < count ? weight : 0;
			});
			return weights_set;
		}
	};

	function load_url_data() {
		try {
			var url_fragment = decodeURIComponent(location.hash.substring(1));
			user_input = JSON.parse(url_fragment);
			INPUT_FIELDS.forEach(function(field) {
				var input = document.getElementById(ID_PREFIX + field);
				input.value = user_input[field];
			});
			// update for consistency
			update();
			// set document title to distinguish bookmarks
			var loc = "de-DE";
			switch (FSPHYS_LOCALE) {
				case 'en-US':
					var title_text = 'Saved bachelor’s grade: ';
					loc = "en-US";
					break;
				case 'de-DE':
				default:
					loc = "de-DE";
					var title_text = 'Gespeicherte Bachelor-Note: ';
					break;
			}
			var total_grade_str = total_grade.toLocaleString(loc,
					{minimumFractionDigits: 2, maximumFractionDigits: 2});
			var re = /\[.+\]/;
			if (re.test(document.title)) {
				document.title = document.title.replace(re,
					'[' + title_text + total_grade_str + ']');
			}
			else {
				document.title += ' [' + title_text + total_grade_str + ']';
			}
		}
		catch (e) {
			console.log(e);
		}
	}

	function update() {
		// update user_input
		INPUT_FIELDS.forEach(function(field) {
			var input = document.getElementById(ID_PREFIX + field);
			user_input[field] = Number(input.value);
		});
		// update exam weights
		exams.update(user_input);
		// get minor grade and total grade using weights
		// divide by 100 because of percentages and round to 2 decimal places
		var weights = exams.weights;
		// minor grade
		var minor_grade = 0;
		for (var exam in weights) {
			// build minor grade from values starting with 'minor_'
			if (exam.indexOf('minor_') === 0) {
				minor_grade += user_input[exam] * weights[exam];
			}
		}
		minor_grade /= 100;
		user_input.minor = minor_grade;
		minor_grade = minor_grade.toLocaleString(FSPHYS_LOCALE,
			{minimumFractionDigits: 2, maximumFractionDigits: 2});
		// total grade
		total_grade = 0;
		for (var exam in weights) {
			if (exam.indexOf('minor_') !== 0 && user_input[exam] !== undefined) {
				total_grade += user_input[exam] * weights[exam];
			}
		}
		total_grade = (total_grade / 100).toLocaleString(FSPHYS_LOCALE,
			{minimumFractionDigits: 2, maximumFractionDigits: 2});
		// write (possibly updated) weight information to DOM
		for (var exam in exams.weights) {
			var text_el = document.getElementById(ID_PREFIX + exam + '_weight');
			if(text_el !== null)
				text_el.textContent = exams.weights[exam];
		}
		// write calculated grades to DOM
		document.getElementById(ID_PREFIX + 'minor').textContent = minor_grade;
		document.getElementById(ID_PREFIX + 'total').textContent = total_grade;
	}

	function write_url_fragment() {
		location.hash = JSON.stringify(user_input);
	}

	// initialize user input data
	// manually set minor because there is no element with the same name
	// included in INPUT_FIELDS
	var user_input = {minor: 0};
	var url_fragment_set = Boolean(location.hash);
	// try to parse input data from URL fragment if provided
	if (url_fragment_set) {
		load_url_data();
	}
	// update with changes to URL fragment
	window.addEventListener('hashchange', load_url_data);
	// print version information
	//document.getElementById(ID_PREFIX + 'version').textContent = DATE;
	//TODO document.getElementById(ID_PREFIX + 'er_version').textContent = ER_VERSION;
	// update on user input
	var gc_form = document.getElementById(ID_PREFIX + 'form');
	gc_form.addEventListener('input', update);
	// assign action to save button
	//TODO document.getElementById(ID_PREFIX + 'save').onclick = write_url_fragment;
	// run update to initialize input_data and for consistency
	update();
});

<commit_msg>Reactivate save+locale<commit_after>document.addEventListener('DOMContentLoaded', function() {
	'use strict';

	//var FSPHYS_LOCALE = "de-DE";
	var DATE = '2017-09-11';
	var ER_VERSION = 'WS 2016/2017';
	var ID_PREFIX = 'fsphys_gc_';
	var INPUT_FIELDS = [
		'physics_1',
		'physics_2',
		'physics_3',
		'math_2',
		'math_3',
		'minor_1',
		'minor_2',
		'minor_3',
		'minor_1_weight',
		'minor_2_weight',
		'minor_3_weight',
		'quantum_mechanics',
		'signal_processing',
		'computational_physics',
		'structure_of_matter',
		'lab_course_1',
		'lab_course_2',
		'statistical_physics',
		'bachelor_thesis'
	]
	var DEFAULT_WEIGHTS = {
			"2016-11-17" : {
				minor:               12,
				quantum_mechanics:    7,
				signal_processing:    7,
				computational_physics:    0,
				structure_of_matter: 12,
				lab_course_1:         0,
				lab_course_2:         9,
				statistical_physics: 10,
				bachelor_thesis:     10,
				physics_X: 11,
				math_X: 11,
			},
			"2021-04-12" : {
				minor:               10,
				quantum_mechanics:    7,
				signal_processing:    6,
				computational_physics:   4,
				structure_of_matter: 10,
				lab_course_1:         4,
				lab_course_2:         9,
				statistical_physics: 10,
				bachelor_thesis:     10,
				physics_X: 10,
				physics_3: 10,
				math_2: 5,
				math_3: 5,
			},
	};

	var total_grade = 0;
	var exams = {
		// weights of the individual module grades towards the total grade
		// (percentages)
		weights: {
				minor:               12,
				quantum_mechanics:    7,
				signal_processing:    7,
				structure_of_matter: 12,
				lab_course_2:         9,
				statistical_physics: 10,
				bachelor_thesis:     10
		},
		version : "2016-11-17",

		update: function(user_input) {
			var e = document.getElementById("fsphys_gc_version");
			var version = e.value;

			this.weights = DEFAULT_WEIGHTS[version];

			var weights = this.weights;
			// special cases: Physics I–III, Math II–III and the minor
			var physics_weights;
			if(version == "2016-11-17") {
			 	physics_weights= this.best_of(
				['physics_1', 'physics_2', 'physics_3'], 2, this.weights["physics_X"], user_input);
				var math_weights = this.best_of(
				['math_2', 'math_3'], 1, this.weights["math_X"], user_input);
				for (name in math_weights) {
					weights[name] = math_weights[name];
				}
			}
			else if(version =="2021-04-12") {
			 	physics_weights= this.best_of(
				['physics_1', 'physics_2'], 1, this.weights["physics_X"], user_input);
			}
			for (name in physics_weights) {
				weights[name] = physics_weights[name];
			}

			weights.minor_1 = user_input.minor_1_weight;
			weights.minor_2 = user_input.minor_2_weight;
			weights.minor_3 = user_input.minor_3_weight;
		},

		best_of: function(exam_set, count, weight, user_input) {
			var weights = this.weights;
			// turn subset of user_input object into an array of key–value pairs
			// to be able to do sorting
			var grades = exam_set.map(function(key) {
				return {exam: key, grade: user_input[key]};
			});
			grades.sort(function(a, b) {
				return a.grade - b.grade;
			});
			var weights_set = {};
			grades.forEach(function(el, idx) {
				// exams up to entry number “count” get “weight”, others 0
				weights_set[el.exam] = idx < count ? weight : 0;
			});
			return weights_set;
		}
	};

	function load_url_data() {
		try {
			var url_fragment = decodeURIComponent(location.hash.substring(1));
			user_input = JSON.parse(url_fragment);
			INPUT_FIELDS.forEach(function(field) {
				var input = document.getElementById(ID_PREFIX + field);
				input.value = user_input[field];
			});
			// update for consistency
			update();
			// set document title to distinguish bookmarks
			var loc = "de-DE";
			switch (FSPHYS_LOCALE) {
				case 'en-US':
					var title_text = 'Saved bachelor’s grade: ';
					loc = "en-US";
					break;
				case 'de-DE':
				default:
					loc = "de-DE";
					var title_text = 'Gespeicherte Bachelor-Note: ';
					break;
			}
			var total_grade_str = total_grade.toLocaleString(loc,
					{minimumFractionDigits: 2, maximumFractionDigits: 2});
			var re = /\[.+\]/;
			if (re.test(document.title)) {
				document.title = document.title.replace(re,
					'[' + title_text + total_grade_str + ']');
			}
			else {
				document.title += ' [' + title_text + total_grade_str + ']';
			}
		}
		catch (e) {
			console.log(e);
		}
	}

	function update() {
		// update user_input
		INPUT_FIELDS.forEach(function(field) {
			var input = document.getElementById(ID_PREFIX + field);
			user_input[field] = Number(input.value);
		});
		// update exam weights
		exams.update(user_input);
		// get minor grade and total grade using weights
		// divide by 100 because of percentages and round to 2 decimal places
		var weights = exams.weights;
		// minor grade
		var minor_grade = 0;
		for (var exam in weights) {
			// build minor grade from values starting with 'minor_'
			if (exam.indexOf('minor_') === 0) {
				minor_grade += user_input[exam] * weights[exam];
			}
		}
		minor_grade /= 100;
		user_input.minor = minor_grade;
		minor_grade = minor_grade.toLocaleString(FSPHYS_LOCALE,
			{minimumFractionDigits: 2, maximumFractionDigits: 2});
		// total grade
		total_grade = 0;
		for (var exam in weights) {
			if (exam.indexOf('minor_') !== 0 && user_input[exam] !== undefined) {
				total_grade += user_input[exam] * weights[exam];
			}
		}
		total_grade = (total_grade / 100).toLocaleString(FSPHYS_LOCALE,
			{minimumFractionDigits: 2, maximumFractionDigits: 2});
		// write (possibly updated) weight information to DOM
		for (var exam in exams.weights) {
			var text_el = document.getElementById(ID_PREFIX + exam + '_weight');
			if(text_el !== null)
				text_el.textContent = exams.weights[exam];
		}
		// write calculated grades to DOM
		document.getElementById(ID_PREFIX + 'minor').textContent = minor_grade;
		document.getElementById(ID_PREFIX + 'total').textContent = total_grade;
	}

	function write_url_fragment() {
		location.hash = JSON.stringify(user_input);
	}

	// initialize user input data
	// manually set minor because there is no element with the same name
	// included in INPUT_FIELDS
	var user_input = {minor: 0};
	var url_fragment_set = Boolean(location.hash);
	// try to parse input data from URL fragment if provided
	if (url_fragment_set) {
		load_url_data();
	}
	// update with changes to URL fragment
	window.addEventListener('hashchange', load_url_data);
	// print version information
	//document.getElementById(ID_PREFIX + 'version').textContent = DATE;
	//TODO document.getElementById(ID_PREFIX + 'er_version').textContent = ER_VERSION;
	// update on user input
	var gc_form = document.getElementById(ID_PREFIX + 'form');
	gc_form.addEventListener('input', update);
	// assign action to save button
	document.getElementById(ID_PREFIX + 'save').onclick = write_url_fragment;
	// run update to initialize input_data and for consistency
	update();
});

<|endoftext|>


<commit_before>/* Slovak initialisation for the jQuery UI date picker plugin. */
/* Written by Vojtech Rinik (vojto@hmm.sk). */
jQuery(function($){
	$.datepicker.regional['sk'] = {
		closeText: 'Zavrieť',
		prevText: '<Predchádzajúci',
		nextText: 'Nasledujúci>',
		currentText: 'Dnes',
		monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
		'Júl','August','September','Október','November','December'],
		monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
		'Júl','Aug','Sep','Okt','Nov','Dec'],
		dayNames: ['Nedel\'a','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
		dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
		dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
		weekHeader: 'Ty',
		dateFormat: 'dd.mm.yy',
		firstDay: 1,
		isRTL: false,
		showMonthAfterYear: false,
		yearSuffix: ''};
	$.datepicker.setDefaults($.datepicker.regional['sk']);
});
<commit_msg>Datepicker: Fixed Slovak locale. Fixes #7254 - Datepicker: Incorrect day name for Slovak localization.<commit_after>/* Slovak initialisation for the jQuery UI date picker plugin. */
/* Written by Vojtech Rinik (vojto@hmm.sk). */
jQuery(function($){
	$.datepicker.regional['sk'] = {
		closeText: 'Zavrieť',
		prevText: '<Predchádzajúci',
		nextText: 'Nasledujúci>',
		currentText: 'Dnes',
		monthNames: ['Január','Február','Marec','Apríl','Máj','Jún',
		'Júl','August','September','Október','November','December'],
		monthNamesShort: ['Jan','Feb','Mar','Apr','Máj','Jún',
		'Júl','Aug','Sep','Okt','Nov','Dec'],
		dayNames: ['Nedeľa','Pondelok','Utorok','Streda','Štvrtok','Piatok','Sobota'],
		dayNamesShort: ['Ned','Pon','Uto','Str','Štv','Pia','Sob'],
		dayNamesMin: ['Ne','Po','Ut','St','Št','Pia','So'],
		weekHeader: 'Ty',
		dateFormat: 'dd.mm.yy',
		firstDay: 1,
		isRTL: false,
		showMonthAfterYear: false,
		yearSuffix: ''};
	$.datepicker.setDefaults($.datepicker.regional['sk']);
});
<|endoftext|>


<commit_before>import map from 'lodash/collection/map';
import without from 'lodash/array/without';
import reject from 'lodash/collection/reject';
import contains from 'lodash/collection/contains';
import qnaDialogTemplate from '../../templates/qna_dialog';

class QuestionGridController {
    constructor($scope, $http, $mdDialog, randomImage, prefetchImage, toast) {
        let $content = angular.element(document.querySelector('.questionGrid')),
            addImage = function(url) {
                this.image = url;
                $scope.gettingImages = false;
                $scope.questions.push(this);
                getImagesWhileGridHasVisibleEmptySpace();
            },
            handlePlaceholderImgErr = function() {
                $scope.gettingImages = false;
                $scope.placeholderFail = true;
            },
            gridHasVisibleEmptySpace = function() {
                let noVisibleEmptySpace = [],
                    scrollOffset = $content[0].offsetHeight + $content[0].scrollTop;

                angular.forEach(document.querySelectorAll('.column'), function(col) {
                    let lastTile = col.children[col.children.length - 1],
                        tileOffset = lastTile.offsetTop + lastTile.offsetHeight;

                    noVisibleEmptySpace.push(tileOffset > scrollOffset);
                });

                return !(contains(noVisibleEmptySpace, true) &&
                without(noVisibleEmptySpace, false).length === noVisibleEmptySpace.length);
            },
            getImagesWhileGridHasVisibleEmptySpace = function() {
                let {view, gettingImages, noQuestions, imageFail, placeholderFail} = $scope;

                if (view.current === 'qna' && !gettingImages && !noQuestions && !imageFail && !placeholderFail && gridHasVisibleEmptySpace()) {
                    $scope.gettingImages = true;

                    $http.get('question/grid', {params: {exclude: map($scope.questions, 'id')}})
                        .then(function({data}) {
                            if (data) {
                                return prefetchImage(data.image || randomImage(), $scope.corsPort)
                                    .then(addImage.bind(data))
                                    .catch(function() {
                                        if (data.image) {
                                            return prefetchImage(randomImage(), $scope.corsPort)
                                                .then(addImage.bind(data))
                                                .catch(handlePlaceholderImgErr);
                                        }

                                        handlePlaceholderImgErr();
                                    });
                            }

                            if (!$scope.questions.length) {
                                $scope.noQuestions = true;
                            }

                            $scope.gettingImages = false;

                        }).catch(function() {
                            $scope.imageFail = true;
                            $scope.gettingImages = false;
                        });
                }
            };

        Object.assign($scope, {
            questions: [],
            imageClicked(e, id) {
                $http.get('qna', {params: {id}}).then(function({data}) {
                    $mdDialog.show({
                        clickOutsideToClose: true,
                        controller: 'qnaDialogController',
                        template: qnaDialogTemplate(),
                        parent: angular.element(document.body),
                        targetEvent: e,
                        locals: {qna: data}
                    }).then(function() {
                        $scope.questions = reject($scope.questions, 'id', id);
                        getImagesWhileGridHasVisibleEmptySpace();
                    }).finally(function() {
                        toast.hide();
                    });
                }).catch(function() {
                    toast.show('Unable to get QnA');
                });
            }
        });

        $content.bind('scroll', getImagesWhileGridHasVisibleEmptySpace);

        getImagesWhileGridHasVisibleEmptySpace();
    }
}

QuestionGridController.$inject = [
    '$scope',
    '$http',
    '$mdDialog',
    'randomImageFactory',
    'prefetchImageFactory',
    'toastFactory'
];

export default QuestionGridController;<commit_msg>Fetch more question images when qna becomes the active view<commit_after>import map from 'lodash/collection/map';
import without from 'lodash/array/without';
import reject from 'lodash/collection/reject';
import contains from 'lodash/collection/contains';
import qnaDialogTemplate from '../../templates/qna_dialog';

class QuestionGridController {
    constructor($scope, $http, $mdDialog, randomImage, prefetchImage, toast) {
        let $content = angular.element(document.querySelector('.questionGrid')),
            addImage = function(url) {
                this.image = url;
                $scope.gettingImages = false;
                $scope.questions.push(this);
                getImagesWhileGridHasVisibleEmptySpace();
            },
            handlePlaceholderImgErr = function() {
                $scope.gettingImages = false;
                $scope.placeholderFail = true;
            },
            gridHasVisibleEmptySpace = function() {
                let noVisibleEmptySpace = [],
                    scrollOffset = $content[0].offsetHeight + $content[0].scrollTop;

                angular.forEach(document.querySelectorAll('.column'), function(col) {
                    let lastTile = col.children[col.children.length - 1],
                        tileOffset = lastTile.offsetTop + lastTile.offsetHeight;

                    noVisibleEmptySpace.push(tileOffset > scrollOffset);
                });

                return !(contains(noVisibleEmptySpace, true) &&
                without(noVisibleEmptySpace, false).length === noVisibleEmptySpace.length);
            },
            getImagesWhileGridHasVisibleEmptySpace = function() {
                let {view, gettingImages, noQuestions, imageFail, placeholderFail} = $scope;

                if (view.current === 'qna' && !gettingImages && !noQuestions && !imageFail && !placeholderFail && gridHasVisibleEmptySpace()) {
                    $scope.gettingImages = true;

                    $http.get('question/grid', {params: {exclude: map($scope.questions, 'id')}})
                        .then(function({data}) {
                            if (data) {
                                return prefetchImage(data.image || randomImage(), $scope.corsPort)
                                    .then(addImage.bind(data))
                                    .catch(function() {
                                        if (data.image) {
                                            return prefetchImage(randomImage(), $scope.corsPort)
                                                .then(addImage.bind(data))
                                                .catch(handlePlaceholderImgErr);
                                        }

                                        handlePlaceholderImgErr();
                                    });
                            }

                            if (!$scope.questions.length) {
                                $scope.noQuestions = true;
                            }

                            $scope.gettingImages = false;

                        }).catch(function() {
                            $scope.imageFail = true;
                            $scope.gettingImages = false;
                        });
                }
            };

        Object.assign($scope, {
            questions: [],
            imageClicked(e, id) {
                $http.get('qna', {params: {id}}).then(function({data}) {
                    $mdDialog.show({
                        clickOutsideToClose: true,
                        controller: 'qnaDialogController',
                        template: qnaDialogTemplate(),
                        parent: angular.element(document.body),
                        targetEvent: e,
                        locals: {qna: data}
                    }).then(function() {
                        $scope.questions = reject($scope.questions, 'id', id);
                        getImagesWhileGridHasVisibleEmptySpace();
                    }).finally(function() {
                        toast.hide();
                    });
                }).catch(function() {
                    toast.show('Unable to get QnA');
                });
            }
        });

        $content.bind('scroll', getImagesWhileGridHasVisibleEmptySpace);

        $scope.$watch('view.current', function(newView) {
            if (newView === 'qna') {
                getImagesWhileGridHasVisibleEmptySpace();
            }
        });
    }
}

QuestionGridController.$inject = [
    '$scope',
    '$http',
    '$mdDialog',
    'randomImageFactory',
    'prefetchImageFactory',
    'toastFactory'
];

export default QuestionGridController;<|endoftext|>


<commit_before>var m = require('mithril');
var util = require('chessground').util;
var tds = require('../util').tds;
var hookRepo = require('../../hookRepo');

function renderHook(ctrl, hook) {
  return m('tr', {
    key: hook.id,
    title: (hook.action === 'join') ? ctrl.trans('joinTheGame') + ' - ' + hook.perf.name : ctrl.trans('cancel'),
    'data-id': hook.id,
    class: 'hook ' + hook.action + (hook.disabled ? ' disabled' : '')
  }, tds([
    m('span', {
      class: 'is is2 color-icon ' + (hook.color || 'random')
    }), (hook.rating ? m('a.ulink', {
      href: '/@/' + hook.username
    }, hook.username) : 'Anonymous'),
    hook.rating ? hook.rating : '',
    hook.clock, [m('span', {
      class: 'varicon',
      'data-icon': hook.perf.icon
    }), ctrl.trans(hook.mode === 1 ? 'rated' : 'casual')]
  ]));
};

function isStandard(value) {
  return function(hook) {
    return (hook.variant === 'STD') === value;
  };
}

module.exports = {
  toggle: function(ctrl) {
    return m('span', {
      'data-hint': ctrl.trans('graph'),
      class: 'mode_toggle hint--bottom',
      onclick: util.partial(ctrl.setMode, 'chart')
    }, m('span.chart[data-icon=9]'));
  },
  render: function(ctrl, allHooks) {
    var max = 14;
    var hooks = allHooks.slice(0, max);
    var render = util.partial(renderHook, ctrl);
    var standards = hooks.filter(isStandard(true));
    hookRepo.sort(ctrl, standards);
    var variants = hooks.filter(isStandard(false))
      .slice(0, Math.max(0, max - standards.length - 1));
    hookRepo.sort(ctrl, variants);
    return m('table.table_wrap', [
      m('thead',
        m('tr', [
          m('th'),
          m('th', ctrl.trans('player')),
          m('th', {
            class: util.classSet({
              sortable: true,
              sort: ctrl.vm.sort === 'rating'
            }),
            onclick: util.partial(ctrl.setSort, 'rating')
          }, [m('i.is'), ctrl.trans('rating')]),
          m('th', {
            class: util.classSet({
              sortable: true,
              sort: ctrl.vm.sort === 'time'
            }),
            onclick: util.partial(ctrl.setSort, 'time')
          }, [m('i.is'), ctrl.trans('time')]),
          m('th', ctrl.trans('mode'))
        ])
      ),
      m('tbody', {
        class: ctrl.vm.stepping ? 'stepping' : '',
        onclick: function(e) {
          var el = e.target;
          if (el.classList.contains('ulink')) return;
          do {
            el = el.parentNode;
            if (el.nodeName === 'TR') return ctrl.clickHook(el.getAttribute('data-id'));
          }
          while (el.nodeName !== 'TABLE');
        }
      }, [
        standards.map(render),
        variants.length ? m('tr.variants', {
            key: 'variants',
          },
          m('td', {
            colspan: 5
          }, '— ' + ctrl.trans('variant') + ' —')
        ) : null,
        variants.map(render)
      ])
    ]);
  }
};
<commit_msg>disabled lobby hooks have no title<commit_after>var m = require('mithril');
var util = require('chessground').util;
var tds = require('../util').tds;
var hookRepo = require('../../hookRepo');

function renderHook(ctrl, hook) {
  return m('tr', {
    key: hook.id,
    title: hook.disabled ? '' : (
      (hook.action === 'join') ? ctrl.trans('joinTheGame') + ' - ' + hook.perf.name : ctrl.trans('cancel')
    ),
    'data-id': hook.id,
    class: 'hook ' + hook.action + (hook.disabled ? ' disabled' : '')
  }, tds([
    m('span', {
      class: 'is is2 color-icon ' + (hook.color || 'random')
    }), (hook.rating ? m('a.ulink', {
      href: '/@/' + hook.username
    }, hook.username) : 'Anonymous'),
    hook.rating ? hook.rating : '',
    hook.clock, [m('span', {
      class: 'varicon',
      'data-icon': hook.perf.icon
    }), ctrl.trans(hook.mode === 1 ? 'rated' : 'casual')]
  ]));
};

function isStandard(value) {
  return function(hook) {
    return (hook.variant === 'STD') === value;
  };
}

module.exports = {
  toggle: function(ctrl) {
    return m('span', {
      'data-hint': ctrl.trans('graph'),
      class: 'mode_toggle hint--bottom',
      onclick: util.partial(ctrl.setMode, 'chart')
    }, m('span.chart[data-icon=9]'));
  },
  render: function(ctrl, allHooks) {
    var max = 14;
    var hooks = allHooks.slice(0, max);
    var render = util.partial(renderHook, ctrl);
    var standards = hooks.filter(isStandard(true));
    hookRepo.sort(ctrl, standards);
    var variants = hooks.filter(isStandard(false))
      .slice(0, Math.max(0, max - standards.length - 1));
    hookRepo.sort(ctrl, variants);
    return m('table.table_wrap', [
      m('thead',
        m('tr', [
          m('th'),
          m('th', ctrl.trans('player')),
          m('th', {
            class: util.classSet({
              sortable: true,
              sort: ctrl.vm.sort === 'rating'
            }),
            onclick: util.partial(ctrl.setSort, 'rating')
          }, [m('i.is'), ctrl.trans('rating')]),
          m('th', {
            class: util.classSet({
              sortable: true,
              sort: ctrl.vm.sort === 'time'
            }),
            onclick: util.partial(ctrl.setSort, 'time')
          }, [m('i.is'), ctrl.trans('time')]),
          m('th', ctrl.trans('mode'))
        ])
      ),
      m('tbody', {
        class: ctrl.vm.stepping ? 'stepping' : '',
        onclick: function(e) {
          var el = e.target;
          if (el.classList.contains('ulink')) return;
          do {
            el = el.parentNode;
            if (el.nodeName === 'TR') return ctrl.clickHook(el.getAttribute('data-id'));
          }
          while (el.nodeName !== 'TABLE');
        }
      }, [
        standards.map(render),
        variants.length ? m('tr.variants', {
            key: 'variants',
          },
          m('td', {
            colspan: 5
          }, '— ' + ctrl.trans('variant') + ' —')
        ) : null,
        variants.map(render)
      ])
    ]);
  }
};
<|endoftext|>


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

  moj.Modules.LabelSelect = {
    el: '.js-LabelSelect',

    init: function () {
      this.cacheEls();
      this.bindEvents();

      // keep current state
      this.$options.each(function () {
        var $el = $(this);
        if($el.is(':checked')){
          $el.parent().addClass('is-selected');
        }
      });
    },

    bindEvents: function () {
      this.$options
        .on('change', function () {
          var $el = $(this),
              $parent = $el.parent('label');

          // clear out all other selections on radio elements
          if ($el.attr('type') === 'radio') {
            $('[name=' + $el.attr('name') + ']').parent('label').removeClass('is-selected');
          }

          // set is-selected state on check
          if($el.is(':checked')){
            $parent.addClass('is-selected');
          } else {
            $parent.removeClass('is-selected');
          }
        });
    },

    cacheEls: function () {
      this.$options = $(this.el).find('input[type=radio], input[type=checkbox]');
    }
  };
}());<commit_msg>Add render function to label select js module<commit_after>(function () {
  'use strict';

  moj.Modules.LabelSelect = {
    el: '.js-LabelSelect',

    init: function () {
      _.bindAll(this, 'render');
      this.cacheEls();
      this.bindEvents();
    },

    bindEvents: function () {
      this.$options
        .on('change', function () {
          var $el = $(this),
              $parent = $el.parent('label');

          // clear out all other selections on radio elements
          if ($el.attr('type') === 'radio') {
            $('[name=' + $el.attr('name') + ']').parent('label').removeClass('is-selected');
          }

          // set is-selected state on check
          if($el.is(':checked')){
            $parent.addClass('is-selected');
          } else {
            $parent.removeClass('is-selected');
          }
        });

      moj.Events.on('render LabelSelect.render', this.render);
    },

    cacheEls: function () {
      this.$options = $(this.el).find('input[type=radio], input[type=checkbox]');
    },

    render: function () {
      // keep current state
      this.$options.each(function () {
        var $el = $(this);
        if($el.is(':checked')){
          $el.parent().addClass('is-selected');
        }
      });
    }
  };
}());<|endoftext|>


<commit_before>'use strict';

describe('controllers', function() {
  beforeEach(module('polyflix'));

  // it('should ....', inject(function($controller) {
  //   console.log('controller',$controller);
  //   var moviesCtrl = $controller('MoviesCtrl');
  //   expect(moviesCtrl).toBeDefined();
  // }));
});<commit_msg>Base test for movies controller<commit_after>'use strict';

describe('controllers', function() {
  var httpBackend, scope, createController;
  beforeEach(module('polyflix'));

  beforeEach(inject(function($rootScope, $httpBackend, $controller) {
    httpBackend = $httpBackend;
    scope = $rootScope.$new();

    createController = function() {
        return $controller('MoviesCtrl', {
            '$scope': scope
        });
    };
  }));

  describe('controller', function() {
    it('should exist', function() {
      var controller = createController();
      expect(controller).toBeDefined();
    });
  });
});<|endoftext|>


<commit_before>var Kc = Kc || {};
Kc.LineItemTable = Kc.LineItemTable || {};
(function(namespace, jQuery) {
    /**
     * Setup the lineItem table's click handler for disclosures
     *
     * @param $lineItemTable the table jQuery object
     */
    namespace.setupLineItemTable = function($lineItemTable) {
        $lineItemTable.on("click", ".uif-lineItem-disclosure", function(){
            var $link = jQuery(this);
            var $lineItemRow = $link.closest("tr");

            var id = $lineItemRow.attr("id");
            var $children = jQuery("[data-parent_row='" + id + "']");

            // Hide or reopen children if they wer open previously
            if ($children.is(":visible")) {
                Kc.LineItemTable.hideSubItems($children);
                $children.hide(400);
                $lineItemRow.data("open", false);
            }
            else {
                $children.show(400);
                Kc.LineItemTable.showSubItems($children);
                $lineItemRow.data("open", true);
            }
        });
    }

    /**
     * Hide the sub items passed in for a lineItem disclosure and its child items also
     *
     * @param $items the items fo the line item to hide
     */
    namespace.hideSubItems = function($items) {
        $items.each(function(){
            var id = jQuery(this).attr("id");
            var $children = jQuery("[data-parent_row='" + id + "']");

            if ($children.length) {
                Kc.LineItemTable.hideSubItems($children);
            }
            $children.hide(400);
        });
    }

    /**
     * Reopen sub items of the line item and its children, if they were in an open state previously
     *
     * @param $items the items of the line item to reopen
     */
    namespace.showSubItems = function($items) {
        $items.each(function(){
            var id = jQuery(this).attr("id");
            var $children = jQuery("[data-parent_row='" + id + "']");

            if (jQuery(this).data("open")) {
                if ($children.length) {
                    Kc.LineItemTable.showSubItems($children);
                }
                $children.show(400);
            }
        });
    }

    /**
     * Scrolls the period columns of the line item table back one previous period
     *
     * @param button the previous period button (it must be in the header of the group)
     */
    namespace.prevPeriod = function(button) {
        // When when scrolling to a previous period make sure next button is enabled
        var nextButton = jQuery(button).next();
        nextButton.prop('disabled', false);
        nextButton.removeClass("disabled");

        // Find the id of the table by using the parent header for this button
        var tableId = jQuery(button).closest("header").data("header_for") + "_table";

        // Period columns represented by the th in thead
        var columns = jQuery("#" + tableId + " thead tr").find(":not(:first-child, .uif-lineItem-rowTotal)");

        // The last visible column of periods is the one that will be hidden
        var hideColumn = columns.filter(":visible:last");
        hideColumn.hide();
        var hideIndex = columns.index(hideColumn);

        // The column before the first visible column of periods is the one that will be shown
        var showColumn = columns.filter(":visible:first").prev();
        var showIndex = columns.index(showColumn);
        showColumn.show();

        // Disable the previous button if the first column (index 0) of periods is currently showing
        if (columns.eq(0).is(":visible")) {
            jQuery(button).prop('disabled', true);
        }

        // Iterate over each row and hide the columns we are hiding by index, and show the columns we are showing by index
        jQuery("#" + tableId + " tbody tr").each(function(){
            var columns = jQuery(this).find(":not(:first-child, .uif-lineItem-rowTotal)");
            columns.eq(hideIndex).hide();
            columns.eq(showIndex).show();
        });
    }

    /**
     * Scrolls the period columns of the line item table forward to the next period
     *
     * @param button the next period button (it must be in the header of the group)
     */
    namespace.nextPeriod = function (button) {
        // When when scrolling to a next period make sure previous button is enabled
        var prevButton = jQuery(button).prev();
        prevButton.prop('disabled', false);
        prevButton.removeClass("disabled");

        // Find the id of the table by using the parent header for this button
        var tableId = jQuery(button).closest("header").data("header_for") + "_table";

        // Period columns represented by the th in thead
        var columns = jQuery("#" + tableId + " thead tr").find(":not(:first-child, .uif-lineItem-rowTotal)");

        // Hide the first visible column
        var hideColumn = columns.filter(":visible:first");
        var hideIndex = columns.index(hideColumn);
        hideColumn.hide();

        // The column that is the first hidden column of the items after the column we are hiding
        var showColumn = hideColumn.nextAll(":hidden:first");
        var showIndex = columns.index(showColumn);
        showColumn.show();

        // Disable the previous button if the first column (index 0) of periods is currently showing
        if (showColumn.nextAll(":hidden").length === 0) {
            jQuery(button).prop('disabled', true);
        }

        // Iterate over each row and hide and show the columns by index discovered above
        jQuery("#" + tableId + " tbody tr").each(function(){
            var columns = jQuery(this).find(":not(:first-child, .uif-lineItem-rowTotal)");
            columns.eq(hideIndex).hide();
            columns.eq(showIndex).show();
        });
    }

})(Kc.LineItemTable, jQuery);<commit_msg>KRACOEUS-7844 small js style fixes<commit_after>var Kc = Kc || {};
Kc.LineItemTable = Kc.LineItemTable || {};
(function(namespace, $) {
    /**
     * Setup the lineItem table's click handler for disclosures
     *
     * @param $lineItemTable the table $ object
     */
    namespace.setupLineItemTable = function($lineItemTable) {
        $lineItemTable.on("click", ".uif-lineItem-disclosure", function(){
            var $link = $(this);
            var $lineItemRow = $link.closest("tr");

            var id = $lineItemRow.attr("id");
            var $children = $("[data-parent_row='" + id + "']");

            // Hide or reopen children if they wer open previously
            if ($children.is(":visible")) {
                namespace.hideSubItems($children);
                $children.hide(400);
                $lineItemRow.data("open", false);
            }
            else {
                $children.show(400);
                namespace.showSubItems($children);
                $lineItemRow.data("open", true);
            }
        });
    }

    /**
     * Hide the sub items passed in for a lineItem disclosure and its child items also
     *
     * @param $items the items fo the line item to hide
     */
    namespace.hideSubItems = function($items) {
        $items.each(function(){
            var id = $(this).attr("id");
            var $children = $("[data-parent_row='" + id + "']");

            if ($children.length) {
                namespace.hideSubItems($children);
            }
            $children.hide(400);
        });
    }

    /**
     * Reopen sub items of the line item and its children, if they were in an open state previously
     *
     * @param $items the items of the line item to reopen
     */
    namespace.showSubItems = function($items) {
        $items.each(function(){
            var id = $(this).attr("id");
            var $children = $("[data-parent_row='" + id + "']");

            if ($(this).data("open")) {
                if ($children.length) {
                    namespace.showSubItems($children);
                }
                $children.show(400);
            }
        });
    }

    /**
     * Scrolls the period columns of the line item table back one previous period
     *
     * @param button the previous period button (it must be in the header of the group)
     */
    namespace.prevPeriod = function(button) {
        // When when scrolling to a previous period make sure next button is enabled
        var nextButton = $(button).next();
        nextButton.prop('disabled', false);
        nextButton.removeClass("disabled");

        // Find the id of the table by using the parent header for this button
        var tableId = $(button).closest("header").data("header_for") + "_table";

        // Period columns represented by the th in thead
        var columns = $("#" + tableId + " thead tr").find(":not(:first-child, .uif-lineItem-rowTotal)");

        // The last visible column of periods is the one that will be hidden
        var hideColumn = columns.filter(":visible:last");
        hideColumn.hide();
        var hideIndex = columns.index(hideColumn);

        // The column before the first visible column of periods is the one that will be shown
        var showColumn = columns.filter(":visible:first").prev();
        var showIndex = columns.index(showColumn);
        showColumn.show();

        // Disable the previous button if the first column (index 0) of periods is currently showing
        if (columns.eq(0).is(":visible")) {
            $(button).prop('disabled', true);
        }

        // Iterate over each row and hide the columns we are hiding by index, and show the columns we are showing by index
        $("#" + tableId + " tbody tr").each(function(){
            var columns = $(this).find(":not(:first-child, .uif-lineItem-rowTotal)");
            columns.eq(hideIndex).hide();
            columns.eq(showIndex).show();
        });
    }

    /**
     * Scrolls the period columns of the line item table forward to the next period
     *
     * @param button the next period button (it must be in the header of the group)
     */
    namespace.nextPeriod = function (button) {
        // When when scrolling to a next period make sure previous button is enabled
        var prevButton = $(button).prev();
        prevButton.prop('disabled', false);
        prevButton.removeClass("disabled");

        // Find the id of the table by using the parent header for this button
        var tableId = $(button).closest("header").data("header_for") + "_table";

        // Period columns represented by the th in thead
        var columns = $("#" + tableId + " thead tr").find(":not(:first-child, .uif-lineItem-rowTotal)");

        // Hide the first visible column
        var hideColumn = columns.filter(":visible:first");
        var hideIndex = columns.index(hideColumn);
        hideColumn.hide();

        // The column that is the first hidden column of the items after the column we are hiding
        var showColumn = hideColumn.nextAll(":hidden:first");
        var showIndex = columns.index(showColumn);
        showColumn.show();

        // Disable the previous button if the first column (index 0) of periods is currently showing
        if (showColumn.nextAll(":hidden").length === 0) {
            $(button).prop('disabled', true);
        }

        // Iterate over each row and hide and show the columns by index discovered above
        $("#" + tableId + " tbody tr").each(function(){
            var columns = $(this).find(":not(:first-child, .uif-lineItem-rowTotal)");
            columns.eq(hideIndex).hide();
            columns.eq(showIndex).show();
        });
    }

})(Kc.LineItemTable, jQuery);<|endoftext|>


<commit_before><commit_msg>Add work done in class<commit_after><|endoftext|>


<commit_before>/*!
 * ${copyright}
 */
sap.ui.define([
	"sap/base/Log",
	"sap/ui/test/Opa",
	"sap/ui/test/TestUtils"
], function (Log, Opa, TestUtils) {
	"use strict";

	return {
		createRelative : function (Given, When, Then, sUIComponent) {
			var aExpectedLogs = [],
				bRealOData = TestUtils.isRealOData(),
				oSideEffectsFailLog1 = {
					component : "sap.ui.model.odata.v4.ODataListBinding",
					level : Log.Level.ERROR,
					message : "Failed to request side effects",
					details : "HTTP request was not processed because the previous request failed"
				},
				oSideEffectsFailLog2 = {
					component : "sap.ui.model.odata.v4.ODataContextBinding",
					level : Log.Level.ERROR,
					message : "Failed to request side effects",
					details : "HTTP request was not processed because the previous request failed"
				},
				oStrictModeFailLog = {
					component : "sap.ui.model.odata.v4.ODataListBinding",
					level : Log.Level.ERROR,
					message : new RegExp("Failed to refresh entity: "
						+ "\\/SalesOrderList\\('.*'\\)\\[-1\\]"),
					details : "HTTP request was not processed because the previous request failed"
				},
				oReadCountFailLog = {
					component : "sap.ui.model.odata.v4.ODataPropertyBinding",
					level : Log.Level.ERROR,
					message : "Failed to read path /SalesOrderList",
					details : "HTTP request was not processed because the previous request failed"
				},
				oReadSchedulesFailLog = {
					component : "sap.ui.model.odata.v4.ODataListBinding",
					level : Log.Level.ERROR,
					message : new RegExp("Failed to get contexts for"
						+ " .*/sap/opu/odata4/sap/zui5_testv4/default/sap/zui5_epm_sample/0002"
						+ "/SalesOrderList\\('.*'\\)/SO_2_SCHDL with start index 0 and length 100"),
					details : "HTTP request was not processed because the previous request failed"
				},
				oUpdateFailLog = {
					component : "sap.ui.model.odata.v4.Context",
					level : Log.Level.ERROR,
					message : "Failed to update path /SalesOrderList"
				};

			// we check supportAssistantIssues only within this test journey because it is the most
			// deepest one regarding reached UI elements
			When.onAnyPage.applySupportAssistant();

			Given.iStartMyUIComponent({
				autoWait : true,
				componentConfig : {
					name : sUIComponent || "sap.ui.core.sample.odata.v4.SalesOrders"
				}
			});

			Opa.getContext().sViewName = "sap.ui.core.sample.odata.v4.SalesOrders.Main";

			// Preparation: create a new sales order
			When.onTheMainPage.firstSalesOrderIsVisible();
			When.onTheMainPage.pressCreateSalesOrdersButton();
			When.onTheCreateNewSalesOrderDialog.confirmDialog();
			When.onTheMainPage.pressSaveSalesOrdersButton();
			When.onTheSuccessInfo.confirm();
			Then.onTheMainPage.checkCompanyName(0, "SAP");
			Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");

			// Create a new sales order line item; no refresh allowed; cancel created item
			When.onTheMainPage.pressCreateSalesOrderItemButton();
			Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");
			Then.onTheMainPage.checkSalesOrderItemsCount(1);
			When.onTheMainPage.pressRefreshSalesOrdersButton();
			When.onTheRefreshConfirmation.cancel();
			// canceling different group does not remove created sales order item
			When.onTheMainPage.pressCancelSalesOrderListChangesButton();
			Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");
			When.onTheMainPage.pressCancelSalesOrderChangesButton();
			Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");
			Then.onTheMainPage.checkSalesOrderItemsCount(0);

			// Delete transient sales order line item
			When.onTheMainPage.pressCreateSalesOrderItemButton();
			When.onTheMainPage.selectSalesOrderItemWithPosition("");
			When.onTheMainPage.deleteSelectedSalesOrderLineItem();
			When.onTheSalesOrderLineItemDeletionConfirmation.confirm();
			When.onTheSuccessInfo.confirm();
			Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");

			// Create a sales order line item; save, update and delete it
			When.onTheMainPage.pressCreateSalesOrderItemButton();
			When.onTheMainPage.selectSalesOrderItemWithPosition("");
			When.onTheMainPage.pressSaveSalesOrderButton();
			When.onTheSuccessInfo.confirm();
			Then.onTheMainPage.checkSalesOrderItemsCount(1);

			if (bRealOData) {
				Then.onTheMainPage.checkNewSalesOrderItemProductName("Notebook Basic 15");
				// update note of new sales order item
				When.onTheMainPage.changeNoteInLineItem(0, "Line Item Note Changed - 1");
				When.onTheMainPage.pressSaveSalesOrderButton();
				Then.onTheMainPage.checkSalesOrderLineItemNote(0, "Line Item Note Changed - 1");

				// check correct error handling of multiple changes in one $batch
				aExpectedLogs.push(oUpdateFailLog);
				When.onTheMainPage.changeNoteInLineItem(0, "Line Item Note Changed - 2");
				aExpectedLogs.push(oUpdateFailLog);
				When.onTheMainPage.changeQuantityInLineItem(0, "0.0");
				aExpectedLogs.push(oSideEffectsFailLog1, oSideEffectsFailLog1,
					oSideEffectsFailLog2, oReadCountFailLog, oReadSchedulesFailLog);
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheMessagePopover.close();
				When.onTheMainPage.changeQuantityInLineItem(0, "2.0");
				When.onTheMainPage.pressSaveSalesOrderButton();
				Then.onTheMainPage.checkSalesOrderLineItemNote(0, "Line Item Note Changed - 2");

				// change context should be possible after Line Items were saved
				// Test only possible with realOData because same GET request for the Line Items
				// with different result happen which is not possible with mockdata
				When.onTheMainPage.selectSalesOrder(1);
				When.onTheMainPage.selectSalesOrder(0);
				When.onTheMainPage.selectSalesOrderItemWithPosition("0000000010");

				// try to change the parent Sales Order,
				// the dependent ODCB should also got its new ETag, check that it can be modified
				When.onTheMainPage.changeNoteInDetails("Sales Order Details Note Changed - 1");
				When.onTheMainPage.pressSaveSalesOrderButton();
				// this is only possible if it has got a new ETag via refresh single
				When.onTheMainPage.changeNoteInSalesOrders(0, "Sales Order Note Changed - 1");
				When.onTheMainPage.pressSaveSalesOrdersButton();

				// change again Note in details causes error because of outdated ETag
				// because refresh on relative bindings is not supported
				aExpectedLogs.push(oUpdateFailLog);
				When.onTheMainPage.changeNoteInDetails("Sales Order Details Note Changed - 2");
				aExpectedLogs.push(oSideEffectsFailLog1, oSideEffectsFailLog1,
					oSideEffectsFailLog2, oSideEffectsFailLog2, oSideEffectsFailLog2,
					oReadCountFailLog, oReadSchedulesFailLog);
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheMessagePopover.close();

				// check has pending changes
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();
				When.onTheRefreshConfirmation.cancel();

				// reset changes and refresh single sales order
				When.onTheMainPage.pressCancelSalesOrderChangesButton();
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();

				// change Note in details is now possible again
				When.onTheMainPage.changeNoteInDetails("Sales Order Details Note Changed - 3");
				When.onTheMainPage.pressSaveSalesOrderButton();

				When.onTheMainPage.increaseSalesOrderItemsQuantity();
				Then.onTheMainPage.checkNote(0, "1 item's quantity increased by: 1", true);
				Then.onTheMainPage.checkSalesOrderLineItemNote(0, "Item quantity increased by: 1");
				Then.onTheMainPage.checkSalesOrderLineItemGrossAmount(0, "3,412.92");
				Then.onTheMainPage.checkSalesOrderLineItemQuantity(0, "3.000");

				// delete persisted sales order item
				When.onTheMainPage.deleteSelectedSalesOrderLineItem();
				When.onTheSalesOrderLineItemDeletionConfirmation.confirm();
				When.onTheSuccessInfo.confirm();
				Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");

				// Confirmation of new created sales order, non-transient but still having -1 path
				// Note: The sales order must have at least one line item
				When.onTheMainPage.pressCreateSalesOrderItemButton();
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheSuccessInfo.confirm();
				When.onTheMainPage.pressConfirmSalesOrderButton();
				aExpectedLogs.push(oStrictModeFailLog);
				When.onTheMainPage.pressCancelStrictModeButton();

				When.onTheMainPage.pressConfirmSalesOrderButton();
				aExpectedLogs.push(oStrictModeFailLog);
				When.onTheMainPage.pressConfirmStrictModeButton();

				// test refresh single row
				// preparation
				When.onTheMainPage.pressRefreshSalesOrdersButton();
				When.onTheMainPage.pressCreateSalesOrdersButton();
				When.onTheCreateNewSalesOrderDialog.confirmDialog();
				When.onTheMainPage.pressSaveSalesOrdersButton();
				When.onTheSuccessInfo.confirm();
				// test: refresh single row reads expands
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();
				When.onTheMainPage.pressCreateSalesOrderItemButton();
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheSuccessInfo.confirm();
				Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");
				// test: refresh single refreshes also dependent bindings
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();
				Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");

				// Create a sales order line item; change Product ID manually
				When.onTheMainPage.pressCreateSalesOrderItemButton();
				When.onTheMainPage.selectSalesOrderItemWithPosition("");
				When.onTheMainPage.changeProductIDinLineItem(1, "HT-1010");
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheSuccessInfo.confirm();
				Then.onTheMainPage.checkProductNameInLineItem(1, "Notebook Professional 15");
				Then.onTheMainPage.checkSalesOrderItemsCount(2);
				// and via value help
				When.onTheMainPage.pressValueHelpOnProductID(1);
				When.onTheValueHelpPopover.selectByKey("HT-1000");
				Then.onTheMainPage.checkProductNameInLineItem(1, "Notebook Professional 15");
				When.onTheMainPage.pressSaveSalesOrderButton();
				Then.onTheMainPage.checkProductNameInLineItem(1, "Notebook Basic 15");
			}

			// delete created sales orders
			When.onAnyPage.cleanUp("SalesOrderList");
			Then.onAnyPage.checkLog(aExpectedLogs);
			Then.onAnyPage.analyzeSupportAssistant();
			Then.iTeardownMyUIComponent();
		}
	};
});<commit_msg>[INTERNAL] sap.ui.core.sample.odata.v4.SalesOrders: expect drilldown console error in OPA<commit_after>/*!
 * ${copyright}
 */
sap.ui.define([
	"sap/base/Log",
	"sap/ui/test/Opa",
	"sap/ui/test/TestUtils"
], function (Log, Opa, TestUtils) {
	"use strict";

	return {
		createRelative : function (Given, When, Then, sUIComponent) {
			var oDrillDownErrorLog = {
					component : "sap.ui.model.odata.v4.lib._Cache",
					level : Log.Level.ERROR,
					message :
						/Failed to drill-down into \('[0-9]*'\), invalid segment: \('[0-9]*'\)/
				},
				aExpectedLogs = [],
				oReadCountFailLog = {
					component : "sap.ui.model.odata.v4.ODataPropertyBinding",
					level : Log.Level.ERROR,
					message : "Failed to read path /SalesOrderList",
					details : "HTTP request was not processed because the previous request failed"
				},
				oReadSchedulesFailLog = {
					component : "sap.ui.model.odata.v4.ODataListBinding",
					level : Log.Level.ERROR,
					message : new RegExp("Failed to get contexts for"
						+ " .*/sap/opu/odata4/sap/zui5_testv4/default/sap/zui5_epm_sample/0002"
						+ "/SalesOrderList\\('.*'\\)/SO_2_SCHDL with start index 0 and length 100"),
					details : "HTTP request was not processed because the previous request failed"
				},
				bRealOData = TestUtils.isRealOData(),
				oSideEffectsFailLog1 = {
					component : "sap.ui.model.odata.v4.ODataListBinding",
					level : Log.Level.ERROR,
					message : "Failed to request side effects",
					details : "HTTP request was not processed because the previous request failed"
				},
				oSideEffectsFailLog2 = {
					component : "sap.ui.model.odata.v4.ODataContextBinding",
					level : Log.Level.ERROR,
					message : "Failed to request side effects",
					details : "HTTP request was not processed because the previous request failed"
				},
				oStrictModeFailLog = {
					component : "sap.ui.model.odata.v4.ODataListBinding",
					level : Log.Level.ERROR,
					message : new RegExp("Failed to refresh entity: "
						+ "\\/SalesOrderList\\('.*'\\)\\[-1\\]"),
					details : "HTTP request was not processed because the previous request failed"
				},
				oUpdateFailLog = {
					component : "sap.ui.model.odata.v4.Context",
					level : Log.Level.ERROR,
					message : "Failed to update path /SalesOrderList"
				};

			// we check supportAssistantIssues only within this test journey because it is the most
			// deepest one regarding reached UI elements
			When.onAnyPage.applySupportAssistant();

			Given.iStartMyUIComponent({
				autoWait : true,
				componentConfig : {
					name : sUIComponent || "sap.ui.core.sample.odata.v4.SalesOrders"
				}
			});

			Opa.getContext().sViewName = "sap.ui.core.sample.odata.v4.SalesOrders.Main";

			// Preparation: create a new sales order
			When.onTheMainPage.firstSalesOrderIsVisible();
			When.onTheMainPage.pressCreateSalesOrdersButton();
			When.onTheCreateNewSalesOrderDialog.confirmDialog();
			When.onTheMainPage.pressSaveSalesOrdersButton();
			When.onTheSuccessInfo.confirm();
			Then.onTheMainPage.checkCompanyName(0, "SAP");
			Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");

			// Create a new sales order line item; no refresh allowed; cancel created item
			When.onTheMainPage.pressCreateSalesOrderItemButton();
			Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");
			Then.onTheMainPage.checkSalesOrderItemsCount(1);
			When.onTheMainPage.pressRefreshSalesOrdersButton();
			When.onTheRefreshConfirmation.cancel();
			// canceling different group does not remove created sales order item
			When.onTheMainPage.pressCancelSalesOrderListChangesButton();
			Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");
			When.onTheMainPage.pressCancelSalesOrderChangesButton();
			Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");
			Then.onTheMainPage.checkSalesOrderItemsCount(0);

			// Delete transient sales order line item
			When.onTheMainPage.pressCreateSalesOrderItemButton();
			When.onTheMainPage.selectSalesOrderItemWithPosition("");
			When.onTheMainPage.deleteSelectedSalesOrderLineItem();
			When.onTheSalesOrderLineItemDeletionConfirmation.confirm();
			When.onTheSuccessInfo.confirm();
			Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");

			// Create a sales order line item; save, update and delete it
			When.onTheMainPage.pressCreateSalesOrderItemButton();
			When.onTheMainPage.selectSalesOrderItemWithPosition("");
			When.onTheMainPage.pressSaveSalesOrderButton();
			When.onTheSuccessInfo.confirm();
			Then.onTheMainPage.checkSalesOrderItemsCount(1);

			if (bRealOData) {
				Then.onTheMainPage.checkNewSalesOrderItemProductName("Notebook Basic 15");
				// update note of new sales order item
				When.onTheMainPage.changeNoteInLineItem(0, "Line Item Note Changed - 1");
				When.onTheMainPage.pressSaveSalesOrderButton();
				Then.onTheMainPage.checkSalesOrderLineItemNote(0, "Line Item Note Changed - 1");

				// check correct error handling of multiple changes in one $batch
				aExpectedLogs.push(oUpdateFailLog);
				When.onTheMainPage.changeNoteInLineItem(0, "Line Item Note Changed - 2");
				aExpectedLogs.push(oUpdateFailLog);
				When.onTheMainPage.changeQuantityInLineItem(0, "0.0");
				aExpectedLogs.push(oSideEffectsFailLog1, oSideEffectsFailLog1,
					oSideEffectsFailLog2, oReadCountFailLog, oReadSchedulesFailLog);
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheMessagePopover.close();
				When.onTheMainPage.changeQuantityInLineItem(0, "2.0");
				When.onTheMainPage.pressSaveSalesOrderButton();
				Then.onTheMainPage.checkSalesOrderLineItemNote(0, "Line Item Note Changed - 2");

				// change context should be possible after Line Items were saved
				// Test only possible with realOData because same GET request for the Line Items
				// with different result happen which is not possible with mockdata
				When.onTheMainPage.selectSalesOrder(1);
				When.onTheMainPage.selectSalesOrder(0);
				When.onTheMainPage.selectSalesOrderItemWithPosition("0000000010");

				// try to change the parent Sales Order,
				// the dependent ODCB should also got its new ETag, check that it can be modified
				When.onTheMainPage.changeNoteInDetails("Sales Order Details Note Changed - 1");
				When.onTheMainPage.pressSaveSalesOrderButton();
				// this is only possible if it has got a new ETag via refresh single
				When.onTheMainPage.changeNoteInSalesOrders(0, "Sales Order Note Changed - 1");
				When.onTheMainPage.pressSaveSalesOrdersButton();

				// change again Note in details causes error because of outdated ETag
				// because refresh on relative bindings is not supported
				aExpectedLogs.push(oUpdateFailLog);
				When.onTheMainPage.changeNoteInDetails("Sales Order Details Note Changed - 2");
				aExpectedLogs.push(oSideEffectsFailLog1, oSideEffectsFailLog1,
					oSideEffectsFailLog2, oSideEffectsFailLog2, oSideEffectsFailLog2,
					oReadCountFailLog, oReadSchedulesFailLog);
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheMessagePopover.close();

				// check has pending changes
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();
				When.onTheRefreshConfirmation.cancel();

				// reset changes and refresh single sales order
				When.onTheMainPage.pressCancelSalesOrderChangesButton();
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();

				// change Note in details is now possible again
				When.onTheMainPage.changeNoteInDetails("Sales Order Details Note Changed - 3");
				When.onTheMainPage.pressSaveSalesOrderButton();

				When.onTheMainPage.increaseSalesOrderItemsQuantity();
				Then.onTheMainPage.checkNote(0, "1 item's quantity increased by: 1", true);
				Then.onTheMainPage.checkSalesOrderLineItemNote(0, "Item quantity increased by: 1");
				Then.onTheMainPage.checkSalesOrderLineItemGrossAmount(0, "3,412.92");
				Then.onTheMainPage.checkSalesOrderLineItemQuantity(0, "3.000");

				// delete persisted sales order item
				When.onTheMainPage.deleteSelectedSalesOrderLineItem();
				When.onTheSalesOrderLineItemDeletionConfirmation.confirm();
				When.onTheSuccessInfo.confirm();
				Then.onTheMainPage.checkTableLength(0, "SO_2_SOITEM");

				// Confirmation of new created sales order, non-transient but still having -1 path
				// Note: The sales order must have at least one line item
				When.onTheMainPage.pressCreateSalesOrderItemButton();
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheSuccessInfo.confirm();
				When.onTheMainPage.pressConfirmSalesOrderButton();
				aExpectedLogs.push(oStrictModeFailLog);
				When.onTheMainPage.pressCancelStrictModeButton();

				When.onTheMainPage.pressConfirmSalesOrderButton();
				aExpectedLogs.push(oStrictModeFailLog);
				When.onTheMainPage.pressConfirmStrictModeButton();
				aExpectedLogs.push(oDrillDownErrorLog); // obsolete with CPOUI5ODATAV4-288

				// test refresh single row
				// preparation
				When.onTheMainPage.pressRefreshSalesOrdersButton();
				When.onTheMainPage.pressCreateSalesOrdersButton();
				When.onTheCreateNewSalesOrderDialog.confirmDialog();
				When.onTheMainPage.pressSaveSalesOrdersButton();
				When.onTheSuccessInfo.confirm();
				// test: refresh single row reads expands
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();
				When.onTheMainPage.pressCreateSalesOrderItemButton();
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheSuccessInfo.confirm();
				Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");
				// test: refresh single refreshes also dependent bindings
				When.onTheMainPage.pressRefreshSelectedSalesOrdersButton();
				Then.onTheMainPage.checkTableLength(1, "SO_2_SOITEM");

				// Create a sales order line item; change Product ID manually
				When.onTheMainPage.pressCreateSalesOrderItemButton();
				When.onTheMainPage.selectSalesOrderItemWithPosition("");
				When.onTheMainPage.changeProductIDinLineItem(1, "HT-1010");
				When.onTheMainPage.pressSaveSalesOrderButton();
				When.onTheSuccessInfo.confirm();
				Then.onTheMainPage.checkProductNameInLineItem(1, "Notebook Professional 15");
				Then.onTheMainPage.checkSalesOrderItemsCount(2);
				// and via value help
				When.onTheMainPage.pressValueHelpOnProductID(1);
				When.onTheValueHelpPopover.selectByKey("HT-1000");
				Then.onTheMainPage.checkProductNameInLineItem(1, "Notebook Professional 15");
				When.onTheMainPage.pressSaveSalesOrderButton();
				Then.onTheMainPage.checkProductNameInLineItem(1, "Notebook Basic 15");
			}

			// delete created sales orders
			When.onAnyPage.cleanUp("SalesOrderList");
			Then.onAnyPage.checkLog(aExpectedLogs);
			Then.onAnyPage.analyzeSupportAssistant();
			Then.iTeardownMyUIComponent();
		}
	};
});<|endoftext|>


<commit_before>import React, { PropTypes } from 'react';
import classnames from 'classnames';
//
import AbstractComponent from '../AbstractComponent/AbstractComponent';
import Icon from '../Icon/Icon';
import Tooltip from '../Tooltip/Tooltip';

/**
 * TODO: Improvent:
 * - add button size (className is abused now)
 *
 * @author Radek Tomiška
 */
class Button extends AbstractComponent {

  constructor(props) {
    super(props);
  }

  focus() {
    this.refs.button.focus();
  }

  render() {
    const {
      level,
      text,
      className,
      children,
      showLoading,
      showLoadingIcon,
      showLoadingText,
      disabled,
      hidden,
      type,
      rendered,
      title,
      titlePlacement,
      titleDelayShow,
      style,
      onClick,
      icon
    } = this.props;
    //
    if (!rendered) {
      return null;
    }

    const classNames = classnames(
      'btn',
      'btn-' + level,
      { hidden },
      className
    );
    let _showLoadingText = children;
    if (showLoadingText !== null) {
      _showLoadingText = showLoadingText;
    }
    //
    return (
      <Tooltip placement={titlePlacement} value={title} delayShow={titleDelayShow}>

          <button
            ref="button"
            type={type ? type : 'button'}
            disabled={disabled || showLoading}
            className={classNames}
            style={style}
            onClick={onClick}>
            {
              showLoading
              ?

                {
                  showLoadingIcon
                  ?
                  <Icon type="fa" icon="refresh" showLoading/>
                  :
                  null
                }
                {
                  showLoadingIcon && _showLoadingText
                  ?
                  '\u00a0'
                  :
                  null
                }
                {_showLoadingText}

              :

                <Icon value={ icon } className="icon-left"/>
                { text }
                { children }

            }
          </button>

     </Tooltip>
    );
  }
}

Button.propTypes = {
  ...AbstractComponent.propTypes,
  /**
   * Button level / css / class
   */
  level: PropTypes.oneOf(['default', 'success', 'warning', 'info', 'danger', 'link', 'primary']),
  /**
   * When showLoading is true, then showLoadingIcon is shown
   */
  showLoadingIcon: PropTypes.bool,
  /**
   *  When showLoading is true, this text will be shown
   */
  showLoadingText: PropTypes.string,
  /**
   * Title position
   */
  titlePlacement: PropTypes.oneOf(['top', 'bottom', 'right', 'left']),
  /**
   * Title show delay
   */
  titleDelayShow: PropTypes.number,
  /**
   * Button icon
   */
  icon: PropTypes.string
};
Button.defaultProps = {
  ...AbstractComponent.defaultProps,
  type: 'button',
  level: 'default',
  hidden: false,
  showLoadingIcon: false,
  showLoadingText: null,
  titlePlacement: 'right',
  icon: null
};

export default Button;
<commit_msg>fix: show button icon in show loading state<commit_after>import React, { PropTypes } from 'react';
import classnames from 'classnames';
//
import AbstractComponent from '../AbstractComponent/AbstractComponent';
import Icon from '../Icon/Icon';
import Tooltip from '../Tooltip/Tooltip';

/**
 * TODO: Improvent:
 * - add button size (className is abused now)
 *
 * @author Radek Tomiška
 */
class Button extends AbstractComponent {

  constructor(props) {
    super(props);
  }

  focus() {
    this.refs.button.focus();
  }

  render() {
    const {
      level,
      text,
      className,
      children,
      showLoading,
      showLoadingIcon,
      showLoadingText,
      disabled,
      hidden,
      type,
      rendered,
      title,
      titlePlacement,
      titleDelayShow,
      style,
      onClick,
      icon
    } = this.props;
    //
    if (!rendered) {
      return null;
    }

    const classNames = classnames(
      'btn',
      'btn-' + level,
      { hidden },
      className
    );
    let _showLoadingText = children;
    if (showLoadingText !== null) {
      _showLoadingText = showLoadingText;
    }
    //
    return (
      <Tooltip placement={titlePlacement} value={title} delayShow={titleDelayShow}>

          <button
            ref="button"
            type={type ? type : 'button'}
            disabled={disabled || showLoading}
            className={classNames}
            style={style}
            onClick={onClick}>
            {
              showLoading
              ?

                {
                  showLoadingIcon
                  ?
                  <Icon type="fa" icon="refresh" showLoading/>
                  :
                  <Icon value={ icon } className="icon-left"/>
                }
                {
                  showLoadingIcon && _showLoadingText
                  ?
                  '\u00a0'
                  :
                  null
                }
                {_showLoadingText}

              :

                <Icon value={ icon } className="icon-left"/>
                { text }
                { children }

            }
          </button>

     </Tooltip>
    );
  }
}

Button.propTypes = {
  ...AbstractComponent.propTypes,
  /**
   * Button level / css / class
   */
  level: PropTypes.oneOf(['default', 'success', 'warning', 'info', 'danger', 'link', 'primary']),
  /**
   * When showLoading is true, then showLoadingIcon is shown
   */
  showLoadingIcon: PropTypes.bool,
  /**
   *  When showLoading is true, this text will be shown
   */
  showLoadingText: PropTypes.string,
  /**
   * Title position
   */
  titlePlacement: PropTypes.oneOf(['top', 'bottom', 'right', 'left']),
  /**
   * Title show delay
   */
  titleDelayShow: PropTypes.number,
  /**
   * Button icon
   */
  icon: PropTypes.string
};
Button.defaultProps = {
  ...AbstractComponent.defaultProps,
  type: 'button',
  level: 'default',
  hidden: false,
  showLoadingIcon: false,
  showLoadingText: null,
  titlePlacement: 'right',
  icon: null
};

export default Button;
<|endoftext|>


<commit_before>// ***********************************************//
//                 models and stores
// ***********************************************//
require('akvo-flow/core');
// DS.Model.reopen({
//	namingConvention: {
//		keyToJSONKey: function(key) {
//			return key;
//		},

//		foreignKey: function(key) {
//			return key;
//		}
//	}
// });

FLOW.store = DS.Store.create({
	revision: 7,
	//adapter:DS.FLOWRESTAdapter.create({bulkCommit:false, namespace:"rest", url:"http://localhost"})
	adapter: DS.fixtureAdapter

});

FLOW.SurveyGroup = DS.Model.extend({
	description: DS.attr('string',{defaultValue: ""}),
	name: DS.attr('string',{defaultValue: ""}),
	createdDateTime: DS.attr('string',{defaultValue: ""}),
	lastUpdateDateTime: DS.attr('string',{defaultValue: ""}),
	// the code field is used as name
	code: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number')
});

FLOW.Survey = DS.Model.extend({
	defaultLanguageCode: DS.attr('string'),
	status: DS.attr('string'),
	code: DS.attr('string'),
	requireApproval: DS.attr('string'),
	version: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	pointType: DS.attr('string'),
	surveyGroupId: DS.attr('number'),
	createdDateTime:DS.attr('number'),
	lastUpdateDateTime:DS.attr('number'),
	primaryKey: 'keyId'

});

FLOW.QuestionGroup = DS.Model.extend({
	order: DS.attr('number'),
	questionMap: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	path: DS.attr('string'),
	//class: let mDS.attr('string'), //FIXME: class is a JS reserved word
	code: DS.attr('string'),
	surveyId: DS.attr('number'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	isOpen: DS.attr('boolean', {
		defaultValue: 0
	}),
	primaryKey: 'keyId'
});

FLOW.Question = DS.Model.extend({
	translationMap: DS.attr('string'),
	// not sure
	allowDecimal: DS.attr('boolean', {defaultValue: 0}),
	optionContainerDto: DS.attr('string'),
	//not sure
	// type:     --- not now
	tip: DS.attr('string'),
	maxVal: DS.attr('number'),
	minVal: DS.attr('number'),
	order: DS.attr('number'),
	isName: DS.attr('boolean', {defaultValue: 0}),
	// questionHelpList:     --- now now
	collabseable: DS.attr('boolean', {defaultValue: 0}),
	path: DS.attr('string'),
	allowMultipleFlag: DS.attr('boolean', {defaultValue: 0}),
	immutable: DS.attr('boolean', {defaultValue: 0}),
	allowOtherFlag: DS.attr('boolean', {defaultValue: 0}),
	allowSign: DS.attr('boolean', {defaultValue: 0}),
	text: DS.attr('string'),
	//class: DS.attr('string'), //FIXME: class is a JS reserved word
	questionDependency: DS.attr('string'),
	mandatoryFlag: DS.attr('boolean', {defaultValue: 0}),
	questionGroupId: DS.attr('number'),
	questionTypeString: DS.attr('string',{defaultValue:"freeText"}),
	surveyId: DS.attr('number'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number')
});

FLOW.QuestionOption = DS.Model.extend({
	questionId: DS.attr('number'),
	text: DS.attr('string'),
	keyId: DS.attr('number')
});

FLOW.SurveyAssignment = DS.Model.extend({

});

FLOW.DeviceGroup = DS.Model.extend({
	displayName: DS.attr('string',{defaultValue: ""}),
	code: DS.attr('string',{defaultValue: ""})
});

FLOW.Device = DS.Model.extend({
	deviceType: DS.attr('string',{defaultValue: ""}),
	phoneNumber: DS.attr('string',{defaultValue: ""}),
	esn: DS.attr('string',{defaultValue: ""}),
	deviceIdentifier: DS.attr('string',{defaultValue: ""}),
	inServiceDate: DS.attr('date'),
	outServiceDate: DS.attr('date'),
	lastUpdate: DS.attr('date', {defaultValue: ""}),
	osVersion: DS.attr('string', {defaultValue: ""}),
	lastKnownLat: DS.attr('number', {defaultValue: 0}),
	lastKnownLong:DS.attr('number', {defaultValue: 0}),
	lastKnownAccuracy: DS.attr('number',{defaultValue:0}),
	lastLocationBeaconTime: DS.attr('date', {defaultValue: ""}),
	deviceGroup: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number'),
	primaryKey:'keyId',
	isSelected: DS.attr('boolean', {defaultValue: false})
});

<commit_msg>Removed not used class attributes<commit_after>// ***********************************************//
//                 models and stores
// ***********************************************//
require('akvo-flow/core');
// DS.Model.reopen({
//	namingConvention: {
//		keyToJSONKey: function(key) {
//			return key;
//		},

//		foreignKey: function(key) {
//			return key;
//		}
//	}
// });

FLOW.store = DS.Store.create({
	revision: 7,
	//adapter:DS.FLOWRESTAdapter.create({bulkCommit:false, namespace:"rest", url:"http://localhost"})
	adapter: DS.fixtureAdapter

});

FLOW.SurveyGroup = DS.Model.extend({
	description: DS.attr('string',{defaultValue: ""}),
	name: DS.attr('string',{defaultValue: ""}),
	createdDateTime: DS.attr('string',{defaultValue: ""}),
	lastUpdateDateTime: DS.attr('string',{defaultValue: ""}),
	// the code field is used as name
	code: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number')
});

FLOW.Survey = DS.Model.extend({
	defaultLanguageCode: DS.attr('string'),
	status: DS.attr('string'),
	code: DS.attr('string'),
	requireApproval: DS.attr('string'),
	version: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	pointType: DS.attr('string'),
	surveyGroupId: DS.attr('number'),
	createdDateTime:DS.attr('number'),
	lastUpdateDateTime:DS.attr('number'),
	primaryKey: 'keyId'

});

FLOW.QuestionGroup = DS.Model.extend({
	order: DS.attr('number'),
	questionMap: DS.attr('string'),
	description: DS.attr('string'),
	name: DS.attr('string'),
	path: DS.attr('string'),
	code: DS.attr('string'),
	surveyId: DS.attr('number'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number'),
	isOpen: DS.attr('boolean', {
		defaultValue: 0
	}),
	primaryKey: 'keyId'
});

FLOW.Question = DS.Model.extend({
	translationMap: DS.attr('string'),
	// not sure
	allowDecimal: DS.attr('boolean', {defaultValue: 0}),
	optionContainerDto: DS.attr('string'),
	//not sure
	// type:     --- not now
	tip: DS.attr('string'),
	maxVal: DS.attr('number'),
	minVal: DS.attr('number'),
	order: DS.attr('number'),
	isName: DS.attr('boolean', {defaultValue: 0}),
	// questionHelpList:     --- now now
	collabseable: DS.attr('boolean', {defaultValue: 0}),
	path: DS.attr('string'),
	allowMultipleFlag: DS.attr('boolean', {defaultValue: 0}),
	immutable: DS.attr('boolean', {defaultValue: 0}),
	allowOtherFlag: DS.attr('boolean', {defaultValue: 0}),
	allowSign: DS.attr('boolean', {defaultValue: 0}),
	text: DS.attr('string'),
	questionDependency: DS.attr('string'),
	mandatoryFlag: DS.attr('boolean', {defaultValue: 0}),
	questionGroupId: DS.attr('number'),
	questionTypeString: DS.attr('string',{defaultValue:"freeText"}),
	surveyId: DS.attr('number'),
	displayName: DS.attr('string'),
	keyId: DS.attr('number')
});

FLOW.QuestionOption = DS.Model.extend({
	questionId: DS.attr('number'),
	text: DS.attr('string'),
	keyId: DS.attr('number')
});

FLOW.SurveyAssignment = DS.Model.extend({

});

FLOW.DeviceGroup = DS.Model.extend({
	displayName: DS.attr('string',{defaultValue: ""}),
	code: DS.attr('string',{defaultValue: ""})
});

FLOW.Device = DS.Model.extend({
	deviceType: DS.attr('string',{defaultValue: ""}),
	phoneNumber: DS.attr('string',{defaultValue: ""}),
	esn: DS.attr('string',{defaultValue: ""}),
	deviceIdentifier: DS.attr('string',{defaultValue: ""}),
	inServiceDate: DS.attr('date'),
	outServiceDate: DS.attr('date'),
	lastUpdate: DS.attr('date', {defaultValue: ""}),
	osVersion: DS.attr('string', {defaultValue: ""}),
	lastKnownLat: DS.attr('number', {defaultValue: 0}),
	lastKnownLong:DS.attr('number', {defaultValue: 0}),
	lastKnownAccuracy: DS.attr('number',{defaultValue:0}),
	lastLocationBeaconTime: DS.attr('date', {defaultValue: ""}),
	deviceGroup: DS.attr('string',{defaultValue: ""}),
	keyId: DS.attr('number'),
	primaryKey:'keyId',
	isSelected: DS.attr('boolean', {defaultValue: false})
});

<|endoftext|>