Greasy Fork is available in English.

WME SER_Outreach

captures editor information from WME for addition to SER outreach database

// ==UserScript==
// @name         WME SER_Outreach
// @namespace    https://greasyfork.org/en/scripts/389934-wme-ser-outreach
// @version      2021.08.29
// @description  captures editor information from WME for addition to SER outreach database
// @author       ramblinwreck_81
// @include      https://www.waze.com/en-US/editor*
// @exclude      https://www.waze.com/user/editor*
// @grant        none
// @require      https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js


// ==/UserScript==

(function() {
    'use strict';
    var SO_Name = GM_info.script.name;
    var SO_Version = GM_info.script.version;
    var settings = {};
    var venuesObject;
    var eID;
    var rank;
    var geoOffset = 'nada';

    function SO_log(message) {
        console.log(`SER Outreach: ${message}`);
    }
    function bootstrap(tries) {
        SO_log(`bootstrap`);
        tries = tries || 1;

        if (W && W.map &&
            W.model && W.loginManager.user &&
            $ ) {
            SO_init();
//            tabBuilder();
        } else if (tries < 1000) {
            setTimeout(function () {bootstrap(tries++);}, 200);
        }
    }

    bootstrap();

    function SO_init() {
        // Check document elements are ready
        var userInfo = document.getElementById("user-info");
        var newEdName = "";
        if (userInfo === null) {
            window.setTimeout(SO_init, 500);
            return;
        }
        var userTabs = document.getElementById("user-tabs");
        if (userTabs === null) {
            window.setTimeout(SO_init, 500);
            return;
        }
        var navTab = userInfo.getElementsByTagName("ul");
        if (navTab.length === 0) {
            window.setTimeout(SO_init, 500);
            return;
        }
        if (typeof navTab[0] === "undefined") {
            window.setTimeout(SO_init, 500);
            return;
        }
        var tabContent = userInfo.getElementsByTagName("div");
        if (tabContent.length === 0) {
            window.setTimeout(SO_init, 500);
            return;
        }
        if (typeof tabContent[0] === "undefined") {
            window.setTimeout(SO_init, 500);
            return;
        }
        var editorURL = '';
        SO_addUserTab();
        SO_addFormBtn();
        function SO_addFormBtn() {
            SO_log(`adding form button`);
            var selection = W.selectionManager.getSelectedFeatures();
            var SODiv = document.createElement("div"),
                SOMnu = document.createElement("select"),
                SOBtn = document.createElement("button");
            var formWindowName = "SER Outreach result",
                formWindowSpecs = "resizable=1,menubar=0,scrollbars=1,status=0,toolbar=0";
            var editPanel,
                selElem,
                formLink;
           SODiv.id = "SER Outreach Div";
            editPanel = document.getElementById("edit-panel");
            selElem = editPanel.getElementsByClassName("selection");
            if (selection.length === 0) { // || selection[0].model.type !== "segment") {
                //formfiller_log("No segments selected.");
                return;
            }
            if (document.getElementById("SEROutreachDiv")) {
                //formfiller_log("Div already created");
                return;
            }

           var forms = [{
                name: "SER Outreach",
                // testing url: "https://docs.google.com/forms/d/e/1FAIpQLSd1Pb1wMLrzKRaXTfQMW1t4FP976WxuPVHognsGrEX4tjis3g/viewform",
                url: "https://docs.google.com/forms/d/e/1FAIpQLSeZ41NxN-kBQmCvvmMtmqLFYPVOGMmCRgZHnLhgofSHKTPY8A/viewform",
                fields: {
                    reporter: "1640561694",
                    profileLink: "37823008",
                    permalink: "1104282593",
                    state: "1743717821",
                    //ed: "343499315",
                    //nameOfVenue: "418181794",
                    editorRank: "1217937573"
                }
            }];

            forms.forEach(function (key, i) {
                SOMnu.options.add(new Option(forms[i].name, i));
            });
            SOBtn.innerHTML = "Go to Form";
            SOBtn.onclick = function () {
                //alert(ffMnu.options[ffMnu.selectedIndex].value+": "+forms[ffMnu.options[ffMnu.selectedIndex].value].name);
                SO_saveSettings();
                formLink = SO_createFormLink(forms[SOMnu.options[SOMnu.selectedIndex].value]);
                if (typeof formLink === "undefined") {
                    return;
                }

                if ($("#SO-open-in-tab").prop("checked")) {
                    window.open(formLink, "_blank");
                } else {
                    window.open(formLink, formWindowName, formWindowSpecs);
                }
            };
            SODiv.appendChild(SOMnu);
            SODiv.appendChild(SOBtn);
            selElem[0].appendChild(SODiv);

            return;
    } // end of SO_addFormBtn


        function createURL(selection)
        {
            var permalink = "https://www.waze.com/en-US/editor?",
            segIDs = [];
            var latLon;
            var lat;
            var lon;
            var env = W.location ? W.location.code : W.app.getAppRegionCode();
            var zoom = W.map.olMap.zoom;
            var type;
            var rank = mostRecentEditorDetails.rank + 1;
            if (W.selectionManager.getSelectedFeatures()[0].model.type === "venue") { // code for selection is a place venue
                if(W.selectionManager.getSelectedFeatures()[0].model.isPoint())

                { // get lat and lon for point place
                    latLon = WazeWrap.Geometry.ConvertTo4326(selection[0].geometry.x, selection[0].geometry.y)
                    lat = latLon.lat
                    lon = latLon.lon
                    // lon = selection[0].geometry.transform(W.map.displayProjection.projCode).x;

                } else
                { // get lat and lon for area place
                    latLon = WazeWrap.Geometry.ConvertTo4326(selection[0].model.geometry.getCentroid().x, selection[0].model.geometry.getCentroid().y);
                    lat = latLon.lat
                    lon = latLon.lon
                }
                permalink += "env=" + env + "&lon=" + lon + "&lat=" + lat + "&zoomLevel=" + zoom.toString() + "&venues=" + W.selectionManager.getSelectedFeatures()[0].model.attributes.id;
//                permalink += "env=" + env + "&lon=" + lon + "&lat=" + lat + "&zoom=" + zoom.toString() + "&venues=" + W.selectionManager.getSelectedFeatures()[0].model.attributes.id;

            } else { // code for if selection is a segment(s)
                type = 'segments'
 //               var zoomToRoadType = W.Config.segments.zoomToRoadType;
                var i;
                //To get lat and long centered on segment
                if (selection.length === 1) {
 //                   latLon = selection[0].model.getCenter().clone();
 //                   latLon.transform(W.map.olMap.projection.projCode, W.map.olMap.displayProjection.projCode);
 //                   lat = latLon.y;
 //                   lon = latLon.x;
                   latLon = selection[0].model.getCenter().clone();
                    latLon = WazeWrap.Geometry.ConvertTo4326(latLon.x,latLon.y)
                    lat = latLon.lat;
                    lon = latLon.lon;
                }
                               var zoomToRoadType = function (e)
                {
                    switch (e)
                    {
                        case 0:
                        case 1:
                            return [];
                        case 2:
                            return [2, 3, 4, 6, 7, 15];
                        case 3:
                            return [2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22];
                        case 4:
                        case 5:
                        case 6:
                        case 7:
                        case 8:
                        case 9:
                        case 10:
                        default:
                            return [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22];
                   }
                };
                for (i = 0; i < selection.length; i += 1) {
                    var segment = selection[i].model;
                    if (segment.type === "segment")
                    {
                        segIDs.push(segment.attributes.id);
                        if (zoomToRoadType(zoom) === 0 || zoomToRoadType(zoom).indexOf(segment.attributes.roadType) === -1)
                        {
                            alert("This zoom level (" + zoom.toString() + ") cannot be used for this road type! Please increase your zoom:\n" +
                                  "Streets: 4+\nOther drivable and Non-drivable: 3+\nHighways and PS: 2+");
                            SO_log("Zoom level not correct for segment: " + zoom.toString() + " " + segment.attributes.roadType.toString());
                            return;
                        }
                    }
                }
                permalink += "env=" + env + "&lon=" + lon + "&lat=" + lat + "&zoomLevel=" + zoom.toString() + "&" + type + "=" + segIDs.join();
            } // end of model.type if test
            return permalink;
        } // end of createURL function
        var mostRecentEditorDetails;
        function SO_getLastEditor(selection) {
            var editorNames = "";
            if(selection[0].model.type === "venue") {
                if(selection[0].model.attributes.residential) {
                    return mostRecentEditorDetails.userName;

                } else { // it's a venue but not an RPP
 //                   editorNameConcat(selection);
                    return mostRecentEditorDetails.userName;
                }
            } else { // it's not a venue, it's a segment or segments
                editorNameConcat(selection)
                return editorNames;
            }

            function editorNameConcat(mapObject){

                mapObject.forEach(function (selected) {
                    eID = selected.model.attributes.updatedBy;
                    if (typeof eID === "undefined" || eID < 0)
                    {
                        SO_log(`Unable to get updatedBy on ${selected.model.attributes.id}`);
                        eID = selected.model.attributes.createdBy;
                    }
                    newEdName = W.model.users.getObjectById(eID).userName;
                    if (editorNames.indexOf(newEdName) === -1) {
                        editorNames += ", " + newEdName;
                    }
                });
                editorNames = editorNames.substr(2);
                return editorNames;
            }
        }
        function SO_createFormLink(formSel) {
        var selection = W.selectionManager.getSelectedFeatures();
        var formValues = {};
        var formFields = formSel.fields;
        var formLink = formSel.url + "?entry.";
        var formArgs = [];
        if (selection.length === 0) { // || selection[0].model.type !== "segment") {
            SO_log(`Nothing selected.`);
            return;
        } else
        {
            venuesObject = obtainVenuesObject();

            checkForVenue();
        }
        function checkForVenue()
        {
            if (venuesObject === undefined)
            {
                setTimeout (function()
                            {
                               checkForVenue();
                            }, 200);
            } else
            {
                completeForm();
                return;
            }
        }

        function obtainVenuesObject()
        {
           var venueDetails;
           var segmentEditor;
           var selection = W.selectionManager.getSelectedFeatures();
           var eID;

           var recentIndex = 0;
           if(selection[0].model.type === "venue") { //&& (selection[0].model.attributes.residential)) {
  //             console.log('RPP');
               var objId = selection[0].model.attributes.id;
               var objUrl = "https://www.waze.com/Descartes/app/ElementHistory?objectType=venue&objectID=" + objId;
               venueDetails = $.ajax({
                   url:objUrl,
                   datatype: 'json',
                   success: function(data) {
                       SO_log(`Descartes API call complete`)
                   },
                   async: false
               }).responseJSON;
               console.log(venueDetails);
               var i
               var mostRecent=venueDetails.transactions.objects[0].date;
               var recentUserID=venueDetails.transactions.objects[0].userID;

               if(venueDetails.transactions.objects.length > 1)
               {
                   for (i=1; i<venueDetails.transactions.objects.length; i+=1)
                   {
                       if(venueDetails.transactions.objects[i].date > mostRecent)
                       {
                           mostRecent=venueDetails.transactions.objects[i].date;
                           recentUserID = venueDetails.transactions.objects[i].userID;
                           recentIndex = i;
                       }
                   }
               }
               var arr = venueDetails.users.objects;
               arr.forEach(function(editor,usersIndex) {
                   if(editor.id === recentUserID) {
                       mostRecentEditorDetails = arr[usersIndex]
                   }
                  });
//              recentIndex = venueDetails.users.objects.indexOf(recentUserID);
//               var mostRecentEditorName = venueDetails.users[recentIndex].userName;
               return mostRecentEditorDetails;
       } else { // the selection is of segment type
                eID = selection[0].model.attributes.updatedBy;
                if (typeof eID === "undefined") {
                    SO_log(`Unable to get updatedBy on ${selection[0].model.attributes.id}`);
                    eID = selection[0].model.attributes.createdBy;
                }

                segmentEditor = W.model.users.getObjectById(eID).userName;
                return segmentEditor;
           }
        }
        function SO_getState(selection) {
            var stateName = "",
                i;
            var venueStreetId;
            var cID;
            debugger;
            for (i = 0; i < selection.length; i += 1) {

                if(selection[0].model.type === "venue")
                {
                    venueStreetId = selection[i].model.attributes.streetID;
                    cID = W.model.streets.getObjectById(venueStreetId).cityID;
                } else
                {
                    if(W.model.streets.getObjectById(selection[i].model.attributes.primaryStreetID) !== null)
                       {
                           cID = W.model.streets.getObjectById(selection[i].model.attributes.primaryStreetID).cityID;
                       } else
                       {
                           alert('Since this is a red road, the script is unable to add the State name to the form.  Please manually add this information.');
                           return stateName;
                       }

                }
                var sID = W.model.cities.getObjectById(cID).attributes.stateID;
                var newState = W.model.states.getObjectById(sID).name;

                if (newState === "") {
                    sID = W.model.cities.getObjectById(cID).attributes.countryID;
                    newState = W.model.countries.getObjectById(sID).name;
                    SO_log("cID: " + cID);
                    SO_log("sID: " + sID);
                    SO_log("newState: " + newState);
                }

                if (stateName === "") {
                    stateName = newState;
                } else if (stateName !== newState) {
                    stateName = "";
                    break;
                }
            }
            return stateName;
        }
        function completeForm()
        {
            var edName = "";

            Object.keys(formFields).forEach(function (key, index) {
                switch (key) {

                    case "reporter":

                        formValues[key] = W.loginManager.user.userName;
                        break;
                    case "profileLink":
   debugger;
                        edName = SO_getLastEditor(selection);
                        formValues[key] = "https://www.waze.com/user/editor/" + edName;
                        break;
                    case "permalink":

                        formValues[key] = createURL(selection);
                        if (typeof formValues.permalink === "undefined") {
                            SO_log(`No permalink generated`);
                            return;
                        }
                        break;
                    case "state":
                        formValues[key] = SO_getState(selection);
                        break;

                    case "editorRank":
                        if(selection[0].model.type === 'venue')
                        {
                            formValues[key] = mostRecentEditorDetails.rank + 1;
                        } else
                        {
                            formValues[key] = W.model.users.getObjectById(eID).rank + 1;
                        }
                        break;
                    default:
                        SO_log(`Nothing defined for ${key}`);
                        break;
                }

                //Add entry to form URL, if there's something to add
                if (typeof formValues[key] !== "undefined" && formValues[key] !== "") {
                    formArgs[index] = formFields[key] + "=" + encodeURIComponent(formValues[key]);
                }
            });
        }
        formLink += formArgs.join("&entry.");

        SO_log(`${formLink}`);

            console.log('formLink: ', formLink);
        return formLink;
    }  // end of createFormLink

        var SEROutreachObserver = new MutationObserver(function (mutations) {
            mutations.forEach(function (mutation) {
                // Mutation is a NodeList and doesn't support forEach like an array
                for (var i = 0; i < mutation.addedNodes.length; i += 1) {
                    var addedNode = mutation.addedNodes[i];

                    // Only fire up if it's a node
                    if (addedNode.nodeType === Node.ELEMENT_NODE) {
                        var selectionDiv = addedNode.querySelector("div.selection");

                        if (selectionDiv) {
                            SO_addFormBtn();
                        }
                    }
                }
            });
        });
        SEROutreachObserver.observe(document.getElementById("edit-panel"), {
            childList: true,
            subtree: true
        });

        if (W.app.modeController) {
            W.app.modeController.model.bind("change:mode", function (model, modeId) {
                if (modeId === 0) {
                   SO_addUserTab();
                }
            });
        }

        // Unit switched (imperial/metric)
        if (W.prefs) {
            W.prefs.on("change:isImperial", SO_addUserTab);
        }

        if (!W.selectionManager.getSelectedFeatures) {
            W.selectionManager.getSelectedFeatures = W.selectionManager.getSelectedItems;
        }
        SO_log(`Init done`);
        return;
    } //end of SO_init

    function tabBuilder()
    {
        var $section = $("<div>");
        $section.html([
            '<div>',
            '<h2>SO_Tab</h2>',
            '<input type="checkbox" id="SO_Enabled" class="SO_SettingsCheckbox"><label for="SO_Enabled">Enable This Script</label>',
            '<hr>',
            '<hr>',
            '<div>',
            '</div>',
            '</div>'
        ].join(' '));
    } // end of tabBuilder function
    function SO_addUserTab()
    {
        SO_log(`adding tab`);
        var userInfo = document.getElementById("user-info"),
            userTabs = document.getElementById("user-tabs"),
            navTabs = userTabs.getElementsByClassName("nav-tabs"),
            tabContent = userInfo.getElementsByClassName("tab-content");
        var SOTab = document.createElement("li"),
            SOPanel = document.createElement("div"),
            SONewTabBox = document.createElement("input"),
            SONewTabLabel = document.createElement("label"),
            SOTabInfo = document.createElement("div");

        SOTab.innerHTML = '<a title="SER Outreach" href="#sidepanel-SER_Outreach" data-toggle="tab">SER Outreach</a>';
        SOPanel.id = "sidepanel-SER_Outreach";
        SOPanel.className = "tab-pane";
        SO_log(`name: ${SO_Name}, Version: ${SO_Version}`);
        SOTabInfo.innerHTML = '<b>' + SO_Name + '</b> v' + SO_Version;
        SONewTabBox.id = "SO-open-in-tab";
        SONewTabBox.type = "checkbox";
        SONewTabBox.name = "SO_open_tab";
        SONewTabLabel.innerHTML = "Open form in new tab";
        SONewTabLabel.for = "SO_open_tab";
        SOPanel.appendChild(SOTabInfo);
        SOPanel.appendChild(SONewTabBox);
        SOPanel.appendChild(SONewTabLabel);
        navTabs[0].appendChild(SOTab);
        tabContent[0].appendChild(SOPanel);
        SO_loadSettings();

    }
    function SO_loadSettings()
    {

        var SOOpenInTab = localStorage.getItem("SO-open-in-tab");
        if (SOOpenInTab === "1") {
            $("#SO-open-in-tab").trigger("click");
        }
        return;
    }

    function SO_saveSettings()
    {
        if ($("#SO-open-in-tab").prop("checked")) {
            localStorage.setItem("SO-open-in-tab", "1");
        } else {
            localStorage.setItem("SO-open-in-tab", "0");
        }
        return;
    }

})();