<commit_before>define( function( require ) {

    'use strict';

	var Postmonger = require( 'postmonger' );
	var $ = require( 'vendor/jquery.min' );

    var connection = new Postmonger.Session();
    var toJbPayload = {};
    var step = 1;
	var endpoints;

    $(window).ready(onRender);

    connection.on('initActivity', function(payload) {
        var amount;

        if (payload) {
            toJbPayload = payload;
            console.log('payload',payload);

			//merge the array of objects.
			var aArgs = toJbPayload['arguments'].execute.inArguments;
			var oArgs = {};
			for (var i=0; i<aArgs.length; i++) {
				for (var key in aArgs[i]) {
					oArgs[key] = aArgs[i][key];
				}
			}
			//oArgs.amount will contain a value if this activity has already been configured:
			amount = oArgs.amount || toJbPayload['configurationArguments'].defaults.amount;
        }

		$.get( "/version", function( data ) {
			$('#version').html('Version: ' + data.version);
		});

        // If there is no amount selected, disable the next button
        if (!amount) {
            connection.trigger('updateButton', { button: 'next', enabled: false });
        }

		$('#selectAmount').find('option[value='+ amount +']').attr('selected', 'selected');
		gotoStep(step);

    });

    connection.on('requestedEndpoints', function(data) {
		if( data.error ) {
			console.error( data.error );
		} else {
			endpoints = data;
            console.log("endpoints",data);
		}
    });

    connection.on('clickedNext', function() {
        step++;
        gotoStep(step);
        connection.trigger('ready');
    });

    connection.on('clickedBack', function() {
        step--;
        gotoStep(step);
        connection.trigger('ready');
    });

    function onRender() {
        connection.trigger('ready');
        connection.trigger('requestEndpoints');

        // Disable the next button if a value isn't selected
        $('#selectValueTier').change(function() {
            var valueTier = getValueTier();
            var type = getType();
            var bonus = getBonus();
            var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
            connection.trigger('updateButton', { button: 'next', enabled: valid });
        });

        $('#selectType').change(function() {
            var valueTier = getValueTier();
            var type = getType();
            var bonus = getBonus();
            var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
            connection.trigger('updateButton', { button: 'next', enabled: valid });
        });

        $('#selectBonus').change(function() {
            var valueTier = getValueTier();
            var type = getType();
            var bonus = getBonus();
            var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
            connection.trigger('updateButton', { button: 'next', enabled: valid });
        });

    };

    function gotoStep(step) {
        $('.step').hide();
        switch(step) {
            case 1:
                $('#step1').show();
                var valueTier = getValueTier();
                var type = getType();
                var bonus = getBonus();
                var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
                connection.trigger('updateButton', { button: 'next', text: 'next', enabled: valid });
                connection.trigger('updateButton', { button: 'back', visible: false });
                break;
            case 2:
                $('#step2').show();
                $('#showValueTier').html(getValueTierText());
                $('#showType').html(getTypeText());
                $('#showBonus').html(getBonusText());
                connection.trigger('updateButton', { button: 'back', visible: true });
                connection.trigger('updateButton', { button: 'next', text: 'done', visible: true });
                break;
            case 3: // Only 2 steps, so the equivalent of 'done' - send off the payload
                save();
                break;
        }
    };

    function getValueTier() {
        return $('#selectValueTier').find('option:selected').attr('value').trim();
    };
    function getType() {
        return $('#selectType').find('option:selected').attr('value').trim();
    };
    function getBonus() {
        return $('#selectBonus').find('option:selected').attr('value').trim();
    };

    function getValueTierText() {
        return $('#selectValueTier').find('option:selected').text().trim();
    };
    function getTypeText() {
        return $('#selectType').find('option:selected').text().trim();
    };
    function getBonusText() {
        return $('#selectBonus').find('option:selected').text().trim();
    };

    function save() {

        var valueTier = getValueTier();
        var type = getType();
        var bonus = getBonus();

        // toJbPayload is initialized on populateFields above.  Journey Builder sends an initial payload with defaults
        // set by this activity's config.json file.  Any property may be overridden as desired.
        //toJbPayload.name = "my activity";

        //this will be sent into the custom activity body within the inArguments array.
        toJbPayload['arguments'].execute.inArguments.push({"valueTier": valueTier});
        toJbPayload['arguments'].execute.inArguments.push({"type": type});
        toJbPayload['arguments'].execute.inArguments.push({"bonus": bonus});

		/*
        toJbPayload['metaData'].things = 'stuff';
        toJbPayload['metaData'].icon = 'path/to/icon/set/from/iframe/icon.png';
        toJbPayload['configurationArguments'].version = '1.1'; // optional - for 3rd party to track their customActivity.js version
        toJbPayload['configurationArguments'].partnerActivityId = '49198498';
        toJbPayload['configurationArguments'].myConfiguration = 'configuration coming from iframe';
		*/

		toJbPayload.metaData.isConfigured = true;  //this is required by JB to set the activity as Configured.
        connection.trigger('updateActivity', toJbPayload);
    };

});

<commit_msg>no message<commit_after>define( function( require ) {

    'use strict';

	var Postmonger = require( 'postmonger' );
	var $ = require( 'vendor/jquery.min' );

    var connection = new Postmonger.Session();
    var toJbPayload = {};
    var step = 1;
	var endpoints;

    $(window).ready(onRender);

    connection.on('initActivity', function(payload) {
        var amount;

        if (payload) {
            toJbPayload = payload;
            console.log('payload',payload);

			//merge the array of objects.
			var aArgs = toJbPayload['arguments'].execute.inArguments;
			var oArgs = {};
			for (var i=0; i<aArgs.length; i++) {
				for (var key in aArgs[i]) {
					oArgs[key] = aArgs[i][key];
				}
			}
			//oArgs.amount will contain a value if this activity has already been configured:
			amount = oArgs.amount || toJbPayload['configurationArguments'].defaults.amount;
        }

		$.get( "/version", function( data ) {
			$('#version').html('Version: ' + data.version);
		});

        // If there is no amount selected, disable the next button
        if (!amount) {
            connection.trigger('updateButton', { button: 'next', enabled: false });
        }

		$('#selectAmount').find('option[value='+ amount +']').attr('selected', 'selected');
		gotoStep(step);

    });

    connection.on('requestedEndpoints', function(data) {
		if( data.error ) {
			console.error( data.error );
		} else {
			endpoints = data;
            console.log("endpoints",data);
		}
    });

    connection.on('clickedNext', function() {
        step++;
        gotoStep(step);
        connection.trigger('ready');
    });

    connection.on('clickedBack', function() {
        step--;
        gotoStep(step);
        connection.trigger('ready');
    });

    function onRender() {
        connection.trigger('ready');
        connection.trigger('requestEndpoints');

        // Disable the next button if a value isn't selected
        $('#selectValueTier').change(function() {
            var valueTier = getValueTier();
            var type = getType();
            var bonus = getBonus();
            var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
            connection.trigger('updateButton', { button: 'next', enabled: valid });
        });

        $('#selectType').change(function() {
            var valueTier = getValueTier();
            var type = getType();
            var bonus = getBonus();
            var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
            connection.trigger('updateButton', { button: 'next', enabled: valid });
        });

        $('#selectBonus').change(function() {
            var valueTier = getValueTier();
            var type = getType();
            var bonus = getBonus();
            var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
            connection.trigger('updateButton', { button: 'next', enabled: valid });
        });

    };

    function gotoStep(step) {
        $('.step').hide();
        switch(step) {
            case 1:
                $('#step1').show();
                var valueTier = getValueTier();
                var type = getType();
                var bonus = getBonus();
                var valid = Boolean(valueTier) && Boolean(bonus) && Boolean(type);
                connection.trigger('updateButton', { button: 'next', text: 'next', enabled: valid });
                connection.trigger('updateButton', { button: 'back', visible: false });
                break;
            case 2:
                $('#step2').show();
                $('#showValueTier').html(getValueTierText());
                $('#showType').html(getTypeText());
                $('#showBonus').html(getBonusText());
                connection.trigger('updateButton', { button: 'back', visible: true });
                connection.trigger('updateButton', { button: 'next', text: 'done', visible: true });
                break;
            case 3: // Only 2 steps, so the equivalent of 'done' - send off the payload
                save();
                break;
        }
    };

    function getValueTier() {
        return $('#selectValueTier').find('option:selected').attr('value').trim();
    };
    function getType() {
        return $('#selectType').find('option:selected').attr('value').trim();
    };
    function getBonus() {
        return $('#selectBonus').find('option:selected').attr('value').trim();
    };

    function getValueTierText() {
        return $('#selectValueTier').find('option:selected').text().trim();
    };
    function getTypeText() {
        return $('#selectType').find('option:selected').text().trim();
    };
    function getBonusText() {
        return $('#selectBonus').find('option:selected').text().trim();
    };

    function save() {

        var valueTier = getValueTier();
        var type = getType();
        var bonus = getBonus();

        // toJbPayload is initialized on populateFields above.  Journey Builder sends an initial payload with defaults
        // set by this activity's config.json file.  Any property may be overridden as desired.
        //toJbPayload.name = "my activity";

        //this will be sent into the custom activity body within the inArguments array.
        toJbPayload['arguments'].execute.inArguments.push({"valueTier": valueTier});
        toJbPayload['arguments'].execute.inArguments.push({"type": type});
        toJbPayload['arguments'].execute.inArguments.push({"bonus": bonus});

        console.log(toJbPayload['arguments'].execute.inArguments);

		/*
        toJbPayload['metaData'].things = 'stuff';
        toJbPayload['metaData'].icon = 'path/to/icon/set/from/iframe/icon.png';
        toJbPayload['configurationArguments'].version = '1.1'; // optional - for 3rd party to track their customActivity.js version
        toJbPayload['configurationArguments'].partnerActivityId = '49198498';
        toJbPayload['configurationArguments'].myConfiguration = 'configuration coming from iframe';
		*/

		toJbPayload.metaData.isConfigured = true;  //this is required by JB to set the activity as Configured.
        connection.trigger('updateActivity', toJbPayload);
    };

});

<|endoftext|>


<commit_before>// ADEPTED FROM EXTERNAL SOURCE: https://github.com/FerCa/tuner/
define([
    'jquery',
    'underscore',
    'backbone'
//    'tuner'
], function ($, _, Backbone) {

    var frequencyBefore = 0;
    var tunerActive = false;
    var tunerShowData = true;

    function FrequenciesExtractor() {

        this.extractHigherValueFrequency = function (frequencyByteData, fourierFastTransformSize, sampleRate) {
//console.log('frequencyByteData: ', frequencyByteData);
            var higherValue = 0;
            var higherValueFrequency = 0;
            var length = frequencyByteData.length;
            // Search for the frequency with the higher value
            for (var x = 0; x < length; x++) {

                var frequency = __calculateFrequency(x, sampleRate, fourierFastTransformSize);

                if (frequencyByteData[x] > higherValue) {
                    higherValue = frequencyByteData[x];
                    higherValueFrequency = frequency;
                }
            }

            return higherValueFrequency;
        };

        function __calculateFrequency(position, sampleRate, fourierFastTransformSize) {
            return position * (sampleRate / (fourierFastTransformSize * 2));
        }

    }

    function startTuner() {
        that = this;
        window.AudioContext = window.AudioContext ||
                window.webkitAudioContext;

        navigator.getMedia = (navigator.getUserMedia ||
                navigator.webkitGetUserMedia ||
                navigator.mozGetUserMedia ||
                navigator.msGetUserMedia);

        var audioContext = new AudioContext();

        var gotStreamCallback = function gotStreamCallbackFunction(mediaStream) {
            var microphoneSource = audioContext.createMediaStreamSource(mediaStream);

            var tuner = new Tuner(microphoneSource, audioContext.destination, audioContext);

            tuner.start(function (note) {

//            $('#frequencies-string2').text(note);
                if (that.tunerShowData === true
                        && note !== 0 && note !== 64 && note !== 75
                        && note !== frequencyBefore) {

                    $('#frequencies-string2').append('-' + note);
                }

                frequencyBefore = note;
            });

        };

        var errorCallback = function errorCallbackFunction(error) {
            console.log(error);
        };

        navigator.getMedia({audio: true}, gotStreamCallback, errorCallback);
    }

    function Tuner(sourceNode, destinationNode, audioContext, frequenciesExtractor, InjectedNotesFrequencies) {

        this.sourceNode = sourceNode;
        this.destinationNode = destinationNode;
        this.audioContext = audioContext;
        this.frequenciesExtractor = frequenciesExtractor || new FrequenciesExtractor();
//        this.NotesFrequencies = InjectedNotesFrequencies || NotesFrequencies;
        this.count = 0;

        this.start = function (callback) {

            var analyserNode = this.audioContext.createAnalyser();
            analyserNode.fftSize = 2048;
            this.sourceNode.connect(analyserNode);

//        var javascriptNode = this.audioContext.createScriptProcessor(8192, 1, 1);
            var javascriptNode = this.audioContext.createScriptProcessor(false, 1, 1);
            analyserNode.connect(javascriptNode);

            var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);

            var self = this;
            // binding the callback to window to avoid the GC to clean it
            // https://bugzilla.mozilla.org/show_bug.cgi?id=916387
            javascriptNode.onaudioprocess = window.audioProcess = function () {

                analyserNode.getByteFrequencyData(freqByteData);

                var higherValueFrequency = self.frequenciesExtractor.extractHigherValueFrequency(freqByteData, analyserNode.fftSize, self.audioContext.sampleRate);

//            var note = self.NotesFrequencies.findNoteByFrequency(higherValueFrequency);
                var note = Math.floor(higherValueFrequency);

                callback(note);

            };

            javascriptNode.connect(this.destinationNode);
        };

    }

    return {
        frequencyBefore: frequencyBefore,
        tunerActive: tunerActive,
        tunerShowData: tunerShowData,
        startTuner: startTuner
    };

//    NotesFrequencies = {
//        findNoteByFrequency: function (frequency) {
//
//            var roundedFrequency = Math.floor(frequency);
//
//            var foundNoteUp = null;
//            var upFrequencyIndex = roundedFrequency;
//            var done = false;
//            while (!done) {
//                if (this.absNotesFrequencies[upFrequencyIndex] !== undefined) {
//                    foundNoteUp = this.absNotesFrequencies[upFrequencyIndex];
//                    done = true;
//                } else {
//                    upFrequencyIndex++;
//                }
//                if (upFrequencyIndex >= 7902) {
//                    done = true;
//                }
//            }
//
//            var foundNoteDown = null;
//            var downFrequencyIndex = roundedFrequency;
//            done = false;
//            while (!done) {
//                if (this.absNotesFrequencies[downFrequencyIndex] !== undefined) {
//                    foundNoteDown = this.absNotesFrequencies[downFrequencyIndex];
//                    done = true;
//                } else {
//                    downFrequencyIndex--;
//                }
//                if (downFrequencyIndex <= 0) {
//                    done = true;
//                }
//            }
//
//            return foundNoteDown + " / " + foundNoteUp;
//        },
//        absNotesFrequencies: {
//            16: "C0",
//            17: "C#0/Db0",
//            18: "D0",
//            19: "D#0/Eb0",
//            20: "E0",
//            21: "F0",
//            23: "F#0/Gb0",
//            24: "G0",
//            25: "G#0/Ab0",
//            27: "A0",
//            29: "A#0/Bb0",
//            30: "B0",
//            32: "C1",
//            34: "C#1/Db1",
//            36: "D1",
//            38: "D#1/Eb1",
//            41: "E1",
//            43: "F1",
//            46: "F#1/Gb1",
//            49: "G1",
//            51: "G#1/Ab1",
//            55: "A1",
//            58: "A#1/Bb1",
//            61: "B1",
//            65: "C2",
//            69: "C#2/Db2",
//            73: "D2",
//            77: "D#2/Eb2",
//            82: "E2",
//            87: "F2",
//            92: "F#2/Gb2",
//            98: "G2",
//            103: "G#2/Ab2",
//            110: "A2",
//            116: "A#2/Bb2",
//            123: "B2",
//            130: "C3",
//            138: "C#3/Db3",
//            146: "D3",
//            155: "D#3/Eb3",
//            164: "E3",
//            174: "F3",
//            185: "F#3/Gb3",
//            196: "G3",
//            207: "G#3/Ab3",
//            220: "A3",
//            233: "A#3/Bb3",
//            246: "B3",
//            261: "C4",
//            277: "C#4/Db4",
//            293: "D4",
//            311: "D#4/Eb4",
//            329: "E4",
//            349: "F4",
//            369: "F#4/Gb4",
//            392: "G4",
//            415: "G#4/Ab4",
//            440: "A4",
//            466: "A#4/Bb4",
//            493: "B4",
//            523: "C5",
//            554: "C#5/Db5",
//            587: "D5",
//            622: "D#5/Eb5",
//            659: "E5",
//            698: "F5",
//            739: "F#5/Gb5",
//            783: "G5",
//            830: "G#5/Ab5",
//            880: "A5",
//            932: "A#5/Bb5",
//            987: "B5",
//            1046: "C6",
//            1108: "C#6/Db6",
//            1174: "D6",
//            1244: "D#6/Eb6",
//            1318: "E6",
//            1396: "F6",
//            1479: "F#6/Gb6",
//            1567: "G6",
//            1661: "G#6/Ab6",
//            1760: "A6",
//            1864: "A#6/Bb6",
//            1975: "B6",
//            2093: "C7",
//            2217: "C#7/Db7",
//            2349: "D7",
//            2489: "D#7/Eb7",
//            2637: "E7",
//            2793: "F7",
//            2959: "F#7/Gb7",
//            3135: "G7",
//            3322: "G#7/Ab7",
//            3520: "A7",
//            3729: "A#7/Bb7",
//            3951: "B7",
//            4186: "C8",
//            4434: "C#8/Db8",
//            4698: "D8",
//            4978: "D#8/Eb8",
//            5274: "E8",
//            5587: "F8",
//            5919: "F#8/Gb8",
//            6271: "G8",
//            6644: "G#8/Ab8",
//            7040: "A8",
//            7458: "A#8/Bb8",
//            7902: "B8"
//        }
//
//    };
});<commit_msg>changed comment<commit_after>// ADAPTED VERSION OF EXTERNAL SOURCE: https://github.com/FerCa/tuner/
define([
    'jquery',
    'underscore',
    'backbone'
//    'tuner'
], function ($, _, Backbone) {

    var frequencyBefore = 0;
    var tunerActive = false;
    var tunerShowData = true;

    function FrequenciesExtractor() {

        this.extractHigherValueFrequency = function (frequencyByteData, fourierFastTransformSize, sampleRate) {
//console.log('frequencyByteData: ', frequencyByteData);
            var higherValue = 0;
            var higherValueFrequency = 0;
            var length = frequencyByteData.length;
            // Search for the frequency with the higher value
            for (var x = 0; x < length; x++) {

                var frequency = __calculateFrequency(x, sampleRate, fourierFastTransformSize);

                if (frequencyByteData[x] > higherValue) {
                    higherValue = frequencyByteData[x];
                    higherValueFrequency = frequency;
                }
            }

            return higherValueFrequency;
        };

        function __calculateFrequency(position, sampleRate, fourierFastTransformSize) {
            return position * (sampleRate / (fourierFastTransformSize * 2));
        }

    }

    function startTuner() {
        that = this;
        window.AudioContext = window.AudioContext ||
                window.webkitAudioContext;

        navigator.getMedia = (navigator.getUserMedia ||
                navigator.webkitGetUserMedia ||
                navigator.mozGetUserMedia ||
                navigator.msGetUserMedia);

        var audioContext = new AudioContext();

        var gotStreamCallback = function gotStreamCallbackFunction(mediaStream) {
            var microphoneSource = audioContext.createMediaStreamSource(mediaStream);

            var tuner = new Tuner(microphoneSource, audioContext.destination, audioContext);

            tuner.start(function (note) {

//            $('#frequencies-string2').text(note);
                if (that.tunerShowData === true
                        && note !== 0 && note !== 64 && note !== 75
                        && note !== frequencyBefore) {

                    $('#frequencies-string2').append('-' + note);
                }

                frequencyBefore = note;
            });

        };

        var errorCallback = function errorCallbackFunction(error) {
            console.log(error);
        };

        navigator.getMedia({audio: true}, gotStreamCallback, errorCallback);
    }

    function Tuner(sourceNode, destinationNode, audioContext, frequenciesExtractor, InjectedNotesFrequencies) {

        this.sourceNode = sourceNode;
        this.destinationNode = destinationNode;
        this.audioContext = audioContext;
        this.frequenciesExtractor = frequenciesExtractor || new FrequenciesExtractor();
//        this.NotesFrequencies = InjectedNotesFrequencies || NotesFrequencies;
        this.count = 0;

        this.start = function (callback) {

            var analyserNode = this.audioContext.createAnalyser();
            analyserNode.fftSize = 2048;
            this.sourceNode.connect(analyserNode);

//        var javascriptNode = this.audioContext.createScriptProcessor(8192, 1, 1);
            var javascriptNode = this.audioContext.createScriptProcessor(false, 1, 1);
            analyserNode.connect(javascriptNode);

            var freqByteData = new Uint8Array(analyserNode.frequencyBinCount);

            var self = this;
            // binding the callback to window to avoid the GC to clean it
            // https://bugzilla.mozilla.org/show_bug.cgi?id=916387
            javascriptNode.onaudioprocess = window.audioProcess = function () {

                analyserNode.getByteFrequencyData(freqByteData);

                var higherValueFrequency = self.frequenciesExtractor.extractHigherValueFrequency(freqByteData, analyserNode.fftSize, self.audioContext.sampleRate);

//            var note = self.NotesFrequencies.findNoteByFrequency(higherValueFrequency);
                var note = Math.floor(higherValueFrequency);

                callback(note);

            };

            javascriptNode.connect(this.destinationNode);
        };

    }

    return {
        frequencyBefore: frequencyBefore,
        tunerActive: tunerActive,
        tunerShowData: tunerShowData,
        startTuner: startTuner
    };

//    NotesFrequencies = {
//        findNoteByFrequency: function (frequency) {
//
//            var roundedFrequency = Math.floor(frequency);
//
//            var foundNoteUp = null;
//            var upFrequencyIndex = roundedFrequency;
//            var done = false;
//            while (!done) {
//                if (this.absNotesFrequencies[upFrequencyIndex] !== undefined) {
//                    foundNoteUp = this.absNotesFrequencies[upFrequencyIndex];
//                    done = true;
//                } else {
//                    upFrequencyIndex++;
//                }
//                if (upFrequencyIndex >= 7902) {
//                    done = true;
//                }
//            }
//
//            var foundNoteDown = null;
//            var downFrequencyIndex = roundedFrequency;
//            done = false;
//            while (!done) {
//                if (this.absNotesFrequencies[downFrequencyIndex] !== undefined) {
//                    foundNoteDown = this.absNotesFrequencies[downFrequencyIndex];
//                    done = true;
//                } else {
//                    downFrequencyIndex--;
//                }
//                if (downFrequencyIndex <= 0) {
//                    done = true;
//                }
//            }
//
//            return foundNoteDown + " / " + foundNoteUp;
//        },
//        absNotesFrequencies: {
//            16: "C0",
//            17: "C#0/Db0",
//            18: "D0",
//            19: "D#0/Eb0",
//            20: "E0",
//            21: "F0",
//            23: "F#0/Gb0",
//            24: "G0",
//            25: "G#0/Ab0",
//            27: "A0",
//            29: "A#0/Bb0",
//            30: "B0",
//            32: "C1",
//            34: "C#1/Db1",
//            36: "D1",
//            38: "D#1/Eb1",
//            41: "E1",
//            43: "F1",
//            46: "F#1/Gb1",
//            49: "G1",
//            51: "G#1/Ab1",
//            55: "A1",
//            58: "A#1/Bb1",
//            61: "B1",
//            65: "C2",
//            69: "C#2/Db2",
//            73: "D2",
//            77: "D#2/Eb2",
//            82: "E2",
//            87: "F2",
//            92: "F#2/Gb2",
//            98: "G2",
//            103: "G#2/Ab2",
//            110: "A2",
//            116: "A#2/Bb2",
//            123: "B2",
//            130: "C3",
//            138: "C#3/Db3",
//            146: "D3",
//            155: "D#3/Eb3",
//            164: "E3",
//            174: "F3",
//            185: "F#3/Gb3",
//            196: "G3",
//            207: "G#3/Ab3",
//            220: "A3",
//            233: "A#3/Bb3",
//            246: "B3",
//            261: "C4",
//            277: "C#4/Db4",
//            293: "D4",
//            311: "D#4/Eb4",
//            329: "E4",
//            349: "F4",
//            369: "F#4/Gb4",
//            392: "G4",
//            415: "G#4/Ab4",
//            440: "A4",
//            466: "A#4/Bb4",
//            493: "B4",
//            523: "C5",
//            554: "C#5/Db5",
//            587: "D5",
//            622: "D#5/Eb5",
//            659: "E5",
//            698: "F5",
//            739: "F#5/Gb5",
//            783: "G5",
//            830: "G#5/Ab5",
//            880: "A5",
//            932: "A#5/Bb5",
//            987: "B5",
//            1046: "C6",
//            1108: "C#6/Db6",
//            1174: "D6",
//            1244: "D#6/Eb6",
//            1318: "E6",
//            1396: "F6",
//            1479: "F#6/Gb6",
//            1567: "G6",
//            1661: "G#6/Ab6",
//            1760: "A6",
//            1864: "A#6/Bb6",
//            1975: "B6",
//            2093: "C7",
//            2217: "C#7/Db7",
//            2349: "D7",
//            2489: "D#7/Eb7",
//            2637: "E7",
//            2793: "F7",
//            2959: "F#7/Gb7",
//            3135: "G7",
//            3322: "G#7/Ab7",
//            3520: "A7",
//            3729: "A#7/Bb7",
//            3951: "B7",
//            4186: "C8",
//            4434: "C#8/Db8",
//            4698: "D8",
//            4978: "D#8/Eb8",
//            5274: "E8",
//            5587: "F8",
//            5919: "F#8/Gb8",
//            6271: "G8",
//            6644: "G#8/Ab8",
//            7040: "A8",
//            7458: "A#8/Bb8",
//            7902: "B8"
//        }
//
//    };
});<|endoftext|>


<commit_before>const DBus = require('dbus-next');
const debug = require('debug');
const { ipcMain } = require('electron');

const logger = debug('headset:mediaKeys');

let track = null;

ipcMain.on('win2Player', (e, args) => {
  if (args[0] === 'trackInfo') {
    track = args[1];
  }
});

function executeMediaKey(win, key) {
  logger('Executing %o media key command', key);
  win.webContents.executeJavaScript(`
    window.electronConnector.emit('${key}')
  `);
}

async function registerBindings(win, desktopEnv, bus) {
  let serviceName = `org.${desktopEnv}.SettingsDaemon`;
  let objectPath = `/org/${desktopEnv}/SettingsDaemon/MediaKeys`;
  let interfaceName = `org.${desktopEnv}.SettingsDaemon.MediaKeys`;

  if (desktopEnv === 'gnome3') {
    serviceName = 'org.gnome.SettingsDaemon.MediaKeys';
    objectPath = '/org/gnome/SettingsDaemon/MediaKeys';
    interfaceName = 'org.gnome.SettingsDaemon.MediaKeys';
  }

  try {
    const settings = await bus.getProxyObject(serviceName, objectPath);
    const mediaKeys = settings.getInterface(interfaceName);

    mediaKeys.on('MediaPlayerKeyPressed', (iface, n, keyName) => {
      logger('Media key pressed: %o', keyName);
      switch (keyName) {
        case 'Next':
          executeMediaKey(win, 'play-next');
          break;
        case 'Previous':
          executeMediaKey(win, 'play-previous');
          break;
        case 'Play':
          if (track !== null) executeMediaKey(win, 'play-pause');
          break;
        default:
      }
    });

    mediaKeys.GrabMediaPlayerKeys('headset', 0);
    logger('Grabbed media keys for %o', desktopEnv);
  } catch (err) {
    // Error if trying to grab keys in another desktop environment
  }
}

module.exports = (win) => {
  logger('Registering media Keys');
  const bus = DBus.sessionBus();

  registerBindings(win, 'gnome', bus);
  registerBindings(win, 'gnome3', bus);
  registerBindings(win, 'mate', bus);
};
<commit_msg>Fix MediaKeys with new mpris API MediaKeys code only works for Mate and older version of gnome All OSs using gnome3 use MPRIS to send mediakey shortcuts<commit_after>const DBus = require('dbus-next');
const debug = require('debug');
const { ipcMain } = require('electron');

const logger = debug('headset:mediaKeys');

let track = null;

ipcMain.on('win2Player', (e, args) => {
  if (args[0] === 'trackInfo') {
    track = args[1];
  }
});

function executeMediaKey(win, key) {
  logger('Executing %o media key command', key);
  win.webContents.executeJavaScript(`
    window.electronConnector.emit('${key}')
  `);
}

async function registerBindings(win, desktopEnv, bus) {
  let serviceName = `org.${desktopEnv}.SettingsDaemon`;
  let objectPath = `/org/${desktopEnv}/SettingsDaemon/MediaKeys`;
  let interfaceName = `org.${desktopEnv}.SettingsDaemon.MediaKeys`;

  if (desktopEnv === 'gnome3') {
    serviceName = 'org.gnome.SettingsDaemon.MediaKeys';
    objectPath = '/org/gnome/SettingsDaemon/MediaKeys';
    interfaceName = 'org.gnome.SettingsDaemon.MediaKeys';
  }

  try {
    const settings = await bus.getProxyObject(serviceName, objectPath);
    const mediaKeys = settings.getInterface(interfaceName);

    mediaKeys.on('MediaPlayerKeyPressed', (iface, keyName) => {
      logger('Media key pressed: %o', keyName);
      switch (keyName) {
        case 'Next':
          executeMediaKey(win, 'play-next');
          break;
        case 'Previous':
          executeMediaKey(win, 'play-previous');
          break;
        case 'Play':
          if (track !== null) executeMediaKey(win, 'play-pause');
          break;
        default:
      }
    });

    mediaKeys.GrabMediaPlayerKeys('headset', 0);
    logger('Grabbed media keys for %o', desktopEnv);
  } catch (err) {
    // Error if trying to grab keys in another desktop environment
  }
}

module.exports = (win) => {
  logger('Registering media Keys');
  const bus = DBus.sessionBus();

  registerBindings(win, 'gnome', bus);
  registerBindings(win, 'gnome3', bus);
  registerBindings(win, 'mate', bus);
};
<|endoftext|>


<commit_before>const { devices } = require('@playwright/test');

module.exports = {
  testMatch: /.*\/tests\/playwright\/.*\.test\.[jt]sx?/,
  timeout: 10 * 60 * 1500,
  navigationTimeout: 1000,
  retries: 0,
  maxFailures: 0,
  workers: 4,
  fullyParallel: true,
  reporter: 'list',
  projects: [
    {
      name: 'Chromium',
      use: {
        ...devices['Desktop Chromium'],
        headless: false,
      },
    },
    /*
    {
      name: 'Firefox',
      use: {
        ...devices['Desktop Firefox'],
        headless: false,
      },
    },
    {
      name: 'Safari',
      use: {
        ...devices['Desktop Safari'],
        headless: false,
      },
    },
    */
  ],
};
<commit_msg>rename tests folder to test<commit_after>const { devices } = require('@playwright/test');

module.exports = {
  testMatch: /.*\/test\/playwright\/.*\.test\.[jt]sx?/,
  timeout: 10 * 60 * 1500,
  navigationTimeout: 1000,
  retries: 0,
  maxFailures: 0,
  workers: 4,
  fullyParallel: true,
  reporter: 'list',
  projects: [
    {
      name: 'Chromium',
      use: {
        ...devices['Desktop Chromium'],
        headless: false,
      },
    },
    /*
    {
      name: 'Firefox',
      use: {
        ...devices['Desktop Firefox'],
        headless: false,
      },
    },
    {
      name: 'Safari',
      use: {
        ...devices['Desktop Safari'],
        headless: false,
      },
    },
    */
  ],
};
<|endoftext|>


<commit_before>define(function(){
	if (!Array.prototype.indexOf) {
	  Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
	    "use strict";
	    if (this == null) {
	      throw new TypeError();
	    }
	    var t = Object(this);
	    var len = t.length >>> 0;

	    if (len === 0) {
	      return -1;
	    }
	    var n = 0;
	    if (arguments.length > 1) {
	      n = Number(arguments[1]);
	      if (n != n) { // shortcut for verifying if it's NaN
	        n = 0;
	      } else if (n != 0 && n != Infinity && n != -Infinity) {
	        n = (n > 0 || -1) * Math.floor(Math.abs(n));
	      }
	    }
	    if (n >= len) {
	      return -1;
	    }
	    var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
	    for (; k < len; k++) {
	      if (k in t && t[k] === searchElement) {
	        return k;
	      }
	    }
	    return -1;
	  }
	}
	if (!Object.keys) {
	  Object.keys = (function () {
	    var hasOwnProperty = Object.prototype.hasOwnProperty,
	        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
	        dontEnums = [
	          'toString',
	          'toLocaleString',
	          'valueOf',
	          'hasOwnProperty',
	          'isPrototypeOf',
	          'propertyIsEnumerable',
	          'constructor'
	        ],
	        dontEnumsLength = dontEnums.length;

	    return function (obj) {
	      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

	      var result = [];

	      for (var prop in obj) {
	        if (hasOwnProperty.call(obj, prop)) result.push(prop);
	      }

	      if (hasDontEnumBug) {
	        for (var i=0; i < dontEnumsLength; i++) {
	          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
	        }
	      }
	      return result;
	    };
	  })();
	}

	if ( !Array.prototype.forEach ) {
	  Array.prototype.forEach = function(fn, scope) {
		for(var i = 0, len = this.length; i < len; ++i) {
		  fn.call(scope || this, this[i], i, this);
		}
	  }
	}
	if (!Function.prototype.bind) {
	  Function.prototype.bind = function (oThis) {
		if (typeof this !== "function") {
		  // closest thing possible to the ECMAScript 5 internal IsCallable function
		  throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
		}

		var aArgs = Array.prototype.slice.call(arguments, 1),
			fToBind = this,
			fNOP = function () {},
			fBound = function () {
			  return fToBind.apply(this instanceof fNOP
									 ? this
									 : oThis,
								   aArgs.concat(Array.prototype.slice.call(arguments)));
			};

		fNOP.prototype = this.prototype;
		fBound.prototype = new fNOP();

		return fBound;
	  };
	}
	if (!String.prototype.trim) {
		String.prototype.trim = function() {
			var that = this.replace(/^\s\s*/, ''),
				ws = /\s/,
				i = that.length;
			while (ws.test(that.charAt(--i)));
			return that.slice(0, i + 1);
		}
	}
	/**
	 * Date.parse with progressive enhancement for ISO 8601 <https://github.com/csnover/js-iso8601>
	 *  2011 Colin Snover <http://zetafleet.com>
	 * Released under MIT license.
	 */
	(function (Date, undefined) {
		var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
		Date.parse = function (date) {
			var timestamp, struct, minutesOffset = 0;

			// ES5 15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
			// before falling back to any implementation-specific date parsing, so thats what we do, even if native
			// implementations could be faster
			//              1 YYYY                2 MM       3 DD           4 HH    5 mm       6 ss        7 msec        8 Z 9     10 tzHH    11 tzmm
			if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
				// avoid NaN timestamps caused by undefined values being passed to Date.UTC
				for (var i = 0, k; (k = numericKeys[i]); ++i) {
					struct[k] = +struct[k] || 0;
				}

				// allow undefined days and months
				struct[2] = (+struct[2] || 1) - 1;
				struct[3] = +struct[3] || 1;

				if (struct[8] !== 'Z' && struct[9] !== undefined) {
					minutesOffset = struct[10] * 60 + struct[11];

					if (struct[9] === '+') {
						minutesOffset = 0 - minutesOffset;
					}
				}

				timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
			}
			else {
				timestamp = origParse ? origParse(date) : NaN;
			}

			return timestamp;
		};
	}(Date));
	if ( !Date.prototype.toISOString ) {

		( function() {

			function pad(number) {
				var r = String(number);
				if ( r.length === 1 ) {
					r = '0' + r;
				}
				return r;
			}

			Date.prototype.toISOString = function() {
				return this.getUTCFullYear()
					+ '-' + pad( this.getUTCMonth() + 1 )
					+ '-' + pad( this.getUTCDate() )
					+ 'T' + pad( this.getUTCHours() )
					+ ':' + pad( this.getUTCMinutes() )
					+ ':' + pad( this.getUTCSeconds() )
					+ '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
					+ 'Z';
			};

		}() );
	}
	//addition to make smart wrap not a default method
	String.prototype.trunc =
	function(n,useWordBoundary){
		var toLong = this.length>n,
			s_ = toLong ? this.substr(0,n-1) : this;
		s_ = useWordBoundary && toLong ? s_.substr(0,s_.lastIndexOf(' ')) : s_;
		return  toLong ? s_ + '...' : s_;
	 };
});<commit_msg>fix: wrong enconding.<commit_after>define(function(){
	if (!Array.prototype.indexOf) {
	  Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
	    "use strict";
	    if (this == null) {
	      throw new TypeError();
	    }
	    var t = Object(this);
	    var len = t.length >>> 0;

	    if (len === 0) {
	      return -1;
	    }
	    var n = 0;
	    if (arguments.length > 1) {
	      n = Number(arguments[1]);
	      if (n != n) { // shortcut for verifying if it's NaN
	        n = 0;
	      } else if (n != 0 && n != Infinity && n != -Infinity) {
	        n = (n > 0 || -1) * Math.floor(Math.abs(n));
	      }
	    }
	    if (n >= len) {
	      return -1;
	    }
	    var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);
	    for (; k < len; k++) {
	      if (k in t && t[k] === searchElement) {
	        return k;
	      }
	    }
	    return -1;
	  }
	}
	if (!Object.keys) {
	  Object.keys = (function () {
	    var hasOwnProperty = Object.prototype.hasOwnProperty,
	        hasDontEnumBug = !({toString: null}).propertyIsEnumerable('toString'),
	        dontEnums = [
	          'toString',
	          'toLocaleString',
	          'valueOf',
	          'hasOwnProperty',
	          'isPrototypeOf',
	          'propertyIsEnumerable',
	          'constructor'
	        ],
	        dontEnumsLength = dontEnums.length;

	    return function (obj) {
	      if (typeof obj !== 'object' && typeof obj !== 'function' || obj === null) throw new TypeError('Object.keys called on non-object');

	      var result = [];

	      for (var prop in obj) {
	        if (hasOwnProperty.call(obj, prop)) result.push(prop);
	      }

	      if (hasDontEnumBug) {
	        for (var i=0; i < dontEnumsLength; i++) {
	          if (hasOwnProperty.call(obj, dontEnums[i])) result.push(dontEnums[i]);
	        }
	      }
	      return result;
	    };
	  })();
	}

	if ( !Array.prototype.forEach ) {
	  Array.prototype.forEach = function(fn, scope) {
		for(var i = 0, len = this.length; i < len; ++i) {
		  fn.call(scope || this, this[i], i, this);
		}
	  }
	}
	if (!Function.prototype.bind) {
	  Function.prototype.bind = function (oThis) {
		if (typeof this !== "function") {
		  // closest thing possible to the ECMAScript 5 internal IsCallable function
		  throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");
		}

		var aArgs = Array.prototype.slice.call(arguments, 1),
			fToBind = this,
			fNOP = function () {},
			fBound = function () {
			  return fToBind.apply(this instanceof fNOP
									 ? this
									 : oThis,
								   aArgs.concat(Array.prototype.slice.call(arguments)));
			};

		fNOP.prototype = this.prototype;
		fBound.prototype = new fNOP();

		return fBound;
	  };
	}
	if (!String.prototype.trim) {
		String.prototype.trim = function() {
			var that = this.replace(/^\s\s*/, ''),
				ws = /\s/,
				i = that.length;
			while (ws.test(that.charAt(--i)));
			return that.slice(0, i + 1);
		}
	}
	/**
	 * Date.parse with progressive enhancement for ISO 8601 <https://github.com/csnover/js-iso8601>
	 * © 2011 Colin Snover <http://zetafleet.com>
	 * Released under MIT license.
	 */
	(function (Date, undefined) {
		var origParse = Date.parse, numericKeys = [ 1, 4, 5, 6, 7, 10, 11 ];
		Date.parse = function (date) {
			var timestamp, struct, minutesOffset = 0;

			// ES5 §15.9.4.2 states that the string should attempt to be parsed as a Date Time String Format string
			// before falling back to any implementation-specific date parsing, so that’s what we do, even if native
			// implementations could be faster
			//              1 YYYY                2 MM       3 DD           4 HH    5 mm       6 ss        7 msec        8 Z 9 ±    10 tzHH    11 tzmm
			if ((struct = /^(\d{4}|[+\-]\d{6})(?:-(\d{2})(?:-(\d{2}))?)?(?:T(\d{2}):(\d{2})(?::(\d{2})(?:\.(\d{3}))?)?(?:(Z)|([+\-])(\d{2})(?::(\d{2}))?)?)?$/.exec(date))) {
				// avoid NaN timestamps caused by “undefined” values being passed to Date.UTC
				for (var i = 0, k; (k = numericKeys[i]); ++i) {
					struct[k] = +struct[k] || 0;
				}

				// allow undefined days and months
				struct[2] = (+struct[2] || 1) - 1;
				struct[3] = +struct[3] || 1;

				if (struct[8] !== 'Z' && struct[9] !== undefined) {
					minutesOffset = struct[10] * 60 + struct[11];

					if (struct[9] === '+') {
						minutesOffset = 0 - minutesOffset;
					}
				}

				timestamp = Date.UTC(struct[1], struct[2], struct[3], struct[4], struct[5] + minutesOffset, struct[6], struct[7]);
			}
			else {
				timestamp = origParse ? origParse(date) : NaN;
			}

			return timestamp;
		};
	}(Date));
	if ( !Date.prototype.toISOString ) {

		( function() {

			function pad(number) {
				var r = String(number);
				if ( r.length === 1 ) {
					r = '0' + r;
				}
				return r;
			}

			Date.prototype.toISOString = function() {
				return this.getUTCFullYear()
					+ '-' + pad( this.getUTCMonth() + 1 )
					+ '-' + pad( this.getUTCDate() )
					+ 'T' + pad( this.getUTCHours() )
					+ ':' + pad( this.getUTCMinutes() )
					+ ':' + pad( this.getUTCSeconds() )
					+ '.' + String( (this.getUTCMilliseconds()/1000).toFixed(3) ).slice( 2, 5 )
					+ 'Z';
			};

		}() );
	}
	//addition to make smart wrap not a default method
	String.prototype.trunc =
	function(n,useWordBoundary){
		var toLong = this.length>n,
			s_ = toLong ? this.substr(0,n-1) : this;
		s_ = useWordBoundary && toLong ? s_.substr(0,s_.lastIndexOf(' ')) : s_;
		return  toLong ? s_ + '...' : s_;
	 };
});<|endoftext|>


<commit_before>function drawChart(title, containerId, data, yLabel, startTime, interval) {
	//startTime is a Date object.
	//interval is second amount.
	//startTime and interval are optional.
	var plotObj = $.jqplot(containerId, [eval(data)], {
        title: {
			text: title,
			fontSize: '16pt'
		},
		seriesDefaults: {
			markerRenderer: $.jqplot.MarkerRenderer,
			markerOptions: {
				size: 5.0,
				color: '#555555'
			},
			lineWidth: 2.0
		},
		axes: {
            xaxis: {
				tickRenderer : $.jqplot.AxisTickRenderer,
                tickOptions: {
					show: false,
					formatter: function(format, value) {
						if (startTime) {
							if (interval) {
								return new Date(startTime.getTime() + value * interval * 1000).toLocaleString();
							} else {
								return new Date(startTime.getTime() + value * 1000).toLocaleString();
							}
						} else {
							return value;
						}
					}
                }
            },
            yaxis: {
				tickRenderer : $.jqplot.CanvasAxisTickRenderer,
				labelRenderer : $.jqplot.CanvasAxisLabelRenderer,
				label : yLabel,
				labelOptions : {
					fontFamily : 'Helvetica',
					fontSize : '12pt'
				},
				tickOptions : {
					angle : -30
				},
				pad: 0,
				numberTicks: 8
            },

        },
		highlighter: {
			show: true,
			sizeAdjust: 3
		},
        cursor:{
			showTooltip:false,
            show: true,
            zoom: true
        }
    });

	return plotObj;
}<commit_msg>[NGRINDER-48]Create pages, update UI style or js. add format for y-axis of chart.<commit_after>function drawChart(title, containerId, data, yLabel, startTime, interval) {
	//startTime is a Date object.
	//interval is second amount.
	//startTime and interval are optional.
	var plotObj = $.jqplot(containerId, [eval(data)], {
        title: {
			text: title,
			fontSize: '16pt'
		},
		seriesDefaults: {
			markerRenderer: $.jqplot.MarkerRenderer,
			markerOptions: {
				size: 5.0,
				color: '#555555'
			},
			lineWidth: 2.0
		},
		axes: {
            xaxis: {
				tickRenderer : $.jqplot.AxisTickRenderer,
                tickOptions: {
					show: false,
					formatter: function(format, value) {
						if (startTime) {
							if (interval) {
								return new Date(startTime.getTime() + value * interval * 1000).toLocaleString();
							} else {
								return new Date(startTime.getTime() + value * 1000).toLocaleString();
							}
						} else {
							return value;
						}
					}
                }
            },
            yaxis: {
				tickRenderer : $.jqplot.CanvasAxisTickRenderer,
				labelRenderer : $.jqplot.CanvasAxisLabelRenderer,
				label : yLabel,
				labelOptions : {
					fontFamily : 'Helvetica',
					fontSize : '12pt'
				},
				tickOptions : {
					angle : -30,
					formatter: function(format, value) {
						if (value < 1000) {
							return value;
						} else if (value < 1000000) {
							return (value/1000).toFixed(2) + "K";
						} else if (value < 1000000000) {
							return (value/1000000).toFixed(2) + "M";
						} else {
							return (value/1000000000).toFixed(2) + "G";
						}
					}
				},
				pad: 0,
				numberTicks: 8
            },

        },
		highlighter: {
			show: true,
			sizeAdjust: 3
		},
        cursor:{
			showTooltip:false,
            show: true,
            zoom: true
        }
    });

	return plotObj;
}<|endoftext|>


<commit_before>AppUtil = {};

AppUtil.run = function (app) {
  var image = Images.findOne({_id: app.imageId});
  // Delete old container if one already exists
  Docker.removeContainer(app.name, function (err) {
    if (err) { console.error(err); }
    Docker.runContainer(app, image, function (err, container) {
      if (err) { throw err; }
      Docker.getContainerData(container.id, function (err, data) {
        if (err) { console.error(err); }
        // Set a delay for app to spin up
        Meteor.setTimeout(function () {
          Apps.update(app._id, {$set: {
            docker: data,
            status: 'READY'
          }});
        }, 2500);
      });
    });
  });
};

AppUtil.restartHelper = function (app) {
  if (app.docker && app.docker.Id) {
    Docker.restartContainer(app.docker.Id, function (err) {
      if (err) { console.error(err); }
      Docker.getContainerData(app.docker.Id, function (err, data) {
        if (err) { console.error(err); }
        Apps.update(app._id, {$set: {
          status: 'READY',
          docker: data
        }});
        // Use dig to refresh the DNS
        exec('/usr/bin/dig ' + app.name + '.kite @172.17.42.1', function(err, stdout, stderr) {
          console.log(err);
          console.log(stdout);
          console.log(stderr);
        });
      });
    });
  }
};

AppUtil.restart = function (appId) {
  var app = Apps.findOne(appId);
  if (app && app.docker) {
    Apps.update(app._id, {$set: {
      status: 'STARTING'
    }});
    AppUtil.restartHelper(app);
  }
};

AppUtil.remove = function (appId) {
  var app = Apps.findOne(appId);
  if (app.docker) {
    Apps.remove({_id: appId});
    Docker.removeContainer(app.docker.Id, function (err) {
      if (err) { console.error(err); }
      var appPath = path.join(KITE_PATH, app.name);
      Util.deleteFolder(appPath);
      Docker.removeBindFolder(app.name, function () {
        console.log('Deleted Kite ' + app.name + ' directory.');
      });
    });
  }
};

AppUtil.configVar = function (appId, configVars) {
  Apps.update(appId, {$set: {
    config: configVars,
    status: 'STARTING'
  }});
  var app = Apps.findOne({_id: appId});
  AppUtil.run(app);
};

AppUtil.logs = function (appId) {
  var app = Apps.findOne(appId);
  if (app.docker && app.docker.Id) {
    var container = docker.getContainer(app.docker.Id);
    container.logs({follow: false, stdout: true, stderr: true, timestamps: false, tail: 300}, function (err, response) {
      if (err) { throw err; }
      Apps.update(app._id, {
        $set: {
          logs: []
        }
      });
      var logs = [];
      response.setEncoding('utf8');
      response.on('data', function (line) {
        logs.push(convert.toHtml(line.slice(8)));
        Apps.update(app._id, {
          $set: {
            logs: logs
          }
        });
      });
      response.on('end', function () {});
    });
  }
};

AppUtil.recover = function () {
  var apps = Apps.find({}).fetch();
  _.each(apps, function (app) {
    // Update the app with the latest container info
    if (!app.docker) {
      return;
    }
    var container = docker.getContainer(app.docker.Id);
    container.inspect(function (err, data) {
      if (app.status !== 'STARTING' && data && data.State && !data.State.Running) {
        console.log('Restarting: ' + app.name);
        console.log(app.docker.Id);
        AppUtil.restartHelper(app, function (err) {
          if (err) { console.error(err); }
        });
      }
    });
  });
};
<commit_msg>Only updates status after dig is ran.<commit_after>AppUtil = {};

AppUtil.run = function (app) {
  var image = Images.findOne({_id: app.imageId});
  // Delete old container if one already exists
  Docker.removeContainer(app.name, function (err) {
    if (err) { console.error(err); }
    Docker.runContainer(app, image, function (err, container) {
      if (err) { throw err; }
      Docker.getContainerData(container.id, function (err, data) {
        if (err) { console.error(err); }
        // Set a delay for app to spin up
        Meteor.setTimeout(function () {
          Apps.update(app._id, {$set: {
            docker: data,
            status: 'READY'
          }});
        }, 2500);
      });
    });
  });
};

AppUtil.restartHelper = function (app) {
  if (app.docker && app.docker.Id) {
    Docker.restartContainer(app.docker.Id, function (err) {
      if (err) { console.error(err); }
      Docker.getContainerData(app.docker.Id, function (err, data) {
        if (err) { console.error(err); }
        // Use dig to refresh the DNS
        exec('/usr/bin/dig ' + app.name + '.kite @172.17.42.1', function(err, stdout, stderr) {
          console.log(err);
          console.log(stdout);
          console.log(stderr);
          Apps.update(app._id, {$set: {
            status: 'READY',
            docker: data
          }});
        });
      });
    });
  }
};

AppUtil.restart = function (appId) {
  var app = Apps.findOne(appId);
  if (app && app.docker) {
    Apps.update(app._id, {$set: {
      status: 'STARTING'
    }});
    AppUtil.restartHelper(app);
  }
};

AppUtil.remove = function (appId) {
  var app = Apps.findOne(appId);
  if (app.docker) {
    Apps.remove({_id: appId});
    Docker.removeContainer(app.docker.Id, function (err) {
      if (err) { console.error(err); }
      var appPath = path.join(KITE_PATH, app.name);
      Util.deleteFolder(appPath);
      Docker.removeBindFolder(app.name, function () {
        console.log('Deleted Kite ' + app.name + ' directory.');
      });
    });
  }
};

AppUtil.configVar = function (appId, configVars) {
  Apps.update(appId, {$set: {
    config: configVars,
    status: 'STARTING'
  }});
  var app = Apps.findOne({_id: appId});
  AppUtil.run(app);
};

AppUtil.logs = function (appId) {
  var app = Apps.findOne(appId);
  if (app.docker && app.docker.Id) {
    var container = docker.getContainer(app.docker.Id);
    container.logs({follow: false, stdout: true, stderr: true, timestamps: false, tail: 300}, function (err, response) {
      if (err) { throw err; }
      Apps.update(app._id, {
        $set: {
          logs: []
        }
      });
      var logs = [];
      response.setEncoding('utf8');
      response.on('data', function (line) {
        logs.push(convert.toHtml(line.slice(8)));
        Apps.update(app._id, {
          $set: {
            logs: logs
          }
        });
      });
      response.on('end', function () {});
    });
  }
};

AppUtil.recover = function () {
  var apps = Apps.find({}).fetch();
  _.each(apps, function (app) {
    // Update the app with the latest container info
    if (!app.docker) {
      return;
    }
    var container = docker.getContainer(app.docker.Id);
    container.inspect(function (err, data) {
      if (app.status !== 'STARTING' && data && data.State && !data.State.Running) {
        console.log('Restarting: ' + app.name);
        console.log(app.docker.Id);
        AppUtil.restartHelper(app, function (err) {
          if (err) { console.error(err); }
        });
      }
    });
  });
};
<|endoftext|>


<commit_before>/**
 * This object represents a tileset used by a TiledMap.
 * There can be multiple Tilesets in a map
 *
 * @class TiledTileset
 * @extends gf.Texture
 * @namespace gf
 * @constructor
 * @param settings {Object} All the settings for the tileset
 */
//TODO: Support external tilesets (TSX files) via the "source" attribute
//see: https://github.com/bjorn/tiled/wiki/TMX-Map-Format#tileset
gf.TiledTileset = function(settings) {
    if(!gf.assetCache[settings.name + '_texture']) {
        throw 'You must preload the tileset images! Try loading the world file with the AssetLoader';
    }

    //initialize the base Texture class
    gf.Texture.call(this, gf.assetCache[settings.name + '_texture'].baseTexture);

    //Tiled Editor properties

    /**
     * The first tileId in the tileset
     *
     * @property firstgid
     * @type Number
     */
    this.firstgid = settings.firstgid;

    /**
     * The name of the tileset
     *
     * @property name
     * @type String
     */
    this.name = settings.name;

    /**
     * The size of a tile in the tileset
     *
     * @property tileSize
     * @type Vector
     */
    this.tileSize = new gf.Vector(settings.tilewidth, settings.tileheight);

    /**
     * The spacing around a tile in the tileset
     *
     * @property spacing
     * @type Number
     */
    this.spacing = settings.spacing || 0;

    /**
     * The margin around a tile in the tileset
     *
     * @property margin
     * @type Number
     */
    this.margin = settings.margin || 0;

    /**
     * The offset of tile positions when rendered
     *
     * @property tileoffset
     * @type Number
     */
    this.tileoffset = new gf.Vector(
        settings.tileoffset ? settings.tileoffset.x : 0,
        settings.tileoffset ? settings.tileoffset.y : 0
    );

    //TODO: Support for "tileoffset," "terraintypes," "image"
    //see: https://github.com/bjorn/tiled/wiki/TMX-Map-Format#tileset

    //Custom/Optional properties

    /**
     * The number of tiles calculated based on size, margin, and spacing
     *
     * @property numTiles
     * @type Vector
     */
    this.numTiles = new gf.Vector(
        ~~((this.baseTexture.source.width - this.margin) / (this.tileSize.x - this.spacing)), //75 /
        ~~((this.baseTexture.source.height - this.margin) / (this.tileSize.y - this.spacing))
    );

    /**
     * The last tileId in the tileset
     *
     * @property lastgid
     * @type Number
     */
    this.lastgid = this.firstgid + (((this.numTiles.x * this.numTiles.y) - 1) || 0);

    /**
     * The properties of the tileset
     *
     * @property properties
     * @type Object
     */
    this.properties = settings.properties || {};

    /**
     * The properties of the tiles in the tileset (like collision stuff)
     *
     * @property tileproperties
     * @type Object
     */
    this.tileproperties = settings.tileproperties || {};

    /**
     * The size of the tileset
     *
     * @property size
     * @type Vector
     */
    this.size = new gf.Vector(settings.imagewidth, settings.imageheight);

    /**
     * The texture instances for each tile in the set
     *
     * @property textures
     * @type Array
     */
    this.textures = [];

    //ensure hitArea is a polygon
    if(this.properties.hitArea) {
        var h = this.properties.hitArea.split(gf.utils._arrayDelim);

        //odd number of values
        if(h.length % 2 !== 0) {
            throw 'Uneven number of values for hitArea on tileset! Should be a flat array of x/y values.';
        }

        var hv = [];
        for(var i = 0, il = h.length; i < il; ++i) {
            hv.push(parseFloat(h[i], 10));
        }
        this.properties.hitArea = new gf.Polygon(hv);
    }

    //massage tile properties
    for(var k in this.tileproperties) {
        var v = this.tileproperties[k];

        if(v.normal) v.normal = gf.utils.ensureVector(v.normal);

        if(v.isCollidable === 'true') v.isCollidable = true;
        if(v.isBreakable === 'true') v.isBreakable = true;

        if(v.hitArea) {
            var ha = v.hitArea.split(gf.utils._arrayDelim);

            //odd number of values
            if(ha.length % 2 !== 0) {
                throw 'Uneven number of values for hitArea on a tile of a tileset! Should be a flat array of x/y values.';
            }

            var hav = [];
            for(var p = 0, pl = ha.length; p < pl; p+=2) {
                hav.push(
                    new gf.Point(
                        parseFloat(ha[p], 10),
                        parseFloat(ha[p + 1], 10)
                    )
                );
            }
            v.hitArea = new gf.Polygon(hav);
        }
    }

    //generate tile textures
    for(var t = 0, tl = this.lastgid - this.firstgid + 1; t < tl; ++t) {
        //convert the tileId to x,y coords of the tile in the Texture
        var y = ~~(t / this.numTiles.x),
            x = (t - (y * this.numTiles.x));

        //get location in pixels
        x = (x * this.tileSize.x) + (x * this.spacing) + this.margin;
        y = (y * this.tileSize.y) + (y * this.spacing) + this.margin;

        this.textures.push(
            new gf.Texture(
                this.baseTexture,
                new PIXI.Rectangle(x, y, this.tileSize.x, this.tileSize.y)
            )
        );
    }
};

gf.inherits(gf.TiledTileset, gf.Texture, {
    /**
     * Gets the tile properties for a tile based on it's ID
     *
     * @method getTileProperties
     * @param tileId {Number} The id of the tile to get the properties for
     * @return {Object} The properties of the tile
     */
    getTileProperties: function(tileId) {
        if(tileId === undefined) return null;

        tileId = tileId - this.firstgid;

        //if less than 0, then this id isn't in this tileset
        if(tileId < 0) return null;

        return this.tileproperties[tileId] ?
                //get this value
                this.tileproperties[tileId] :
                //set this id to default values and cache
                this.tileproperties[tileId] = {
                    isCollidable: false,
                    isBreakable: false,
                    type: gf.Tile.TYPE.NONE
                };
    },
    /**
     * Gets the tile texture for a tile based on it's ID
     *
     * @method getTileTexture
     * @param tileId {Number} The id of the tile to get the texture for
     * @return {Texture} The texture for the tile
     */
    getTileTexture: function(tileId) {
        if(tileId === undefined) return null;

        //get the internal ID of the tile in this set (0 indexed)
        tileId = tileId - this.firstgid;

        //if less than 0, then this id isn't in this tileset
        if(tileId < 0) return null;

        return this.textures[tileId];
    }
});
<commit_msg>better hitArea support in tileset<commit_after>/**
 * This object represents a tileset used by a TiledMap.
 * There can be multiple Tilesets in a map
 *
 * @class TiledTileset
 * @extends gf.Texture
 * @namespace gf
 * @constructor
 * @param settings {Object} All the settings for the tileset
 */
//TODO: Support external tilesets (TSX files) via the "source" attribute
//see: https://github.com/bjorn/tiled/wiki/TMX-Map-Format#tileset
gf.TiledTileset = function(settings) {
    if(!gf.assetCache[settings.name + '_texture']) {
        throw 'You must preload the tileset images! Try loading the world file with the AssetLoader';
    }

    //initialize the base Texture class
    gf.Texture.call(this, gf.assetCache[settings.name + '_texture'].baseTexture);

    //Tiled Editor properties

    /**
     * The first tileId in the tileset
     *
     * @property firstgid
     * @type Number
     */
    this.firstgid = settings.firstgid;

    /**
     * The name of the tileset
     *
     * @property name
     * @type String
     */
    this.name = settings.name;

    /**
     * The size of a tile in the tileset
     *
     * @property tileSize
     * @type Vector
     */
    this.tileSize = new gf.Vector(settings.tilewidth, settings.tileheight);

    /**
     * The spacing around a tile in the tileset
     *
     * @property spacing
     * @type Number
     */
    this.spacing = settings.spacing || 0;

    /**
     * The margin around a tile in the tileset
     *
     * @property margin
     * @type Number
     */
    this.margin = settings.margin || 0;

    /**
     * The offset of tile positions when rendered
     *
     * @property tileoffset
     * @type Number
     */
    this.tileoffset = new gf.Vector(
        settings.tileoffset ? settings.tileoffset.x : 0,
        settings.tileoffset ? settings.tileoffset.y : 0
    );

    //TODO: Support for "tileoffset," "terraintypes," "image"
    //see: https://github.com/bjorn/tiled/wiki/TMX-Map-Format#tileset

    //Custom/Optional properties

    /**
     * The number of tiles calculated based on size, margin, and spacing
     *
     * @property numTiles
     * @type Vector
     */
    this.numTiles = new gf.Vector(
        ~~((this.baseTexture.source.width - this.margin) / (this.tileSize.x - this.spacing)), //75 /
        ~~((this.baseTexture.source.height - this.margin) / (this.tileSize.y - this.spacing))
    );

    /**
     * The last tileId in the tileset
     *
     * @property lastgid
     * @type Number
     */
    this.lastgid = this.firstgid + (((this.numTiles.x * this.numTiles.y) - 1) || 0);

    /**
     * The properties of the tileset
     *
     * @property properties
     * @type Object
     */
    this.properties = settings.properties || {};

    /**
     * The properties of the tiles in the tileset (like collision stuff)
     *
     * @property tileproperties
     * @type Object
     */
    this.tileproperties = settings.tileproperties || {};

    /**
     * The size of the tileset
     *
     * @property size
     * @type Vector
     */
    this.size = new gf.Vector(settings.imagewidth, settings.imageheight);

    /**
     * The texture instances for each tile in the set
     *
     * @property textures
     * @type Array
     */
    this.textures = [];

    //ensure hitArea is a polygon
    if(this.properties.hitArea) {
        var h = this.properties.hitArea.replace(/\[\]/g, '').split(gf.utils._arrayDelim);

        //odd number of values
        if(h.length % 2 !== 0 && h.length !== 3) {
            throw 'Strange number of values for hitArea on tileset! Should be a flat array of values, like: [x,y,r] for a circle, [x,y,w,h] for a rectangle, or [x,y,x,y,...] for other polygons.';
        }

        var hv = [];
        for(var i = 0, il = h.length; i < il; ++i) {
            hv.push(parseFloat(h[i], 10));
        }

        //a circle x,y,r
        if(hv.length === 3) {
            this.properties.hitArea = new gf.Circle(hv[0], hv[1], hv[2]);
        }
        //a rectangle x,y,w,h
        else if(hv.length === 4) {
            this.properties.hitArea = new gf.Rectangle(hv[0], hv[1], hv[2], hv[3]);
        }
        //generic polygon
        else {
            this.properties.hitArea = new gf.Polygon(hv);
        }
    }

    //massage tile properties
    for(var k in this.tileproperties) {
        var v = this.tileproperties[k];

        if(v.normal) v.normal = gf.utils.ensureVector(v.normal);

        if(v.isCollidable === 'true') v.isCollidable = true;
        if(v.isBreakable === 'true') v.isBreakable = true;

        if(v.hitArea) {
            var ha = v.hitArea.split(gf.utils._arrayDelim);

            //odd number of values
            if(ha.length % 2 !== 0) {
                throw 'Uneven number of values for hitArea on a tile of a tileset! Should be a flat array of x/y values.';
            }

            var hav = [];
            for(var p = 0, pl = ha.length; p < pl; p+=2) {
                hav.push(
                    new gf.Point(
                        parseFloat(ha[p], 10),
                        parseFloat(ha[p + 1], 10)
                    )
                );
            }
            v.hitArea = new gf.Polygon(hav);
        }
    }

    //generate tile textures
    for(var t = 0, tl = this.lastgid - this.firstgid + 1; t < tl; ++t) {
        //convert the tileId to x,y coords of the tile in the Texture
        var y = ~~(t / this.numTiles.x),
            x = (t - (y * this.numTiles.x));

        //get location in pixels
        x = (x * this.tileSize.x) + (x * this.spacing) + this.margin;
        y = (y * this.tileSize.y) + (y * this.spacing) + this.margin;

        this.textures.push(
            new gf.Texture(
                this.baseTexture,
                new PIXI.Rectangle(x, y, this.tileSize.x, this.tileSize.y)
            )
        );
    }
};

gf.inherits(gf.TiledTileset, gf.Texture, {
    /**
     * Gets the tile properties for a tile based on it's ID
     *
     * @method getTileProperties
     * @param tileId {Number} The id of the tile to get the properties for
     * @return {Object} The properties of the tile
     */
    getTileProperties: function(tileId) {
        if(tileId === undefined) return null;

        tileId = tileId - this.firstgid;

        //if less than 0, then this id isn't in this tileset
        if(tileId < 0) return null;

        return this.tileproperties[tileId] ?
                //get this value
                this.tileproperties[tileId] :
                //set this id to default values and cache
                this.tileproperties[tileId] = {
                    isCollidable: false,
                    isBreakable: false,
                    type: gf.Tile.TYPE.NONE
                };
    },
    /**
     * Gets the tile texture for a tile based on it's ID
     *
     * @method getTileTexture
     * @param tileId {Number} The id of the tile to get the texture for
     * @return {Texture} The texture for the tile
     */
    getTileTexture: function(tileId) {
        if(tileId === undefined) return null;

        //get the internal ID of the tile in this set (0 indexed)
        tileId = tileId - this.firstgid;

        //if less than 0, then this id isn't in this tileset
        if(tileId < 0) return null;

        return this.textures[tileId];
    }
});
<|endoftext|>


<commit_before>(function () {
  angular.module('mnBucketsService', [
    'mnBucketsStats'
  ]).factory('mnBucketsService', mnBucketsServiceFactory);

  function mnBucketsServiceFactory($http, $q, mnBucketsStats) {
    var mnBucketsService = {
      getBucketsByType: getBucketsByType,
      getBucketsForBucketsPage: getBucketsForBucketsPage
    };

    return mnBucketsService;

    function getPieConfig(bucket) {
      var h = _.reduce(_.pluck(bucket.nodes, 'status'), function (counts, stat) {
        counts[stat] = (counts[stat] || 0) + 1;
        return counts;
      }, {});

      var pieConfig = {};
      var healthStats = [h.healthy || 0, h.warmup || 0, h.unhealthy || 0];
      pieConfig.status = _.clone(healthStats);

      var total = _.inject(healthStats, function (a,b) {return a+b}, 0);

      var minimalAngle = Math.PI/180*30;
      var nodeSize = total < 1E-6 ? 0 : Math.PI*2/total;

      var stolenSize = 0;
      var maxAngle = 0;
      var maxIndex = -1;

      for (var i = healthStats.length; i--;) {
        var newValue = healthStats[i] * nodeSize;
        if (newValue != 0 && newValue < minimalAngle) {
          stolenSize += minimalAngle - newValue;
          newValue = minimalAngle;
        }
        healthStats[i] = newValue;
        if (newValue >= maxAngle) {
          maxAngle = newValue;
          maxIndex = i;
        }
      }

      pieConfig.series = healthStats;
      bucket.pieConfig = pieConfig;
    }

    function getBucketsForBucketsPage(fromCache, mnHttpParams) {
      return getBucketsByType(fromCache, mnHttpParams).then(function (buckets) {
        angular.forEach(buckets, getPieConfig);
        return buckets;
      });
    }

    function getBucketsByType(fromCache, mnHttpParams) {
      return mnBucketsStats[fromCache ? "get" : "getFresh"](mnHttpParams).then(function (resp) {
        var bucketsDetails = resp.data
        bucketsDetails.byType = {membase: [], memcached: []};
        bucketsDetails.byType.membase.isMembase = true;
        bucketsDetails.byType.memcached.isMemcached = true;
        _.each(bucketsDetails, function (bucket) {
          bucketsDetails.byType[bucket.bucketType].push(bucket);
          bucket.isMembase = bucket.bucketType === 'membase';
        });
        bucketsDetails.byType.names = _.pluck(bucketsDetails, 'name');
        bucketsDetails.byType.defaultName = _.contains(bucketsDetails.byType.names, 'default') ? 'default' : bucketsDetails.byType.names[0] || '';
        bucketsDetails.byType.membase.names = _.pluck(bucketsDetails.byType.membase, 'name');
        bucketsDetails.byType.membase.defaultName = _.contains(bucketsDetails.byType.membase.names, 'default') ? 'default' : bucketsDetails.byType.membase.names[0] || '';
        return bucketsDetails;
      });
    }
  }
})();
<commit_msg>app-classic: added new 'ephemeral' bucket type in getBucketsByType function<commit_after>(function () {
  angular.module('mnBucketsService', [
    'mnBucketsStats'
  ]).factory('mnBucketsService', mnBucketsServiceFactory);

  function mnBucketsServiceFactory($http, $q, mnBucketsStats) {
    var mnBucketsService = {
      getBucketsByType: getBucketsByType,
      getBucketsForBucketsPage: getBucketsForBucketsPage
    };

    return mnBucketsService;

    function getPieConfig(bucket) {
      var h = _.reduce(_.pluck(bucket.nodes, 'status'), function (counts, stat) {
        counts[stat] = (counts[stat] || 0) + 1;
        return counts;
      }, {});

      var pieConfig = {};
      var healthStats = [h.healthy || 0, h.warmup || 0, h.unhealthy || 0];
      pieConfig.status = _.clone(healthStats);

      var total = _.inject(healthStats, function (a,b) {return a+b}, 0);

      var minimalAngle = Math.PI/180*30;
      var nodeSize = total < 1E-6 ? 0 : Math.PI*2/total;

      var stolenSize = 0;
      var maxAngle = 0;
      var maxIndex = -1;

      for (var i = healthStats.length; i--;) {
        var newValue = healthStats[i] * nodeSize;
        if (newValue != 0 && newValue < minimalAngle) {
          stolenSize += minimalAngle - newValue;
          newValue = minimalAngle;
        }
        healthStats[i] = newValue;
        if (newValue >= maxAngle) {
          maxAngle = newValue;
          maxIndex = i;
        }
      }

      pieConfig.series = healthStats;
      bucket.pieConfig = pieConfig;
    }

    function getBucketsForBucketsPage(fromCache, mnHttpParams) {
      return getBucketsByType(fromCache, mnHttpParams).then(function (buckets) {
        angular.forEach(buckets, getPieConfig);
        return buckets;
      });
    }

    function getBucketsByType(fromCache, mnHttpParams) {
      return mnBucketsStats[fromCache ? "get" : "getFresh"](mnHttpParams).then(function (resp) {
        var bucketsDetails = resp.data
        bucketsDetails.byType = {membase: [], memcached: [], ephemeral: []};
        bucketsDetails.byType.membase.isMembase = true;
        bucketsDetails.byType.memcached.isMemcached = true;
        _.each(bucketsDetails, function (bucket) {
          bucketsDetails.byType[bucket.bucketType].push(bucket);
          bucket.isMembase = bucket.bucketType === 'membase';
        });
        bucketsDetails.byType.names = _.pluck(bucketsDetails, 'name');
        bucketsDetails.byType.defaultName = _.contains(bucketsDetails.byType.names, 'default') ? 'default' : bucketsDetails.byType.names[0] || '';
        bucketsDetails.byType.membase.names = _.pluck(bucketsDetails.byType.membase, 'name');
        bucketsDetails.byType.membase.defaultName = _.contains(bucketsDetails.byType.membase.names, 'default') ? 'default' : bucketsDetails.byType.membase.names[0] || '';
        return bucketsDetails;
      });
    }
  }
})();
<|endoftext|>


<commit_before>var linz = require('../'),
    async = require('async'),
    moment = require('moment');

let useLocalTime = false;
let dateFormat = false;

var modelExportHelpers = function modelExportHelpers (req, res) {

    var getRecordData = function getRecordData (fields, record) {

        var orderedRecord = {};

        // order field names in the selected order
        fields.forEach(function (fieldName) {
            orderedRecord[fieldName] = prettifyData(fieldName, record[fieldName]);
        });

        return linz.utils.json2CSV(orderedRecord);

    };

    /**
     * Format a date object using the list dsl settings.
     * @param {Date} val A date object.
     * @return {String} A date string.
     */
    const formatDate = (val) => {

        if (!(val instanceof Date)) {
            return val;
        }

        return moment(val)
            .utcOffset((useLocalTime && linz.api.session.getTimezone(req)) || 0)
            .format((typeof dateFormat === 'string') && dateFormat);

    };

    var prettifyData = function prettifyData (fieldName, val) {

        if (val === undefined || val === '' || val === null) {
            return val;
        }

        if (typeof val === 'number') {
            return val;
        }

        var Model = req.linz.model;

        if (Model.schema.tree[fieldName].ref) {
            return val.title;
        }

        if (Array.isArray(val)) {

            if (val.length === 0) {
                return '';
            }

            var strArr = [];

            val.forEach(function (obj) {

                if (typeof obj === 'object') {

                    var arr = [];

                    // tostring embedded object
                    Object.keys(obj).forEach(function (key) {
                        if (key === '_id' || key === 'id' || key === 'dateModified' || key === 'dateCreated' || obj[key] === '' || obj[key] === undefined) {
                            return;
                        }
                        return arr.push(key + ': ' + obj[key].toString());
                    });

                    return strArr.push(arr.join(', '));
                }

                return strArr.push(obj.toString());

            });

            return strArr.join(', ');

        }

        if (typeof val === 'boolean' || 'true,false,yes,no'.indexOf(val) >= 0 ) {
            return (linz.utils.asBoolean(val) ? 'Yes' : 'No');
        }

        if (val instanceof Date) {
            val = formatDate(val);
        }

        return val;

    };

    return {

        mongooseToCSV: function mongooseToCSV (fields, form) {

            var count = 0;

            return function (doc) {

                var str = '',
                    record = doc.toObject({virtuals: true });

                if (count !== 0) {
                    return getRecordData(fields, record);
                }

                var arr = [];

                // get field labels
                fields.forEach(function (fieldName) {
                    arr.push(form[fieldName].label);
                });

                str = arr.join() + '\n';

                count++;

                return str + getRecordData(fields, record);

            };

        },

        getFilters: function getFilters (cb) {

            if (!req.body.filters.length) {
                return cb(null, {});
            }

            var Model = req.linz.model,
                form = JSON.parse(req.body.filters);

            // check if there are any filters in the form post
            if (!form.selectedFilters) {
                return cb(null, {});
            }

            async.waterfall([

                function (callback) {

                    Model.getList(req, function (err, list) {

                        if (err) {
                            return cb(err);
                        }

                        return callback(null, list);

                    });
                },

                function (list, callback) {

                    var filters = {};

                    async.each(form.selectedFilters.split(','), function (fieldName, filtersDone) {

                        // call the filter renderer and update the content with the result
                        list.filters[fieldName].filter.filter(fieldName, form, function (err, result) {

                            if (err) {
                                return filtersDone(err);
                            }

                            filters = Model.addSearchFilter(filters, result);

                            return filtersDone(null);

                        });

                    }, function (err) {

                        if (err) {
                            return cb(err);
                        }

                        // consolidate filters into query
                        if (Object.keys(filters).length) {
                            filters = Model.setFiltersAsQuery(filters);
                        }

                        return cb(err, filters);

                    });

                }

            ]);

        },

        addIdFilters: function addIdFilters (filters, cb) {

            if (!req.body.selectedIds.length) {
                return cb(null, filters);
            }

            filters = filters || { '$and': [] };
            filters['$and'] = filters['$and'] || [];

            var ids = [],
                db  = linz.mongoose.connection.db;

            // compile ids into ObjectId type
            req.body.selectedIds.split(',').forEach(function (id) {
                ids.push(new db.bsonLib.ObjectID(id));
            });

            // let's add selected Ids to the filters
            filters['$and'].push({
                _id: { $in: ids}
            });

            return cb(null, filters);

        },

        getForm: function getForm(filters, cb) {

            req.linz.model.getForm(req, function (err, form) {
                return cb(err, filters, form);
            });

        },

        getList: function getList (filters, form, cb) {

            req.linz.model.getList(req, function (err, list) {
                return cb(err, filters, form, list);
            });

        }

    };

};

// this will retrieve the export object, using Linz's default export handler amongst custom export handlers
// this is based on the knowledge that only Linz's default export handler can have an `action` of `export`
// `exports` should be model.list.export
var getExport = function (exports) {

    var exp = undefined;

    // retrieve the export object
    exports.forEach(function (_export) {

        // Linz's default export function is called export
        if (_export.action && _export.action === 'export') {
            exp = _export;
        }

    });

    // if the export object could not be found, throw an error
    if (!exp) {
        throw new Error('The export was using Linz default export method, yet the model\'s list.export object could not be found.');
    }

    return exp;

}

module.exports = {

    get: function (req, res, next) {

        req.linz.model.getList(req, function (err, list) {

            if (err) {
                return next(err);
            }

            // attach our list object to the model
            req.linz.model.list = list;

            // retrieve the export object
            req.linz.export = getExport(list.export);
            req.linz.export.fields = {};

            // retrieve the form to provide a list of fields to choose from
            req.linz.model.getForm(req, function (formErr, form){

                if (formErr) {
                    return next(formErr);
                }

                var excludedFieldNames = req.linz.export.exclusions.concat(',__v').split(','),
                    fieldLabels = {};

                // get a list of field names
                req.linz.model.schema.eachPath(function (pathname, schemaType) {

                    if (excludedFieldNames.indexOf(pathname) >= 0) {
                        // exit if current field name is one of the exclusion fields
                        return;
                    }

                    if (!form[pathname]) {
                        throw new Error(`Could not find ${pathname} field in the labels array.`);
                    }

                    // get a list of fields by the label ready for sorting
                    fieldLabels[form[pathname].label] = pathname;

                });

                // sort fields by label
                var sortedFieldsByLabel = Object.keys(fieldLabels).sort();

                // iterate through sorted label and re-constructs in the order of labels
                sortedFieldsByLabel.forEach(function (label) {
                    req.linz.export.fields[fieldLabels[label]] = label;
                });

                return next(null);

            });

        });

    },

    post: function (req, res, next) {

        var Model = req.linz.model;

        // since a custom export function is not defined for model, use local export function
        var asyncFn = [],
            helpers = modelExportHelpers(req, res);

        asyncFn.push(helpers.getFilters);
        asyncFn.push(helpers.addIdFilters);
        asyncFn.push(helpers.getForm);
        asyncFn.push(helpers.getList);

        // get the actual export object
        asyncFn.push(function (filters, form, list, callback) {

            // retrieve the export
            var _export = getExport(list.export);
            _export.fields = {};

            return callback(null, filters, form, list, _export);

        });

        async.waterfall(asyncFn, function (err, filters, form, list, exportObj) {

            if (err) {
                return next(err);
            }

            useLocalTime = exportObj && exportObj.useLocalTime;
            dateFormat = exportObj && exportObj.dateFormat;

            var fields = req.body.selectedFields.split(','),
                refFieldNames = [],
                filterFieldNames = [];

            fields.forEach(function (fieldName, index, arr) {

                // remove any property that doesn't exist in the model
                if (!Model.schema.tree[fieldName]) {
                    return arr.splice(index, 1);
                }

                // check if there any ref fields selected to be exported
                if(!Model.schema.tree[fieldName].ref) {
                    return;
                }

                return refFieldNames.push(fieldName);

            });

            // check if _id is excluded
            if (exportObj.exclusions.indexOf('_id') >= 0) {
                filterFieldNames.push('-_id');
            }

            filterFieldNames = filterFieldNames.concat(fields);

            // serve .csv file
            res.setHeader('Content-disposition', 'attachment; filename=' + Model.linz.formtools.model.plural + '-' + moment(Date.now()).format('l').replace(/\//g, '.', 'g') + '.csv');
            res.writeHead(200, { 'Content-Type': 'text/csv' });

            // pipe data to response stream
            req.linz.model.getQuery(req, filters, function getQuery (err, query) {

                if (err) {
                    return next(err);
                }

                query.select(filterFieldNames.join(' '))
                    .populate(refFieldNames.join(' '), '-_id -__v -dateCreated -dateModified -createdBy -modifiedBy')
                    .stream({ transform: helpers.mongooseToCSV(fields, form) })
                    .pipe(res);

            });

        });

    }
};
<commit_msg>Fix issue where linz would try to toString null values<commit_after>var linz = require('../'),
    async = require('async'),
    moment = require('moment');

let useLocalTime = false;
let dateFormat = false;

var modelExportHelpers = function modelExportHelpers (req, res) {

    var getRecordData = function getRecordData (fields, record) {

        var orderedRecord = {};

        // order field names in the selected order
        fields.forEach(function (fieldName) {
            orderedRecord[fieldName] = prettifyData(fieldName, record[fieldName]);
        });

        return linz.utils.json2CSV(orderedRecord);

    };

    /**
     * Format a date object using the list dsl settings.
     * @param {Date} val A date object.
     * @return {String} A date string.
     */
    const formatDate = (val) => {

        if (!(val instanceof Date)) {
            return val;
        }

        return moment(val)
            .utcOffset((useLocalTime && linz.api.session.getTimezone(req)) || 0)
            .format((typeof dateFormat === 'string') && dateFormat);

    };

    var prettifyData = function prettifyData (fieldName, val) {

        if (val === undefined || val === '' || val === null) {
            return val;
        }

        if (typeof val === 'number') {
            return val;
        }

        var Model = req.linz.model;

        if (Model.schema.tree[fieldName].ref) {
            return val.title;
        }

        if (Array.isArray(val)) {

            if (val.length === 0) {
                return '';
            }

            var strArr = [];

            val.forEach(function (obj) {

                if (typeof obj === 'object') {

                    var arr = [];

                    // tostring embedded object
                    Object.keys(obj).forEach(function (key) {
                        if (key === '_id' || key === 'id' || key === 'dateModified' || key === 'dateCreated' || obj[key] === '' || obj[key] === undefined) {
                            return;
                        }
                        return arr.push(key + ': ' + (obj[key] || '').toString());
                    });

                    return strArr.push(arr.join(', '));
                }

                return strArr.push(obj.toString());

            });

            return strArr.join(', ');

        }

        if (typeof val === 'boolean' || 'true,false,yes,no'.indexOf(val) >= 0 ) {
            return (linz.utils.asBoolean(val) ? 'Yes' : 'No');
        }

        if (val instanceof Date) {
            val = formatDate(val);
        }

        return val;

    };

    return {

        mongooseToCSV: function mongooseToCSV (fields, form) {

            var count = 0;

            return function (doc) {

                var str = '',
                    record = doc.toObject({virtuals: true });

                if (count !== 0) {
                    return getRecordData(fields, record);
                }

                var arr = [];

                // get field labels
                fields.forEach(function (fieldName) {
                    arr.push(form[fieldName].label);
                });

                str = arr.join() + '\n';

                count++;

                return str + getRecordData(fields, record);

            };

        },

        getFilters: function getFilters (cb) {

            if (!req.body.filters.length) {
                return cb(null, {});
            }

            var Model = req.linz.model,
                form = JSON.parse(req.body.filters);

            // check if there are any filters in the form post
            if (!form.selectedFilters) {
                return cb(null, {});
            }

            async.waterfall([

                function (callback) {

                    Model.getList(req, function (err, list) {

                        if (err) {
                            return cb(err);
                        }

                        return callback(null, list);

                    });
                },

                function (list, callback) {

                    var filters = {};

                    async.each(form.selectedFilters.split(','), function (fieldName, filtersDone) {

                        // call the filter renderer and update the content with the result
                        list.filters[fieldName].filter.filter(fieldName, form, function (err, result) {

                            if (err) {
                                return filtersDone(err);
                            }

                            filters = Model.addSearchFilter(filters, result);

                            return filtersDone(null);

                        });

                    }, function (err) {

                        if (err) {
                            return cb(err);
                        }

                        // consolidate filters into query
                        if (Object.keys(filters).length) {
                            filters = Model.setFiltersAsQuery(filters);
                        }

                        return cb(err, filters);

                    });

                }

            ]);

        },

        addIdFilters: function addIdFilters (filters, cb) {

            if (!req.body.selectedIds.length) {
                return cb(null, filters);
            }

            filters = filters || { '$and': [] };
            filters['$and'] = filters['$and'] || [];

            var ids = [],
                db  = linz.mongoose.connection.db;

            // compile ids into ObjectId type
            req.body.selectedIds.split(',').forEach(function (id) {
                ids.push(new db.bsonLib.ObjectID(id));
            });

            // let's add selected Ids to the filters
            filters['$and'].push({
                _id: { $in: ids}
            });

            return cb(null, filters);

        },

        getForm: function getForm(filters, cb) {

            req.linz.model.getForm(req, function (err, form) {
                return cb(err, filters, form);
            });

        },

        getList: function getList (filters, form, cb) {

            req.linz.model.getList(req, function (err, list) {
                return cb(err, filters, form, list);
            });

        }

    };

};

// this will retrieve the export object, using Linz's default export handler amongst custom export handlers
// this is based on the knowledge that only Linz's default export handler can have an `action` of `export`
// `exports` should be model.list.export
var getExport = function (exports) {

    var exp = undefined;

    // retrieve the export object
    exports.forEach(function (_export) {

        // Linz's default export function is called export
        if (_export.action && _export.action === 'export') {
            exp = _export;
        }

    });

    // if the export object could not be found, throw an error
    if (!exp) {
        throw new Error('The export was using Linz default export method, yet the model\'s list.export object could not be found.');
    }

    return exp;

}

module.exports = {

    get: function (req, res, next) {

        req.linz.model.getList(req, function (err, list) {

            if (err) {
                return next(err);
            }

            // attach our list object to the model
            req.linz.model.list = list;

            // retrieve the export object
            req.linz.export = getExport(list.export);
            req.linz.export.fields = {};

            // retrieve the form to provide a list of fields to choose from
            req.linz.model.getForm(req, function (formErr, form){

                if (formErr) {
                    return next(formErr);
                }

                var excludedFieldNames = req.linz.export.exclusions.concat(',__v').split(','),
                    fieldLabels = {};

                // get a list of field names
                req.linz.model.schema.eachPath(function (pathname, schemaType) {

                    if (excludedFieldNames.indexOf(pathname) >= 0) {
                        // exit if current field name is one of the exclusion fields
                        return;
                    }

                    if (!form[pathname]) {
                        throw new Error(`Could not find ${pathname} field in the labels array.`);
                    }

                    // get a list of fields by the label ready for sorting
                    fieldLabels[form[pathname].label] = pathname;

                });

                // sort fields by label
                var sortedFieldsByLabel = Object.keys(fieldLabels).sort();

                // iterate through sorted label and re-constructs in the order of labels
                sortedFieldsByLabel.forEach(function (label) {
                    req.linz.export.fields[fieldLabels[label]] = label;
                });

                return next(null);

            });

        });

    },

    post: function (req, res, next) {

        var Model = req.linz.model;

        // since a custom export function is not defined for model, use local export function
        var asyncFn = [],
            helpers = modelExportHelpers(req, res);

        asyncFn.push(helpers.getFilters);
        asyncFn.push(helpers.addIdFilters);
        asyncFn.push(helpers.getForm);
        asyncFn.push(helpers.getList);

        // get the actual export object
        asyncFn.push(function (filters, form, list, callback) {

            // retrieve the export
            var _export = getExport(list.export);
            _export.fields = {};

            return callback(null, filters, form, list, _export);

        });

        async.waterfall(asyncFn, function (err, filters, form, list, exportObj) {

            if (err) {
                return next(err);
            }

            useLocalTime = exportObj && exportObj.useLocalTime;
            dateFormat = exportObj && exportObj.dateFormat;

            var fields = req.body.selectedFields.split(','),
                refFieldNames = [],
                filterFieldNames = [];

            fields.forEach(function (fieldName, index, arr) {

                // remove any property that doesn't exist in the model
                if (!Model.schema.tree[fieldName]) {
                    return arr.splice(index, 1);
                }

                // check if there any ref fields selected to be exported
                if(!Model.schema.tree[fieldName].ref) {
                    return;
                }

                return refFieldNames.push(fieldName);

            });

            // check if _id is excluded
            if (exportObj.exclusions.indexOf('_id') >= 0) {
                filterFieldNames.push('-_id');
            }

            filterFieldNames = filterFieldNames.concat(fields);

            // serve .csv file
            res.setHeader('Content-disposition', 'attachment; filename=' + Model.linz.formtools.model.plural + '-' + moment(Date.now()).format('l').replace(/\//g, '.', 'g') + '.csv');
            res.writeHead(200, { 'Content-Type': 'text/csv' });

            // pipe data to response stream
            req.linz.model.getQuery(req, filters, function getQuery (err, query) {

                if (err) {
                    return next(err);
                }

                query.select(filterFieldNames.join(' '))
                    .populate(refFieldNames.join(' '), '-_id -__v -dateCreated -dateModified -createdBy -modifiedBy')
                    .stream({ transform: helpers.mongooseToCSV(fields, form) })
                    .pipe(res);

            });

        });

    }
};
<|endoftext|>