<commit_before>var TOPIC_DATE_RANGE = "subscriber";
var TOPIC_USERNAME = "subscriberUser";
var TOPIC_USERPREF_DELETION = "subscriberUserPrefDeletion";
var TOPIC_SLIDER = "publisherSliderDateRange";
var TOPIC_REGION = "publisherRegion";
var listnedTimeFromValue;
var listnedTimeToValue;
var listnedAdditionalUserPrefs = "";
var globalUniqueArray = [];
var rangeStart;
var rangeEnd;
var rangeHistoryArray = [];
var idpTypeFilter = "";

var page = gadgetUtil.getCurrentPageName();
var qs = gadgetUtil.getQueryString();
var prefs = new gadgets.Prefs();
var type;
var chart = gadgetUtil.getChart(prefs.getString(PARAM_GADGET_ROLE));
var map;

if (chart) {
    type = gadgetUtil.getRequestType(page, chart);
}

$(function() {

    if (!chart) {
        $("#canvas").html(gadgetUtil.getErrorText("Gadget initialization failed. Gadget role must be provided."));
        return;
    }
    if (page != TYPE_LANDING && page != TYPE_RESIDENT_IDP && qs[PARAM_ID] == null) {
        $("#canvas").html(gadgetUtil.getDefaultText());
        return;
    }

    if(page == TYPE_RESIDENT_IDP) {
        idpTypeFilter = " AND identityProviderType:\"LOCAL\"";
    } else {
        idpTypeFilter = " AND identityProviderType:\"FEDERATED\"";
    }

    var historyParmExist = gadgetUtil.getURLParam("persistTimeFrom");

    if(historyParmExist == null){
        listnedTimeFromValue = gadgetUtil.timeFrom();
        listnedTimeToValue = gadgetUtil.timeTo();
    }else{
        var historyParms = gadgetUtil.getURLParams();

        for (var key in historyParms) {
            if (historyParms.hasOwnProperty(key)) {

                if(key == "persistTimeFrom"){
                    listnedTimeFromValue = historyParms[key];
                }else if(key == "persistTimeTo"){
                    listnedTimeToValue = historyParms[key];
                }else if(Object.keys(historyParms).length > 2){
                    var historyParamVal = historyParms[key].toString();
                    addUserPrefsToGlobalArray("Topic",key,historyParamVal.split("_")[0]);
                }
            }
        }
    }

    onDataChanged();

    $("#back").off().click(function (event) {
        if(rangeHistoryArray.length > 0) {
            var timeRange = rangeHistoryArray[rangeHistoryArray.length - 1];
            rangeHistoryArray.splice(rangeHistoryArray.length - 1, 1);
            listnedTimeFromValue = timeRange[0];
            listnedTimeToValue = timeRange[1];
            var message = {
                timeFrom: listnedTimeFromValue,
                timeTo: listnedTimeToValue,
                timeUnit: "Custom"
            };
            gadgets.Hub.publish(TOPIC_SLIDER, message);
            onDataChanged();

            if(rangeHistoryArray.length == 0) {
                $(this).hide();
            }
        }
    });

    checkMapType();
});

function checkMapType() {
    if (document.getElementById('chkMap').checked) {
        $("#mapFailDiv").hide();
        $("#mapSuccessDiv").show()
        map.colorCode = "SUCCESS";
    } else {
        $("#mapSuccessDiv").hide();
        $("#mapFailDiv").show();
        map.colorCode = "FAILURE";
    }
}

gadgets.HubSettings.onConnect = function() {

    gadgets.Hub.subscribe(TOPIC_DATE_RANGE, function(topic, data, subscriberData) {

        listnedTimeFromValue = data.timeFrom;
        listnedTimeToValue = data.timeTo;
        onDataChanged();
        $("#back").hide();
    });

    gadgets.Hub.subscribe(TOPIC_USERNAME, function(topic, data, subscriberData) {

        addUserPrefsToGlobalArray(topic,data.mode,data.userPrefValue);
        onDataChanged();
    });

    gadgets.Hub.subscribe(TOPIC_USERPREF_DELETION, function(topic, data, subscriberData) {

        var index;
        for(i=0;i<globalUniqueArray.length;i++){
            if(globalUniqueArray[i][2] == data.category){
                index = i;
                break;
            }
        }
        globalUniqueArray.splice(index, 1);
        listnedAdditionalUserPrefs = "";

        for(i=0;i<globalUniqueArray.length;i++){
            if(globalUniqueArray[i][2] == "USERNAME"){
                listnedAdditionalUserPrefs+= " AND userName:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "SERVICEPROVIDER"){
                listnedAdditionalUserPrefs+= " AND serviceProvider:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "ROLE"){
                listnedAdditionalUserPrefs+= " AND rolesCommaSeperated:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "IDENTITYPROVIDER"){
                listnedAdditionalUserPrefs+= " AND identityProvider:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "REGION"){
                listnedAdditionalUserPrefs+= " AND region:\""+globalUniqueArray[i][1]+"\"";
            }
        }

        onDataChanged();
    });
};

function addUserPrefsToGlobalArray(topic,mode,userPref){

    var valExist = false;

    if(globalUniqueArray.length != 0){
        for(i=0;i<globalUniqueArray.length;i++){
            if(globalUniqueArray[i][2] == mode){
                valExist = true;
                globalUniqueArray[i][0] = topic;
                globalUniqueArray[i][1] = userPref;
                break;
            }
        }

        if(!valExist){
            var arry = [topic,userPref,mode];
            globalUniqueArray.push(arry);
        }
    }else{
        var arry = [topic,userPref,mode];
        globalUniqueArray.push(arry);
    }

    listnedAdditionalUserPrefs = "";

    for(i=0;i<globalUniqueArray.length;i++){
        if(globalUniqueArray[i][2] == "USERNAME"){
            listnedAdditionalUserPrefs+= " AND userName:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "SERVICEPROVIDER"){
            listnedAdditionalUserPrefs+= " AND serviceProvider:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "ROLE"){
            listnedAdditionalUserPrefs+= " AND rolesCommaSeperated:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "IDENTITYPROVIDER"){
            listnedAdditionalUserPrefs+= " AND identityProvider:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "REGION"){
            listnedAdditionalUserPrefs+= " AND region:\""+globalUniqueArray[i][1]+"\"";
        }
    }
}

function onDataChanged() {

    gadgetUtil.updateURLParam("persistTimeFrom", listnedTimeFromValue.toString());
    gadgetUtil.updateURLParam("persistTimeTo", listnedTimeToValue.toString());

    gadgetUtil.fetchData(CONTEXT, {
        type: type,
        timeFrom: listnedTimeFromValue,
        timeTo: listnedTimeToValue,
        listnedAdditionalUserPrefs: listnedAdditionalUserPrefs,
        idpType:idpTypeFilter
    }, onData, onError);

    gadgetUtil.fetchData(CONTEXT, {
        type: 25,
        timeFrom: listnedTimeFromValue,
        timeTo: listnedTimeToValue,
        listnedAdditionalUserPrefs: listnedAdditionalUserPrefs,
        idpType:idpTypeFilter,
        start:0,
        count:10
    }, loadMap, onError);

};

function onData(response) {
    try {
        var data = response.message;
        /*if (data.length == 0) {
         $('#canvas').html(gadgetUtil.getEmptyRecordsText());
         return;
         }*/
        //sort the timestamps
        data.sort(function(a, b) {
            return a.timestamp - b.timestamp;
        });

        //perform necessary transformation on input data

        var allData = chart.processData(data);
        var message = {
            success: allData[1],
            failed: allData[2]
        };

        //gadgets.Hub.publish(TOPIC_STAT_PUBLISHER, message);
        loadStats(message);

        var callbackmethod = function(start, end) {
            rangeStart = start;
            rangeEnd = end;
        };

        chart.schema[0].data = allData[0];
        //finally draw the chart on the given canvas
        chart.chartConfig.width = $("#canvas").width();
        chart.chartConfig.height = $("#canvas").height();

        var vg = new vizg(chart.schema, chart.chartConfig);
        $("#canvas").empty();
        vg.draw("#canvas",[{type:"range", callback:callbackmethod}]);
    } catch (e) {
        $('#canvas').html(gadgetUtil.getErrorText(e));
    }
}

function onError(msg) {
    $("#canvas").html(gadgetUtil.getErrorText(msg));
};

function loadStats(data){

    var successCount = data.success;
    var failed = data.failed;
    var total = successCount + failed;

    $('#gadget-messge').hide();
    $('#stats').show();
    var success = total - failed;
    var failedPct = (failed / total) * 100;
    var successPct = 100 - failedPct;

    $("#totalCount").html(total);
    $("#failedCount").html(failed);
    $("#failedPercent").html(parseFloat(failedPct).toFixed(2));
    $("#successCount").html(success);
    $("#successPercent").html(parseFloat(successPct).toFixed(2));

    var successColor = function(){
        return parseFloat(successPct) > 0 ? '#5CB85C' : '#353B48';
    };

    var failColor = function(){
        return parseFloat(failedPct) > 0 ? '#D9534F' : '#353B48';
    };

//draw donuts
    var dataT = [{
        "metadata": {
            "names": ["Rate", "Status"],
            "types": ["linear", "ordinal"]
        },
        "data": [
            [parseFloat(success), "Success"],
            [parseFloat(failed), "Failure"]
        ]
    }];

    var configT = {
        charts: [{ type: "arc", x: "Rate", color: "Status", mode:"donut" }],
        innerRadius: 0.3,
        padding: { top:0, right:70, bottom:0, left:10 },
        legend: true,
        percentage: true,
        colorScale: [successColor(), failColor()],
        width: 260,
        height: 160
    }

    var chartT = new vizg(dataT, configT);
    chartT.draw("#donutDiv");
}

function loadMap(data) {

    if(data.message.length == 0) {
        $(".text-center").hide();
    } else {
        $(".text-center").show();
    }

    var successData = [];
    var failedData = [];

    var mapCallBack = function(event, item) {
        if (item != null) {
            var region = item.datum.zipped.unitName;
            map.mode = "REGION";

            var message = {
                userPrefValue: region,
                mode: map.mode,
                colorCode:map.colorCode
            };

            gadgetUtil.updateURLParam(map.mode, region + "_" +map.colorCode);

            gadgets.Hub.publish(TOPIC_REGION, message);
        }
    }

    for (var i = 0 ; i < data.message.length; i++) {
        successData.push([data.message[i].region, data.message[i].authSuccessCount]);
        failedData.push([data.message[i].region, data.message[i].authFailureCount]);
    }

    var worldSuccessData =  [
        {
            "metadata" : {
                "names" : ["Country","Logins"],
                "types" : ["ordinal", "linear"]
            },
            "data": successData
        }
    ];

    var configSuccessWorld = {
        type: "map",
        x : "Country",
        legend : false,
        padding: { top:0, right:50, bottom:00, left:10 },
        renderer : "canvas",
        charts : [{type: "map",  y : "Logins", mapType : "world"}],
        width: 380,
        height: 250,
        colorScale:["#dcefdc","#5CB85C"]
    };

    configSuccessWorld.helperUrl = "../../portal/templates/geojson/countryInfo.json";
    configSuccessWorld.geoCodesUrl = "../../portal/templates/geojson/world.json";
    var worldSuccessChart = new vizg(worldSuccessData, configSuccessWorld);
    worldSuccessChart.draw("#mapSuccessDiv",[{type:"click", callback:mapCallBack}]);

    var worldFailedData =  [
        {
            "metadata" : {
                "names" : ["Country","Logins"],
                "types" : ["ordinal", "linear"]
            },
            "data": failedData
        }
    ];

    var configFailedWorld = {
        type: "map",
        x : "Country",
        legend : false,
        padding: { top:0, right:50, bottom:00, left:10 },
        renderer : "canvas",
        charts : [{type: "map",  y : "Logins", mapType : "world"}],
        width: 380,
        height: 250,
        colorScale:["#f6d6d5","#D9534F"]
    };

    configFailedWorld.helperUrl = "../../portal/templates/geojson/countryInfo.json";
    configFailedWorld.geoCodesUrl = "../../portal/templates/geojson/world.json";
    var worldFailedChart = new vizg(worldFailedData, configFailedWorld);
    worldFailedChart.draw("#mapFailDiv",[{type:"click", callback:mapCallBack}]);
}

document.body.onmouseup = function() {

    if((rangeStart) && (rangeEnd) && (rangeStart.toString() !== rangeEnd.toString())){

        if(event.target.nodeName == 'path' || event.target.nodeName == 'rect'){
            var timeFromValue = JSON.parse(JSON.stringify(listnedTimeFromValue));
            var timeToValue = JSON.parse(JSON.stringify(listnedTimeToValue));
            var timeRange = [timeFromValue, timeToValue];
            rangeHistoryArray.push(timeRange);
            $("#back").show();

            listnedTimeFromValue = new Date(rangeStart).getTime();
            listnedTimeToValue = new Date(rangeEnd).getTime();
            onDataChanged();
            var message = {
                timeFrom: listnedTimeFromValue,
                timeTo: listnedTimeToValue,
                timeUnit: "Custom"
            };
            gadgets.Hub.publish(TOPIC_SLIDER, message);
        }
    }
}
<commit_msg>UI changes in map switch button<commit_after>var TOPIC_DATE_RANGE = "subscriber";
var TOPIC_USERNAME = "subscriberUser";
var TOPIC_USERPREF_DELETION = "subscriberUserPrefDeletion";
var TOPIC_SLIDER = "publisherSliderDateRange";
var TOPIC_REGION = "publisherRegion";
var listnedTimeFromValue;
var listnedTimeToValue;
var listnedAdditionalUserPrefs = "";
var globalUniqueArray = [];
var rangeStart;
var rangeEnd;
var rangeHistoryArray = [];
var idpTypeFilter = "";

var page = gadgetUtil.getCurrentPageName();
var qs = gadgetUtil.getQueryString();
var prefs = new gadgets.Prefs();
var type;
var chart = gadgetUtil.getChart(prefs.getString(PARAM_GADGET_ROLE));
var map;

if (chart) {
    type = gadgetUtil.getRequestType(page, chart);
}

$(function() {

    if (!chart) {
        $("#canvas").html(gadgetUtil.getErrorText("Gadget initialization failed. Gadget role must be provided."));
        return;
    }
    if (page != TYPE_LANDING && page != TYPE_RESIDENT_IDP && qs[PARAM_ID] == null) {
        $("#canvas").html(gadgetUtil.getDefaultText());
        return;
    }

    if(page == TYPE_RESIDENT_IDP) {
        idpTypeFilter = " AND identityProviderType:\"LOCAL\"";
    } else {
        idpTypeFilter = " AND identityProviderType:\"FEDERATED\"";
    }

    var historyParmExist = gadgetUtil.getURLParam("persistTimeFrom");

    if(historyParmExist == null){
        listnedTimeFromValue = gadgetUtil.timeFrom();
        listnedTimeToValue = gadgetUtil.timeTo();
    }else{
        var historyParms = gadgetUtil.getURLParams();

        for (var key in historyParms) {
            if (historyParms.hasOwnProperty(key)) {

                if(key == "persistTimeFrom"){
                    listnedTimeFromValue = historyParms[key];
                }else if(key == "persistTimeTo"){
                    listnedTimeToValue = historyParms[key];
                }else if(Object.keys(historyParms).length > 2){
                    var historyParamVal = historyParms[key].toString();
                    addUserPrefsToGlobalArray("Topic",key,historyParamVal.split("_")[0]);
                }
            }
        }
    }

    onDataChanged();

    $("#back").off().click(function (event) {
        if(rangeHistoryArray.length > 0) {
            var timeRange = rangeHistoryArray[rangeHistoryArray.length - 1];
            rangeHistoryArray.splice(rangeHistoryArray.length - 1, 1);
            listnedTimeFromValue = timeRange[0];
            listnedTimeToValue = timeRange[1];
            var message = {
                timeFrom: listnedTimeFromValue,
                timeTo: listnedTimeToValue,
                timeUnit: "Custom"
            };
            gadgets.Hub.publish(TOPIC_SLIDER, message);
            onDataChanged();

            if(rangeHistoryArray.length == 0) {
                $(this).hide();
            }
        }
    });

    checkMapType();
});

function checkMapType() {
    if (document.getElementById('chkMap').checked) {
        $("#mapFailDiv").hide();
        $("#mapSuccessDiv").show()
        map.colorCode = "SUCCESS";
    } else {
        $("#mapSuccessDiv").hide();
        $("#mapFailDiv").show();
        map.colorCode = "FAILURE";
    }
}

gadgets.HubSettings.onConnect = function() {

    gadgets.Hub.subscribe(TOPIC_DATE_RANGE, function(topic, data, subscriberData) {

        listnedTimeFromValue = data.timeFrom;
        listnedTimeToValue = data.timeTo;
        onDataChanged();
        $("#back").hide();
    });

    gadgets.Hub.subscribe(TOPIC_USERNAME, function(topic, data, subscriberData) {

        addUserPrefsToGlobalArray(topic,data.mode,data.userPrefValue);
        onDataChanged();
    });

    gadgets.Hub.subscribe(TOPIC_USERPREF_DELETION, function(topic, data, subscriberData) {

        var index;
        for(i=0;i<globalUniqueArray.length;i++){
            if(globalUniqueArray[i][2] == data.category){
                index = i;
                break;
            }
        }
        globalUniqueArray.splice(index, 1);
        listnedAdditionalUserPrefs = "";

        for(i=0;i<globalUniqueArray.length;i++){
            if(globalUniqueArray[i][2] == "USERNAME"){
                listnedAdditionalUserPrefs+= " AND userName:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "SERVICEPROVIDER"){
                listnedAdditionalUserPrefs+= " AND serviceProvider:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "ROLE"){
                listnedAdditionalUserPrefs+= " AND rolesCommaSeperated:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "IDENTITYPROVIDER"){
                listnedAdditionalUserPrefs+= " AND identityProvider:\""+globalUniqueArray[i][1]+"\"";
            }else if(globalUniqueArray[i][2] == "REGION"){
                listnedAdditionalUserPrefs+= " AND region:\""+globalUniqueArray[i][1]+"\"";
            }
        }

        onDataChanged();
    });
};

function addUserPrefsToGlobalArray(topic,mode,userPref){

    var valExist = false;

    if(globalUniqueArray.length != 0){
        for(i=0;i<globalUniqueArray.length;i++){
            if(globalUniqueArray[i][2] == mode){
                valExist = true;
                globalUniqueArray[i][0] = topic;
                globalUniqueArray[i][1] = userPref;
                break;
            }
        }

        if(!valExist){
            var arry = [topic,userPref,mode];
            globalUniqueArray.push(arry);
        }
    }else{
        var arry = [topic,userPref,mode];
        globalUniqueArray.push(arry);
    }

    listnedAdditionalUserPrefs = "";

    for(i=0;i<globalUniqueArray.length;i++){
        if(globalUniqueArray[i][2] == "USERNAME"){
            listnedAdditionalUserPrefs+= " AND userName:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "SERVICEPROVIDER"){
            listnedAdditionalUserPrefs+= " AND serviceProvider:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "ROLE"){
            listnedAdditionalUserPrefs+= " AND rolesCommaSeperated:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "IDENTITYPROVIDER"){
            listnedAdditionalUserPrefs+= " AND identityProvider:\""+globalUniqueArray[i][1]+"\"";
        }else if(globalUniqueArray[i][2] == "REGION"){
            listnedAdditionalUserPrefs+= " AND region:\""+globalUniqueArray[i][1]+"\"";
        }
    }
}

function onDataChanged() {

    gadgetUtil.updateURLParam("persistTimeFrom", listnedTimeFromValue.toString());
    gadgetUtil.updateURLParam("persistTimeTo", listnedTimeToValue.toString());

    gadgetUtil.fetchData(CONTEXT, {
        type: type,
        timeFrom: listnedTimeFromValue,
        timeTo: listnedTimeToValue,
        listnedAdditionalUserPrefs: listnedAdditionalUserPrefs,
        idpType:idpTypeFilter
    }, onData, onError);

    gadgetUtil.fetchData(CONTEXT, {
        type: 25,
        timeFrom: listnedTimeFromValue,
        timeTo: listnedTimeToValue,
        listnedAdditionalUserPrefs: listnedAdditionalUserPrefs,
        idpType:idpTypeFilter,
        start:0,
        count:10
    }, loadMap, onError);

};

function onData(response) {
    try {
        var data = response.message;
        /*if (data.length == 0) {
         $('#canvas').html(gadgetUtil.getEmptyRecordsText());
         return;
         }*/
        //sort the timestamps
        data.sort(function(a, b) {
            return a.timestamp - b.timestamp;
        });

        //perform necessary transformation on input data

        var allData = chart.processData(data);
        var message = {
            success: allData[1],
            failed: allData[2]
        };

        //gadgets.Hub.publish(TOPIC_STAT_PUBLISHER, message);
        loadStats(message);

        var callbackmethod = function(start, end) {
            rangeStart = start;
            rangeEnd = end;
        };

        chart.schema[0].data = allData[0];
        //finally draw the chart on the given canvas
        chart.chartConfig.width = $("#canvas").width();
        chart.chartConfig.height = $("#canvas").height();

        var vg = new vizg(chart.schema, chart.chartConfig);
        $("#canvas").empty();
        vg.draw("#canvas",[{type:"range", callback:callbackmethod}]);
    } catch (e) {
        $('#canvas').html(gadgetUtil.getErrorText(e));
    }
}

function onError(msg) {
    $("#canvas").html(gadgetUtil.getErrorText(msg));
};

function loadStats(data){

    var successCount = data.success;
    var failed = data.failed;
    var total = successCount + failed;

    $('#gadget-messge').hide();
    $('#stats').show();
    var success = total - failed;
    var failedPct = (failed / total) * 100;
    var successPct = 100 - failedPct;

    $("#totalCount").html(total);
    $("#failedCount").html(failed);
    $("#failedPercent").html(parseFloat(failedPct).toFixed(2));
    $("#successCount").html(success);
    $("#successPercent").html(parseFloat(successPct).toFixed(2));

    var successColor = function(){
        return parseFloat(successPct) > 0 ? '#5CB85C' : '#353B48';
    };

    var failColor = function(){
        return parseFloat(failedPct) > 0 ? '#D9534F' : '#353B48';
    };

//draw donuts
    var dataT = [{
        "metadata": {
            "names": ["Rate", "Status"],
            "types": ["linear", "ordinal"]
        },
        "data": [
            [parseFloat(success), "Success"],
            [parseFloat(failed), "Failure"]
        ]
    }];

    var configT = {
        charts: [{ type: "arc", x: "Rate", color: "Status", mode:"donut" }],
        innerRadius: 0.3,
        padding: { top:0, right:70, bottom:0, left:10 },
        legend: true,
        percentage: true,
        colorScale: [successColor(), failColor()],
        width: 260,
        height: 160
    }

    var chartT = new vizg(dataT, configT);
    chartT.draw("#donutDiv");
}

function loadMap(data) {

    if(data.message.length == 0) {
        $("#chkMap").attr("disabled", true);
    } else {
        $("#chkMap").attr("disabled", false);
    }

    var successData = [];
    var failedData = [];

    var mapCallBack = function(event, item) {
        if (item != null) {
            var region = item.datum.zipped.unitName;
            map.mode = "REGION";

            var message = {
                userPrefValue: region,
                mode: map.mode,
                colorCode:map.colorCode
            };

            gadgetUtil.updateURLParam(map.mode, region + "_" +map.colorCode);

            gadgets.Hub.publish(TOPIC_REGION, message);
        }
    }

    for (var i = 0 ; i < data.message.length; i++) {
        successData.push([data.message[i].region, data.message[i].authSuccessCount]);
        failedData.push([data.message[i].region, data.message[i].authFailureCount]);
    }

    var worldSuccessData =  [
        {
            "metadata" : {
                "names" : ["Country","Logins"],
                "types" : ["ordinal", "linear"]
            },
            "data": successData
        }
    ];

    var configSuccessWorld = {
        type: "map",
        x : "Country",
        legend : false,
        padding: { top:0, right:50, bottom:00, left:10 },
        renderer : "canvas",
        charts : [{type: "map",  y : "Logins", mapType : "world"}],
        width: 380,
        height: 250,
        colorScale:["#dcefdc","#5CB85C"]
    };

    configSuccessWorld.helperUrl = "../../portal/templates/geojson/countryInfo.json";
    configSuccessWorld.geoCodesUrl = "../../portal/templates/geojson/world.json";
    var worldSuccessChart = new vizg(worldSuccessData, configSuccessWorld);
    worldSuccessChart.draw("#mapSuccessDiv",[{type:"click", callback:mapCallBack}]);

    var worldFailedData =  [
        {
            "metadata" : {
                "names" : ["Country","Logins"],
                "types" : ["ordinal", "linear"]
            },
            "data": failedData
        }
    ];

    var configFailedWorld = {
        type: "map",
        x : "Country",
        legend : false,
        padding: { top:0, right:50, bottom:00, left:10 },
        renderer : "canvas",
        charts : [{type: "map",  y : "Logins", mapType : "world"}],
        width: 380,
        height: 250,
        colorScale:["#f6d6d5","#D9534F"]
    };

    configFailedWorld.helperUrl = "../../portal/templates/geojson/countryInfo.json";
    configFailedWorld.geoCodesUrl = "../../portal/templates/geojson/world.json";
    var worldFailedChart = new vizg(worldFailedData, configFailedWorld);
    worldFailedChart.draw("#mapFailDiv",[{type:"click", callback:mapCallBack}]);
}

document.body.onmouseup = function() {

    if((rangeStart) && (rangeEnd) && (rangeStart.toString() !== rangeEnd.toString())){

        if(event.target.nodeName == 'path' || event.target.nodeName == 'rect'){
            var timeFromValue = JSON.parse(JSON.stringify(listnedTimeFromValue));
            var timeToValue = JSON.parse(JSON.stringify(listnedTimeToValue));
            var timeRange = [timeFromValue, timeToValue];
            rangeHistoryArray.push(timeRange);
            $("#back").show();

            listnedTimeFromValue = new Date(rangeStart).getTime();
            listnedTimeToValue = new Date(rangeEnd).getTime();
            onDataChanged();
            var message = {
                timeFrom: listnedTimeFromValue,
                timeTo: listnedTimeToValue,
                timeUnit: "Custom"
            };
            gadgets.Hub.publish(TOPIC_SLIDER, message);
        }
    }
}
<|endoftext|>


<commit_before>'use strict';
var fs = require('fs');

var template = fs.readFileSync(__dirname + '/cam-tasklist-search-plugin.html', 'utf8');
var searchConfigJSON = fs.readFileSync(__dirname + '/cam-tasklist-search-plugin-config.json', 'utf8');

var angular = require('camunda-commons-ui/vendor/angular');
var moment = require('camunda-commons-ui/vendor/moment');

var expressionsRegex = /^[\s]*(\#|\$)\{/;
var simpleDateExp = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(|\.[0-9]{0,4})$/;

var searchConfig = JSON.parse(searchConfigJSON);

var parseValue = function(value, enforceString) {
  if(enforceString) {
    return '' + value;
  }
  if(!isNaN(value) && value.trim() !== '') {
      // value must be transformed to number
    return +value;
  }
  if(value === 'true') {
    return true;
  }
  if(value === 'false') {
    return false;
  }
  if(value === 'NULL') {
    return null;
  }
  if(value.indexOf('\'') === 0 && value.lastIndexOf('\'') === value.length - 1) {
    return value.substr(1, value.length - 2);
  }
  return value;
};

var sanitizeValue = function(value, operator, search) {
  if(operator === 'Like' || operator === 'like') {
    return '%'+value+'%';
  } else if(operator == 'in') {
    return value.split(',');
  } else if(search.allowDates && simpleDateExp.test(value)) {
    return moment(value).format('YYYY-MM-DDTHH:mm:ss.SSSZZ');
  }
  return value;
};

var getQueryValueBySearch = function(search) {
  if (search.basic) {
    return true;
  }
  return sanitizeValue(parseValue(search.value.value, search.enforceString), search.operator.value.key, search);
};

var sanitizeProperty = function(search, type, operator, value) {
  var out = type;
  if(['Like', 'Before', 'After'].indexOf(operator) !== -1) {
    out += operator;
  }
  if(expressionsRegex.test(value) &&
       ['assignee', 'owner', 'candidateGroup', 'candidateUser', 'involvedUser', 'processInstanceBusinessKey'].indexOf(type) !== -1) {
    out += 'Expression';
  }
  if(type === 'priority' && operator !== 'eq') {
    out = operator + 'Priority';
  }
  return out;
};

var Controller = [
  '$scope',
  '$translate',
  '$location',
  function(
    $scope,
    $translate,
    $location
  ) {

    $scope.searches = [];
    $scope.translations = {};
    $scope.matchAny = $location.search()['searchOrQuery'] || false;

    angular.forEach(searchConfig.tooltips, function(value, key) {
      $scope.translations[key] = $translate.instant(value);
    });

    $scope.types = searchConfig.types.map(function(el) {
      el.id.value = $translate.instant(el.id.value);
      if(el.operators) {
        el.operators = el.operators.map(function(op) {
          op.value = $translate.instant(op.value);
          return op;
        });
      }
      return el;
    });

    $scope.operators = searchConfig.operators;
    angular.forEach($scope.operators.date, function(el) {
      el.value = $translate.instant(el.value);
    });

    var searchData = $scope.tasklistData.newChild($scope);
    $scope.$watch('[searches, matchAny]', function() {
      var baseQuery = {};
      var tempQuery;

      if ($scope.matchAny === true) {
        baseQuery.orQueries = [{}];
        tempQuery = baseQuery.orQueries[0];
        tempQuery.processVariables = [];
        tempQuery.taskVariables = [];
        tempQuery.caseInstanceVariables = [];
      } else {
        baseQuery.processVariables = [];
        baseQuery.taskVariables = [];
        baseQuery.caseInstanceVariables = [];
        tempQuery = baseQuery;
      }

      angular.forEach($scope.searches, function(search) {
        if(typeof tempQuery[search.type.value.key] === 'object') {
          tempQuery[search.type.value.key].push({
            name: typeof search.name.value === 'object' ? search.name.value.key : search.name.value,
            operator: search.operator.value.key,
            value: getQueryValueBySearch(search)
          });
        } else {
          tempQuery[sanitizeProperty(search, search.type.value.key, search.operator.value.key, search.value.value)] = getQueryValueBySearch(search);
        }
      });

      if ($scope.matchAny === false) {
        delete baseQuery.orQueries;
      }

      searchData.set('searchQuery', baseQuery);
    }, true);

    searchData.observe('currentFilter', function(filter) {
      angular.forEach($scope.types, function(ea) {
        ea.potentialNames = [];
        for(var i = 0; i < (filter.properties.variables && filter.properties.variables.length) || 0; i++) {
          var v = filter.properties.variables[i];
          ea.potentialNames.push({
            key: v.name,
            value: v.label+' ('+v.name+')'
          });
        }
      });

      angular.forEach($scope.searches, function(ea) {
        ea.potentialNames = $scope.types.filter(function(type) {
          return type.id.key === ea.type.value.key;
        })[0].potentialNames;
      });
    });

    searchData.observe('taskList', function(taskList) {
      $scope.totalItems = taskList.count;
    });
  }];

var Configuration = function PluginConfiguration(ViewsProvider) {

  ViewsProvider.registerDefaultView('tasklist.list', {
    id: 'task-search',
    template: template,
    controller: Controller,
    priority: 100
  });
};

Configuration.$inject = ['ViewsProvider'];

module.exports = Configuration;
<commit_msg>feat(cockpit): make like operator flexible to handle  '_' and '%' wildcards in tasklist<commit_after>'use strict';
var fs = require('fs');

var template = fs.readFileSync(__dirname + '/cam-tasklist-search-plugin.html', 'utf8');
var searchConfigJSON = fs.readFileSync(__dirname + '/cam-tasklist-search-plugin-config.json', 'utf8');

var angular = require('camunda-commons-ui/vendor/angular');
var moment = require('camunda-commons-ui/vendor/moment');

var expressionsRegex = /^[\s]*(\#|\$)\{/;
var simpleDateExp = /^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(|\.[0-9]{0,4})$/;

var searchConfig = JSON.parse(searchConfigJSON);

var parseValue = function(value, enforceString) {
  if(enforceString) {
    return '' + value;
  }
  if(!isNaN(value) && value.trim() !== '') {
      // value must be transformed to number
    return +value;
  }
  if(value === 'true') {
    return true;
  }
  if(value === 'false') {
    return false;
  }
  if(value === 'NULL') {
    return null;
  }
  if(value.indexOf('\'') === 0 && value.lastIndexOf('\'') === value.length - 1) {
    return value.substr(1, value.length - 2);
  }
  return value;
};

var sanitizeValue = function(value, operator, search) {
  // Regex for '\_' and '\%' epxressions
  var specialWildCardCharExp = /(\\%)|(\\_)/g;
  // Regex for '_' and '%' special characters
  var wildCardExp = /(\%)|(\_)/;
  if(operator.toLowerCase() === 'like' && !wildCardExp.test(value.replace(specialWildCardCharExp, ''))) {
    return '%'+value+'%';
  } else if(operator == 'in') {
    return value.split(',');
  } else if(search.allowDates && simpleDateExp.test(value)) {
    return moment(value).format('YYYY-MM-DDTHH:mm:ss.SSSZZ');
  }
  return value;
};

var getQueryValueBySearch = function(search) {
  if (search.basic) {
    return true;
  }
  return sanitizeValue(parseValue(search.value.value, search.enforceString), search.operator.value.key, search);
};

var sanitizeProperty = function(search, type, operator, value) {
  var out = type;
  if(['Like', 'Before', 'After'].indexOf(operator) !== -1) {
    out += operator;
  }
  if(expressionsRegex.test(value) &&
       ['assignee', 'owner', 'candidateGroup', 'candidateUser', 'involvedUser', 'processInstanceBusinessKey'].indexOf(type) !== -1) {
    out += 'Expression';
  }
  if(type === 'priority' && operator !== 'eq') {
    out = operator + 'Priority';
  }
  return out;
};

var Controller = [
  '$scope',
  '$translate',
  '$location',
  function(
    $scope,
    $translate,
    $location
  ) {

    $scope.searches = [];
    $scope.translations = {};
    $scope.matchAny = $location.search()['searchOrQuery'] || false;

    angular.forEach(searchConfig.tooltips, function(value, key) {
      $scope.translations[key] = $translate.instant(value);
    });

    $scope.types = searchConfig.types.map(function(el) {
      el.id.value = $translate.instant(el.id.value);
      if(el.operators) {
        el.operators = el.operators.map(function(op) {
          op.value = $translate.instant(op.value);
          return op;
        });
      }
      return el;
    });

    $scope.operators = searchConfig.operators;
    angular.forEach($scope.operators.date, function(el) {
      el.value = $translate.instant(el.value);
    });

    var searchData = $scope.tasklistData.newChild($scope);
    $scope.$watch('[searches, matchAny]', function() {
      var baseQuery = {};
      var tempQuery;

      if ($scope.matchAny === true) {
        baseQuery.orQueries = [{}];
        tempQuery = baseQuery.orQueries[0];
        tempQuery.processVariables = [];
        tempQuery.taskVariables = [];
        tempQuery.caseInstanceVariables = [];
      } else {
        baseQuery.processVariables = [];
        baseQuery.taskVariables = [];
        baseQuery.caseInstanceVariables = [];
        tempQuery = baseQuery;
      }

      angular.forEach($scope.searches, function(search) {
        if(typeof tempQuery[search.type.value.key] === 'object') {
          tempQuery[search.type.value.key].push({
            name: typeof search.name.value === 'object' ? search.name.value.key : search.name.value,
            operator: search.operator.value.key,
            value: getQueryValueBySearch(search)
          });
        } else {
          tempQuery[sanitizeProperty(search, search.type.value.key, search.operator.value.key, search.value.value)] = getQueryValueBySearch(search);
        }
      });

      if ($scope.matchAny === false) {
        delete baseQuery.orQueries;
      }

      searchData.set('searchQuery', baseQuery);
    }, true);

    searchData.observe('currentFilter', function(filter) {
      angular.forEach($scope.types, function(ea) {
        ea.potentialNames = [];
        for(var i = 0; i < (filter.properties.variables && filter.properties.variables.length) || 0; i++) {
          var v = filter.properties.variables[i];
          ea.potentialNames.push({
            key: v.name,
            value: v.label+' ('+v.name+')'
          });
        }
      });

      angular.forEach($scope.searches, function(ea) {
        ea.potentialNames = $scope.types.filter(function(type) {
          return type.id.key === ea.type.value.key;
        })[0].potentialNames;
      });
    });

    searchData.observe('taskList', function(taskList) {
      $scope.totalItems = taskList.count;
    });
  }];

var Configuration = function PluginConfiguration(ViewsProvider) {

  ViewsProvider.registerDefaultView('tasklist.list', {
    id: 'task-search',
    template: template,
    controller: Controller,
    priority: 100
  });
};

Configuration.$inject = ['ViewsProvider'];

module.exports = Configuration;
<|endoftext|>


<commit_before>
var copy = require('dryice').copy;
var fs = require('fs');
var os = require('os');
var spawn = require('child_process').spawn;
var shell = require('shelljs');

var release = __dirname + '/release';

shell.rm('-rf', 'release');

copy.mkdirSync(release + '/content', 0755);
copy({
  source: {
    root: __dirname + '/content',
    include: [ /.*\.html$/ ]
  },
  dest: release + '/content'
});

copy({
  source: [ 'content/loader.js' ],
  dest: release
});

copy({
  source: [
    {
      root: __dirname + '/content',
      exclude: [/loader.js/, /main.js/],
      include: [ /.*\.js$/ ]
    },
    __dirname + '/content/main.js'
  ],
  dest: release + '/content/main.js'
});

copy.mkdirSync(release + '/skin', 0755);
copy({
  source: {
    root: __dirname + '/skin',
    include: [ /.*\.css$/, /.*\.gif$/, /.*\.png$/ ]
  },
  dest: release + '/skin'
});

copy({
  source: [ 'bootstrap.js', 'license.txt', 'README.md', 'app.properties' ],
  dest: release
});

var packageFile = fs.readFileSync(__dirname + '/package.json', 'utf8');
var version = JSON.parse(packageFile).version;
copy({
  source: [ 'install.rdf' ],
  filter: function(data) {
    return data.toString().replace(/@VERSION@/, version);
  },
  dest: release
});

var zip;
if (os.platform() === 'win32') {
  var params = 'a -tzip ../ccdump.xpi skin content bootstrap.js license.txt README.md install.rdf app.properties';
  zip = spawn('7z.exe', params.split(' '), { cwd: release });
}
else {
  zip = spawn('zip', [ '-r', __dirname + '/ccdump.xpi', release ]);
}

zip.on("exit", function() {
  shell.rm('-rf', 'release');
});
<commit_msg>update build file to munge define headers<commit_after>
var copy = require('dryice').copy;
var fs = require('fs');
var os = require('os');
var spawn = require('child_process').spawn;
var shell = require('shelljs');

var release = __dirname + '/release';

shell.rm('-rf', 'release');

copy.mkdirSync(release + '/content', 0755);
copy({
  source: {
    root: __dirname + '/content',
    include: [ /.*\.html$/ ]
  },
  dest: release + '/content'
});

copy({
  source: [ 'content/loader.js' ],
  dest: release
});

var project = copy.createCommonJsProject({
  roots: [ __dirname + '/content' ]
});

/**
 * Munge define lines to add module names
 */
function moduleDefines(input, source) {
  input = (typeof input !== 'string') ? input.toString() : input;
  var deps = source.deps ? Object.keys(source.deps) : [];
  deps = deps.length ? (", '" + deps.join("', '") + "'") : "";
  var module = source.isLocation ? source.path : source;
  module = module.replace(/\.js$/, '');
  return input.replace(/define\(\[/, 'define("' + module + '", [');
};
moduleDefines.onRead = true;

copy({
  source: [
    {
      project: project,
      require: [
        'lib/tabView', 'lib/lib', 'lib/trace', 'tabs/homeTab', 'tabs/aboutTab',
        'app/analyzer', 'app/tabNavigator', 'lib/options',
      ]
    },
    __dirname + '/content/main.js'
  ],
  filter: moduleDefines,
  dest: release + '/content/main.js'
});
console.log(project.report());

copy.mkdirSync(release + '/skin', 0755);
copy({
  source: {
    root: __dirname + '/skin',
    include: [ /.*\.css$/, /.*\.gif$/, /.*\.png$/ ]
  },
  dest: release + '/skin'
});

copy({
  source: [ 'bootstrap.js', 'license.txt', 'README.md', 'app.properties' ],
  dest: release
});

var packageFile = fs.readFileSync(__dirname + '/package.json', 'utf8');
var version = JSON.parse(packageFile).version;
copy({
  source: [ 'install.rdf' ],
  filter: function(data) {
    return data.toString().replace(/@VERSION@/, version);
  },
  dest: release
});

var zip;
if (os.platform() === 'win32') {
  var params = 'a -tzip ../ccdump.xpi skin content bootstrap.js license.txt README.md install.rdf app.properties';
  zip = spawn('7z.exe', params.split(' '), { cwd: release });
}
else {
  zip = spawn('zip', [ '-r', __dirname + '/ccdump.xpi', release ]);
}

zip.on("exit", function() {
  //shell.rm('-rf', 'release');
});
<|endoftext|>


<commit_before>(function() {
  var events = {log: []};
  var session = sessionID();
  var user;

  if ((typeof zooniverse != 'undefined') &&
      (typeof zooniverse.models != 'undefined')) {
    user = zooniverse.models.User;
  } else if (typeof window.User != 'undefined') {
    user = window.User;
  } else if ((typeof require != 'undefined') &&
      (typeof define == 'undefined')) {
    try {
      user = require('zooniverse/lib/models/user');
    } catch (e) {
      user = require('lib/user');
    }
  } else {
    user = {current: {id: "Not Logged In"}};
  }

  function sessionID() {
    var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    });
    return guid;
  }

  function send(auth, data) {
    var url;
    var xhr = new XMLHttpRequest();

    xhr.onload = function() {
      if (xhr.status == 201) {
        timeout = parseInt(xhr.response);
        setTimeout(postLog, timeout, auth);
      } else {
        throw new Error("Failed to Post to Server");
      }
    };
    xhr.onerror = function(e) {
      return e;
    }
    if (parseInt(location.hash) > 1024) {
      url = "http://localhost:3000/events/";
    } else {
      url = "https://sleuther.herokuapp.com/events/";
    }
    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8");
    xhr.setRequestHeader("Accept", "text/plain")
    if (typeof auth == 'object') {
      authStr = btoa(auth.site + ":" + auth.key);
      xhr.setRequestHeader("Authorization", "Basic " + authStr);
    }
    xhr.send(JSON.stringify(data));
  }

  function logEvent(e) {
    var currentUser;
    if ((typeof user.current == 'undefined') ||
        (user.current == null))
      currentUser = "Not Logged-In"
    else
      currentUser = user.current.id
    e.user = currentUser;
    e.session = session;
    e.created_at = new Date();
    e.window_height = window.innerHeight;
    e.window_width = window.innerWidth;
    e.path_name = location.pathname + location.hash;
    e.user_agent = navigator.userAgent;
    events.log.push(e);
  }

  function logDomEvent(e) {
    return if e.target.type === 'password'
    event = {
      type: e.type,
      tag: e.target.tagName,
      id_name: e.target.id,
      class_name: e.target.className,
      position_x: e.clientX,
      position_y: e.clientY,
      value: (e.target.value || "")
    };
    logEvent(event);
  }

  function logCustomEvent(e) {
    if ((typeof e.type == 'undefined') || (typeof e.value == 'undefined'))
      throw new Error("Events Must Have a Type and Value");
    else
      logEvent(e);
  }

  function postLog(auth) {
    if (events.log.length != 0) {
      send(auth, events);
      events.log = [];
    } else {
      setTimeout(postLog, 5000, auth);
    }
  }

  function init(site, key) {
    var auth = {site: site, key: key};
    document.addEventListener("click", logDomEvent, true);
    document.addEventListener("change", logDomEvent, true);
    setTimeout(postLog, 5000, auth);
  }

  sleuth = {
    logCustomEvent: logCustomEvent,
    init: init
  };

  this.sleuth = sleuth;

}).call(this);<commit_msg>Fix to disable for certian types of inputs<commit_after>(function() {
  var events = {log: []};
  var session = sessionID();
  var user;

  if ((typeof zooniverse != 'undefined') &&
      (typeof zooniverse.models != 'undefined')) {
    user = zooniverse.models.User;
  } else if (typeof window.User != 'undefined') {
    user = window.User;
  } else if ((typeof require != 'undefined') &&
      (typeof define == 'undefined')) {
    try {
      user = require('zooniverse/lib/models/user');
    } catch (e) {
      user = require('lib/user');
    }
  } else {
    user = {current: {id: "Not Logged In"}};
  }

  function sessionID() {
    var guid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
      var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
      return v.toString(16);
    });
    return guid;
  }

  function send(auth, data) {
    var url;
    var xhr = new XMLHttpRequest();

    xhr.onload = function() {
      if (xhr.status == 201) {
        timeout = parseInt(xhr.response);
        setTimeout(postLog, timeout, auth);
      } else {
        throw new Error("Failed to Post to Server");
      }
    };
    xhr.onerror = function(e) {
      return e;
    }
    if (parseInt(location.hash) > 1024) {
      url = "http://localhost:3000/events/";
    } else {
      url = "https://sleuther.herokuapp.com/events/";
    }
    xhr.open("POST", url, true);
    xhr.setRequestHeader("Content-Type", "application/json;charset=utf-8");
    xhr.setRequestHeader("Accept", "text/plain")
    if (typeof auth == 'object') {
      authStr = btoa(auth.site + ":" + auth.key);
      xhr.setRequestHeader("Authorization", "Basic " + authStr);
    }
    xhr.send(JSON.stringify(data));
  }

  function logEvent(e) {
    var currentUser;
    if ((typeof user.current == 'undefined') ||
        (user.current == null))
      currentUser = "Not Logged-In"
    else
      currentUser = user.current.id
    e.user = currentUser;
    e.session = session;
    e.created_at = new Date();
    e.window_height = window.innerHeight;
    e.window_width = window.innerWidth;
    e.path_name = location.pathname + location.hash;
    e.user_agent = navigator.userAgent;
    events.log.push(e);
  }

  function logDomEvent(e) {
    if (e.target.type === 'password')
      return;
    event = {
      type: e.type,
      tag: e.target.tagName,
      id_name: e.target.id,
      class_name: e.target.className,
      position_x: e.clientX,
      position_y: e.clientY,
      value: (e.target.value || "")
    };
    logEvent(event);
  }

  function logCustomEvent(e) {
    if ((typeof e.type == 'undefined') || (typeof e.value == 'undefined'))
      throw new Error("Events Must Have a Type and Value");
    else
      logEvent(e);
  }

  function postLog(auth) {
    if (events.log.length != 0) {
      send(auth, events);
      events.log = [];
    } else {
      setTimeout(postLog, 5000, auth);
    }
  }

  function init(site, key) {
    var auth = {site: site, key: key};
    document.addEventListener("click", logDomEvent, true);
    document.addEventListener("change", logDomEvent, true);
    setTimeout(postLog, 5000, auth);
  }

  sleuth = {
    logCustomEvent: logCustomEvent,
    init: init
  };

  this.sleuth = sleuth;

}).call(this);<|endoftext|>


<commit_before>'use strict';
var Configurable = require('../../lib/configurable'),
    LusterConfigurationError = require('../../lib/errors').LusterConfigurationError,
    fixturesConf = require('../fixtures/luster.conf'),
    extend = require('extend');

// suppress stderr from terror
LusterConfigurationError.setLogger(function() {});

describe('Configurable', function() {
    var configurable,
        sandbox = sinon.sandbox.create();

    afterEach(function() {
        sandbox.restore();
    });

    describe('configure', function() {
        var config;

        beforeEach(function() {
            configurable = new Configurable();
            config = extend({}, fixturesConf, true);
            configurable.addListener('error', function() {});
        });

        afterEach(function() {
            configurable.removeAllListeners('error');
        });

        it('should emit "configured" event on configuration success', function() {
            sandbox.spy(configurable, 'emit');

            configurable.configure(config);

            assert.calledWith(configurable.emit, 'configured');
        });

        it('should emit "error" event for malformed config', function() {
            sandbox.spy(configurable, 'emit');

            configurable.configure({});

            assert.calledWith(configurable.emit, 'error');
        });

        describe('configuring via environment variable', function() {
            afterEach(function() {
                delete process.env.LUSTER_CONF;
            });

            it('should do simple one-level override', function() {
                process.env.LUSTER_CONF = 'workers=1';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('workers'), 1);
            });

            it('should do nothing if overriding is explicitly turned off', function() {
                process.env.LUSTER_CONF = 'workers=1';

                configurable.configure(config, false);

                assert.strictEqual(configurable.config.get('workers'), 10);
            });

            it('should override to undefined value via empty string', function() {
                process.env.LUSTER_CONF = 'foo=';

                configurable.configure(config);

                assert.isUndefined(configurable.config.get('foo'));
            });

            it('should do nothing when only propname is provided', function() {
                process.env.LUSTER_CONF = 'foo';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('foo'), true);
            });

            it('should emit error when trying to override non-string property with a string', function() {
                process.env.LUSTER_CONF = 'workers=some';
                sandbox.spy(configurable, 'emit');

                configurable.configure(config);

                assert.calledWith(configurable.emit, 'error');
            });

            it('should respect semicolon in quoted property value', function() {
                process.env.LUSTER_CONF = 'foo="baz;"';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('foo'), 'baz;');
            });

            it('should respect equality sign in quoted property value', function() {
                process.env.LUSTER_CONF = 'foo="baz=bar"';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('foo'), 'baz=bar');
            });

            it('should parse json from propval', function() {
                process.env.LUSTER_CONF = 'properties={"foo":true,"baz":"bar"}';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('properties.foo'), true);
                assert.strictEqual(configurable.config.get('properties.baz'), 'bar');
            });

            it('should override complex property with a scalar value', function() {
                process.env.LUSTER_CONF = 'server=true';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('server'), true);
            });

            it('should throw when trying to set inner property to a scalar property', function() {
                process.env.LUSTER_CONF = 'baz.foo.bar=true';

                assert.throws(function() { configurable.configure(config); },
                    'LusterConfigurationError: Property "baz.foo" already exists and is not an object');
            });

            it('should do second-level nested property override', function() {
                process.env.LUSTER_CONF = 'server.port=8080';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('server.port'), 8080);
            });

            it('should do deep nested property override', function() {
                process.env.LUSTER_CONF = 'properties.foo.bar.baz=true';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('properties.foo.bar.baz'), true);
            });

            describe('should override multiple properties at once', function() {
                it('should respect semicolon separated values', function() {
                    process.env.LUSTER_CONF = 'workers=1;foo=false';

                    configurable.configure(config);

                    assert.strictEqual(configurable.config.get('workers'), 1);
                    assert.strictEqual(configurable.config.get('foo'), false);
                });

                it('whitespaces should not matter', function() {
                    process.env.LUSTER_CONF = 'workers = 1; foo =false';

                    configurable.configure(config);

                    assert.strictEqual(configurable.config.get('workers'), 1);
                    assert.strictEqual(configurable.config.get('foo'), false);
                });
            });
        });
    });

});
<commit_msg>fix event handler mock<commit_after>'use strict';
var Configurable = require('../../lib/configurable'),
    LusterConfigurationError = require('../../lib/errors').LusterConfigurationError,
    fixturesConf = require('../fixtures/luster.conf'),
    extend = require('extend');

// suppress stderr from terror
LusterConfigurationError.setLogger(function() {});

describe('Configurable', function() {
    var configurable,
        sandbox = sinon.sandbox.create();

    afterEach(function() {
        sandbox.restore();
    });

    describe('configure', function() {
        var config;

        beforeEach(function() {
            configurable = new Configurable();
            config = extend({}, fixturesConf, true);
            configurable.addListener('error', function() {});
        });

        afterEach(function() {
            configurable.removeAllListeners('error');
        });

        it('should emit "configured" event on configuration success', function() {
            var spy = sandbox.spy();

            configurable.on('configured', spy);
            configurable.configure(config);

            assert.calledOnce(spy);
        });

        it('should emit "error" event for malformed config', function() {
            var spy = sandbox.spy();

            configurable.on('error', spy);
            configurable.configure({});

            assert.calledOnce(spy);
        });

        describe('configuring via environment variable', function() {
            afterEach(function() {
                delete process.env.LUSTER_CONF;
            });

            it('should do simple one-level override', function() {
                process.env.LUSTER_CONF = 'workers=1';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('workers'), 1);
            });

            it('should do nothing if overriding is explicitly turned off', function() {
                process.env.LUSTER_CONF = 'workers=1';

                configurable.configure(config, false);

                assert.strictEqual(configurable.config.get('workers'), 10);
            });

            it('should override to undefined value via empty string', function() {
                process.env.LUSTER_CONF = 'foo=';

                configurable.configure(config);

                assert.isUndefined(configurable.config.get('foo'));
            });

            it('should do nothing when only propname is provided', function() {
                process.env.LUSTER_CONF = 'foo';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('foo'), true);
            });

            it('should emit error when trying to override non-string property with a string', function() {
                process.env.LUSTER_CONF = 'workers=some';
                var spy = sandbox.spy();

                configurable.on('error', spy);
                configurable.configure(config);

                assert.calledOnce(spy);
            });

            it('should respect semicolon in quoted property value', function() {
                process.env.LUSTER_CONF = 'foo="baz;"';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('foo'), 'baz;');
            });

            it('should respect equality sign in quoted property value', function() {
                process.env.LUSTER_CONF = 'foo="baz=bar"';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('foo'), 'baz=bar');
            });

            it('should parse json from propval', function() {
                process.env.LUSTER_CONF = 'properties={"foo":true,"baz":"bar"}';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('properties.foo'), true);
                assert.strictEqual(configurable.config.get('properties.baz'), 'bar');
            });

            it('should override complex property with a scalar value', function() {
                process.env.LUSTER_CONF = 'server=true';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('server'), true);
            });

            it('should throw when trying to set inner property to a scalar property', function() {
                process.env.LUSTER_CONF = 'baz.foo.bar=true';

                assert.throws(function() { configurable.configure(config); },
                    'LusterConfigurationError: Property "baz.foo" already exists and is not an object');
            });

            it('should do second-level nested property override', function() {
                process.env.LUSTER_CONF = 'server.port=8080';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('server.port'), 8080);
            });

            it('should do deep nested property override', function() {
                process.env.LUSTER_CONF = 'properties.foo.bar.baz=true';

                configurable.configure(config);

                assert.strictEqual(configurable.config.get('properties.foo.bar.baz'), true);
            });

            describe('should override multiple properties at once', function() {
                it('should respect semicolon separated values', function() {
                    process.env.LUSTER_CONF = 'workers=1;foo=false';

                    configurable.configure(config);

                    assert.strictEqual(configurable.config.get('workers'), 1);
                    assert.strictEqual(configurable.config.get('foo'), false);
                });

                it('whitespaces should not matter', function() {
                    process.env.LUSTER_CONF = 'workers = 1; foo =false';

                    configurable.configure(config);

                    assert.strictEqual(configurable.config.get('workers'), 1);
                    assert.strictEqual(configurable.config.get('foo'), false);
                });
            });
        });
    });

});
<|endoftext|>


<commit_before>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "c9", "tabManager", "preferences", "settings", "save", "ace", "proc", "info", "http"
    ];
    main.provides = ["wakatime"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var c9 = imports.c9;
        var settings = imports.settings;
        var prefs = imports.preferences;
        var tabManager = imports.tabManager;
        var ace = imports.ace;
        var save = imports.save;
        var proc = imports.proc;
        var info = imports.info;
        var http = imports.http;

        var path = require('path');

        /***** Initialization *****/

        var plugin = new Plugin("WakaTime", main.consumes);
        var api  = plugin.setAPIKey(options.apikey);
        // var emit = plugin.getEmitter();
        // emit.setMaxListeners(2);

        var pluginVersion = null;
        var c9Version = null;
        var lastFile = null;
        var lastWrite = null;
        var lastTime = 0;
        var cachedPythonLocation = null;
        var cachedApiKey = null;

        function init() {
            pluginVersion = options.version || '2.0.3';
            c9Version = c9.version.split(' ')[0];
            if (settings.get('user/wakatime/@debug'))
                console.log('Initializing WakaTime v' + pluginVersion);

            setupSettings();

            // get user's c9 email address
            info.getUser(function(err, user) {
                if (err || !user || !user.email) {
                    console.log(err);
                    finishInit();
                } else {
                    getApiKey(function(apiKey) {
                        if (isValidApiKey(apiKey)) {
                            finishInit();
                        } else {
                            createWakaUser(user, finishInit);
                        }
                    });
                }
            });
        }

        function finishInit() {

            // make sure we have a WakaTime api key
            getApiKey(function(apiKey) {

                if (!isValidApiKey(apiKey)) {
                    apiKey = promptForApiKey(apiKey);
                    if (isValidApiKey(apiKey))
                        setApiKey(apiKey);
                }

                setupEventHandlers();

            });
        }

        /***** Methods *****/

        function createWakaUser(user, callback) {
            var url = 'https://wakatime.com/api/v1/users/signup/c9'
            var body = {
                email: user.email,
            };
            if (user.fullname) body.full_name = user.fullname;
            var options = {
                method: 'POST',
                body: body,
                timeout: 30000,
            };
            http.request(url, options, function(err, data, res) {
                if (err) console.log(err);
                if (data && data.data && isValidApiKey(data.data.api_key))
                    setApiKey(data.data.api_key);
                callback && callback();
            });
        }

        function setApiKey(apiKey) {
            if (isValidApiKey(apiKey)) {
                cachedApiKey = apiKey;

                var data = {
                    apiKey: apiKey,
                };
                api.setPersistentData("user", data, function(err) {
                    if (err) console.log(err);
                });
            }
        }

        function getApiKey(callback) {
            if (cachedApiKey) return callback && callback(cachedApiKey);

            api.getPersistentData("user", function(err, data) {
                if (err) console.log(err);
                var apiKey = undefined;
                if (data && data.apiKey) apiKey = data.apiKey;
                callback && callback(apiKey);
            });
        }

        function promptForApiKey(defaultKey) {
            var key = window.prompt("[WakaTime] Enter your wakatime.com api key:", defaultKey);
            return key;
        }

        function isValidApiKey(key) {
            if (!key) return false;
            var re = new RegExp('^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$', 'i');
            return re.test(key);
        }

        function setupSettings() {
            settings.on("read", function(e) {
                settings.setDefaults("user/wakatime", [
                    ["debug", false],
                    ["exclude", ""],
                ]);
            });
            prefs.add({
                "WakaTime" : {
                    position: 650,
                    "WakaTime" : {
                        position: 100,
                        "Debug": {
                            type: "checkbox",
                            setting: "user/wakatime/@debug",
                            position: 100,
                        },
                        "Exclude": {
                            type: "textarea-row",
                            setting: "user/wakatime/@exclude",
                            position: 200,
                            width: 600,
                            height: 100,
                            fixedFont: true,
                            rowheight: 250,
                        },
                    }
                }
            }, plugin);
        }

        function setupEventHandlers() {

            save.on('afterSave', function(e) {
                handleActivity(true);
            });

            tabManager.on('focus', function(e) {
                handleActivity();
            });

            ace.on('create', function(createEvent) {
                createEvent.editor.ace.on('input', function(e) {
                    handleActivity();
                });
            }, plugin);
        }

        function enoughTimePassed(time) {
            return lastTime + 120000 < time;
        }

        function fileIsIgnored(file) {
            var patterns = settings.get('user/wakatime/@exclude').split(/\n/);
            var ignore = false;
            for (var i=0; i<patterns.length; i++) {
                if (patterns[i].trim()) {
                    var re = new RegExp(patterns[i], 'gi');
                    if (re.test(file)) {
                        // console.log("matched " + patterns[i] + " on " + file);
                        ignore = true;
                        break;
                    }
                }
            }
            return ignore;
        }

        function pythonLocation(callback, locations) {
            if (cachedPythonLocation) {
                if (callback)
                    return callback(cachedPythonLocation);
                else
                    return;
            }

            if (locations === undefined) {
                locations = [
                    'pythonw',
                    'python',
                    '/usr/local/bin/python',
                    '/usr/bin/python',
                ];
                for (var i=26; i<40; i++) {
                    locations.push(path.join('python' + i, 'pythonw'));
                    locations.push(path.join('Python' + i, 'pythonw'));
                }
            }

            if (locations.length == 0) {
                if (callback)
                    callback(null);
                return;
            }

            var args = ['--version'];
            var location = locations[0];

            proc.execFile(location, {args:args}, function(error, stdout, stderr) {
                if (!error) {
                    cachedPythonLocation = location;
                    if (callback)
                        callback(location);
                } else {
                    locations.splice(0, 1);
                    pythonLocation(callback, locations);
                }
            });

        }

        function coreLocation() {
            return path.join(c9.home, '.c9/lib/wakatime/wakatime/cli.py');
        }

        function obfuscateKey(key) {
            var newKey = '';
            if (key) {
                newKey = key;
                if (key.length > 4)
                    newKey = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX' + key.substring(key.length - 4);
            }
            return newKey;
        }

        function obfuscateKeyFromArguments(args) {
            var newCmds = [];
            var lastCmd = "";
            for (var i = 0; i<args.length; i++) {
                if (lastCmd == "--key")
                    newCmds.push(obfuscateKey(args[i]));
                else
                    newCmds.push(args[i]);
                lastCmd = args[i];
            }
            return newCmds;
        }

        function handleActivity(isWrite) {
            var tab = tabManager.focussedTab;
            if (!tab) return;

            var file = tab.path;
            if (!file)
                return;

            if (file.indexOf('~') == 0) {
                file = path.join(c9.home, file.substring(1));
            } else if (file.indexOf(c9.home, 0) != 0) {
                file = path.join(c9.workspaceDir, file);
            }

            var time = Date.now();
            if (isWrite && lastWrite != isWrite || enoughTimePassed(time) || lastFile != file) {
                if (fileIsIgnored(file))
                    return;

                var cursorpos = getCursorPosition(tab);
                sendHeartbeat(file, time, isWrite, cursorpos);
            }
        }

        function getCursorPosition(tab) {
            try {
                if (!tab) return null;
                var aceSession = tab.document.getSession().session;
                if (!aceSession) return null;
                var aceDoc = aceSession.doc;
                if (!aceDoc) return null;
                var selection = aceSession.getSelection();
                if (!selection) return null;
                var anchor = selection.anchor;
                if (!anchor) return null;
                var row = anchor.row;
                var col = anchor.column;
                var cursorpos = aceDoc.positionToIndex({ row: row, column: col });
                if (cursorpos !== undefined && cursorpos != null) return cursorpos;
                return null;
            } catch(err) {
                console.log(err);
                cursorpos = null;
            }
        }

        function sendHeartbeat(file, time, isWrite, cursorpos) {
            pythonLocation(function(python) {
                if (!python)
                    return;
                var debug = settings.get("user/wakatime/@debug");
                getApiKey(function(apiKey) {
                    var core = coreLocation();
                    var userAgent = 'c9/' + c9Version + ' c9-wakatime/' + pluginVersion;
                    var args = [core, '--file', file, '--plugin', userAgent];
                    if (isWrite)
                        args.push('--write');
                    if (isValidApiKey(apiKey)) {
                        args.push('--key');
                        args.push(apiKey);
                    }
                    if (cursorpos != null) {
                        args.push('--cursorpos');
                        args.push(cursorpos);
                    }
                    if (debug) {
                        args.push('--verbose');
                        var clone = args.slice(0);
                        clone.unshift(python);
                        console.log('Sending heartbeat: ' + obfuscateKeyFromArguments(clone).join(' '));
                    }
                    proc.execFile(python, {args:args}, function(error, stdout, stderr) {
                        if (error) {
                            if (stderr && stderr != '')
                                console.warn(stderr);
                            if (stdout && stdout != '')
                                console.warn(stdout);

                            var msg = error.message;
                            var status = 'Error'
                            var title = 'Unknown Error (' + error.code + '); Check your Dev Console and ~/.wakatime.log for more info.'
                            if (error.code == 102) {
                                msg = null;
                                status = null;
                                title = 'WakaTime Offline, coding activity will sync when online.';
                            } else if (error.code == 103) {
                                msg = 'An error occured while parsing ~/.wakatime.cfg. Check ~/.wakatime.log for more info.';
                                status = 'Error';
                                title = msg;
                            } else if (error.code == 104) {
                                msg = 'Invalid API Key. Make sure your API Key is correct!';
                                status = 'Error';
                                title = msg;
                            }

                            console.warn(msg);
                            setStatusBarText(status);
                            setStatusBarTitle(title);
                        }
                    });
                    lastTime = time;
                    lastFile = file;
                    lastWrite = !!isWrite;
                });
            });
        }

        function setStatusBarText(text) {
            // TODO: update status bar text
            return;
        }

        function setStatusBarTitle(text) {
            // TODO: update status bar onhover title
            return;
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            init();
        });
        plugin.on("unload", function() {
        });

        /***** Register and define API *****/
        plugin.freezePublicAPI({
            _events: [
            ],
        });

        register(null, {
            "wakatime": plugin
        });
    }
});
<commit_msg>allow user to change api key from user prefs<commit_after>define(function(require, exports, module) {
    main.consumes = [
        "Plugin", "c9", "tabManager", "preferences", "settings", "save", "ace", "proc", "info", "http"
    ];
    main.provides = ["wakatime"];
    return main;

    function main(options, imports, register) {
        var Plugin = imports.Plugin;
        var c9 = imports.c9;
        var settings = imports.settings;
        var prefs = imports.preferences;
        var tabManager = imports.tabManager;
        var ace = imports.ace;
        var save = imports.save;
        var proc = imports.proc;
        var info = imports.info;
        var http = imports.http;

        var path = require('path');

        /***** Initialization *****/

        var plugin = new Plugin("WakaTime", main.consumes);
        var api  = plugin.setAPIKey(options.apikey);
        // var emit = plugin.getEmitter();
        // emit.setMaxListeners(2);

        var pluginVersion = null;
        var c9Version = null;
        var lastFile = null;
        var lastWrite = null;
        var lastTime = 0;
        var cachedPythonLocation = null;
        var cachedApiKey = null;

        function init() {
            pluginVersion = options.version || '2.0.3';
            c9Version = c9.version.split(' ')[0];
            if (settings.get('user/wakatime/@debug'))
                console.log('Initializing WakaTime v' + pluginVersion);

            getApiKey(function(apiKey) {
                if (isValidApiKey(apiKey))
                    settings.set("user/wakatime/@apikey", apiKey);
                setupSettings();
            });

            // get user's c9 email address
            info.getUser(function(err, user) {
                if (err || !user || !user.email) {
                    console.log(err);
                    finishInit();
                } else {
                    getApiKey(function(apiKey) {
                        if (isValidApiKey(apiKey)) {
                            finishInit();
                        } else {
                            createWakaUser(user, finishInit);
                        }
                    });
                }
            });
        }

        function finishInit() {

            // make sure we have a WakaTime api key
            getApiKey(function(apiKey) {

                if (!isValidApiKey(apiKey)) {
                    apiKey = promptForApiKey(apiKey);
                    if (isValidApiKey(apiKey))
                        setApiKey(apiKey);
                }

                setupEventHandlers();

            });
        }

        /***** Methods *****/

        function createWakaUser(user, callback) {
            var url = 'https://wakatime.com/api/v1/users/signup/c9'
            var body = {
                email: user.email,
            };
            if (user.fullname) body.full_name = user.fullname;
            var options = {
                method: 'POST',
                body: body,
                timeout: 30000,
            };
            http.request(url, options, function(err, data, res) {
                if (err) console.log(err);
                if (data && data.data && isValidApiKey(data.data.api_key))
                    setApiKey(data.data.api_key);
                callback && callback();
            });
        }

        function setApiKey(apiKey) {
            if (isValidApiKey(apiKey)) {
                cachedApiKey = apiKey;

                var data = {
                    apiKey: apiKey,
                };
                api.setPersistentData("user", data, function(err) {
                    if (err) console.log(err);
                });
            }
        }

        function getApiKey(callback) {
            if (cachedApiKey) return callback && callback(cachedApiKey);

            api.getPersistentData("user", function(err, data) {
                if (err) console.log(err);
                var apiKey = undefined;
                if (data && data.apiKey) apiKey = data.apiKey;
                callback && callback(apiKey);
            });
        }

        function promptForApiKey(defaultKey) {
            var key = window.prompt("[WakaTime] Enter your wakatime.com api key:", defaultKey);
            return key;
        }

        function isValidApiKey(key) {
            if (!key) return false;
            var re = new RegExp('^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$', 'i');
            return re.test(key);
        }

        function setupSettings() {
            settings.on("read", function(e) {
                settings.setDefaults("user/wakatime", [
                    ["apikey", ""],
                    ["debug", false],
                    ["exclude", ""],
                ]);
            });
            settings.on("user/wakatime/@apikey", function(value) {
                setApiKey(value);
            }, plugin);
            prefs.add({
                "WakaTime" : {
                    position: 650,
                    "WakaTime" : {
                        position: 100,
                        "API Key": {
                            type: "textbox",
                            setting: "user/wakatime/@apikey",
                            position: 100,
                            width: 242,
                        },
                        "Debug": {
                            type: "checkbox",
                            setting: "user/wakatime/@debug",
                            position: 200,
                        },
                        "Exclude": {
                            type: "textarea-row",
                            setting: "user/wakatime/@exclude",
                            position: 300,
                            width: 600,
                            height: 100,
                            fixedFont: true,
                            rowheight: 250,
                        },
                    }
                }
            }, plugin);
        }

        function setupEventHandlers() {

            save.on('afterSave', function(e) {
                handleActivity(true);
            });

            tabManager.on('focus', function(e) {
                handleActivity();
            });

            ace.on('create', function(createEvent) {
                createEvent.editor.ace.on('input', function(e) {
                    handleActivity();
                });
            }, plugin);
        }

        function enoughTimePassed(time) {
            return lastTime + 120000 < time;
        }

        function fileIsIgnored(file) {
            var patterns = settings.get('user/wakatime/@exclude').split(/\n/);
            var ignore = false;
            for (var i=0; i<patterns.length; i++) {
                if (patterns[i].trim()) {
                    var re = new RegExp(patterns[i], 'gi');
                    if (re.test(file)) {
                        // console.log("matched " + patterns[i] + " on " + file);
                        ignore = true;
                        break;
                    }
                }
            }
            return ignore;
        }

        function pythonLocation(callback, locations) {
            if (cachedPythonLocation) {
                if (callback)
                    return callback(cachedPythonLocation);
                else
                    return;
            }

            if (locations === undefined) {
                locations = [
                    'pythonw',
                    'python',
                    '/usr/local/bin/python',
                    '/usr/bin/python',
                ];
                for (var i=26; i<40; i++) {
                    locations.push(path.join('python' + i, 'pythonw'));
                    locations.push(path.join('Python' + i, 'pythonw'));
                }
            }

            if (locations.length == 0) {
                if (callback)
                    callback(null);
                return;
            }

            var args = ['--version'];
            var location = locations[0];

            proc.execFile(location, {args:args}, function(error, stdout, stderr) {
                if (!error) {
                    cachedPythonLocation = location;
                    if (callback)
                        callback(location);
                } else {
                    locations.splice(0, 1);
                    pythonLocation(callback, locations);
                }
            });

        }

        function coreLocation() {
            return path.join(c9.home, '.c9/lib/wakatime/wakatime/cli.py');
        }

        function obfuscateKey(key) {
            var newKey = '';
            if (key) {
                newKey = key;
                if (key.length > 4)
                    newKey = 'XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXX' + key.substring(key.length - 4);
            }
            return newKey;
        }

        function obfuscateKeyFromArguments(args) {
            var newCmds = [];
            var lastCmd = "";
            for (var i = 0; i<args.length; i++) {
                if (lastCmd == "--key")
                    newCmds.push(obfuscateKey(args[i]));
                else
                    newCmds.push(args[i]);
                lastCmd = args[i];
            }
            return newCmds;
        }

        function handleActivity(isWrite) {
            var tab = tabManager.focussedTab;
            if (!tab) return;

            var file = tab.path;
            if (!file)
                return;

            if (file.indexOf('~') == 0) {
                file = path.join(c9.home, file.substring(1));
            } else if (file.indexOf(c9.home, 0) != 0) {
                file = path.join(c9.workspaceDir, file);
            }

            var time = Date.now();
            if (isWrite && lastWrite != isWrite || enoughTimePassed(time) || lastFile != file) {
                if (fileIsIgnored(file))
                    return;

                var cursorpos = getCursorPosition(tab);
                sendHeartbeat(file, time, isWrite, cursorpos);
            }
        }

        function getCursorPosition(tab) {
            try {
                if (!tab) return null;
                var aceSession = tab.document.getSession().session;
                if (!aceSession) return null;
                var aceDoc = aceSession.doc;
                if (!aceDoc) return null;
                var selection = aceSession.getSelection();
                if (!selection) return null;
                var anchor = selection.anchor;
                if (!anchor) return null;
                var row = anchor.row;
                var col = anchor.column;
                var cursorpos = aceDoc.positionToIndex({ row: row, column: col });
                if (cursorpos !== undefined && cursorpos != null) return cursorpos;
                return null;
            } catch(err) {
                console.log(err);
                cursorpos = null;
            }
        }

        function sendHeartbeat(file, time, isWrite, cursorpos) {
            pythonLocation(function(python) {
                if (!python)
                    return;
                var debug = settings.get("user/wakatime/@debug");
                getApiKey(function(apiKey) {
                    var core = coreLocation();
                    var userAgent = 'c9/' + c9Version + ' c9-wakatime/' + pluginVersion;
                    var args = [core, '--file', file, '--plugin', userAgent];
                    if (isWrite)
                        args.push('--write');
                    if (isValidApiKey(apiKey)) {
                        args.push('--key');
                        args.push(apiKey);
                    }
                    if (cursorpos != null) {
                        args.push('--cursorpos');
                        args.push(cursorpos);
                    }
                    if (debug) {
                        args.push('--verbose');
                        var clone = args.slice(0);
                        clone.unshift(python);
                        console.log('Sending heartbeat: ' + obfuscateKeyFromArguments(clone).join(' '));
                    }
                    proc.execFile(python, {args:args}, function(error, stdout, stderr) {
                        if (error) {
                            if (stderr && stderr != '')
                                console.warn(stderr);
                            if (stdout && stdout != '')
                                console.warn(stdout);

                            var msg = error.message;
                            var status = 'Error'
                            var title = 'Unknown Error (' + error.code + '); Check your Dev Console and ~/.wakatime.log for more info.'
                            if (error.code == 102) {
                                msg = null;
                                status = null;
                                title = 'WakaTime Offline, coding activity will sync when online.';
                            } else if (error.code == 103) {
                                msg = 'An error occured while parsing ~/.wakatime.cfg. Check ~/.wakatime.log for more info.';
                                status = 'Error';
                                title = msg;
                            } else if (error.code == 104) {
                                msg = 'Invalid API Key. Make sure your API Key is correct!';
                                status = 'Error';
                                title = msg;
                            }

                            console.warn(msg);
                            setStatusBarText(status);
                            setStatusBarTitle(title);
                        }
                    });
                    lastTime = time;
                    lastFile = file;
                    lastWrite = !!isWrite;
                });
            });
        }

        function setStatusBarText(text) {
            // TODO: update status bar text
            return;
        }

        function setStatusBarTitle(text) {
            // TODO: update status bar onhover title
            return;
        }

        /***** Lifecycle *****/

        plugin.on("load", function() {
            init();
        });
        plugin.on("unload", function() {
        });

        /***** Register and define API *****/
        plugin.freezePublicAPI({
            _events: [
            ],
        });

        register(null, {
            "wakatime": plugin
        });
    }
});
<|endoftext|>