WME Review Edits

copies information from WME and adds to google sheet for record of reviewed edits.

// ==UserScript==
// @name         WME Review Edits
// @namespace    https://greasyfork.org/en/scripts/382070-wme-reviewedits
// @version      2021.08.26.02
// @description  copies information from WME and adds to google sheet for record of reviewed edits.
// @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 RE_Name = GM_info.script.name;
    var RE_Version = GM_info.script.version;
    var settings = {};
    var venuesObject;
    var eID;
    var rank;
    var geoOffset = 'nada';

    function RE_log(message) {
        console.log(`Review Edits: ${message}`);
    }
    function bootstrap(tries) {
        RE_log(`bootstrap`);
        tries = tries || 1;

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

    bootstrap();

    function RE_init() {
        // Check document elements are ready
        var userInfo = document.getElementById("user-info");
        var newEdName = "";
        if (userInfo === null) {
            window.setTimeout(RE_init, 500);
            return;
        }
        var userTabs = document.getElementById("user-tabs");
        if (userTabs === null) {
            window.setTimeout(RE_init, 500);
            return;
        }
        var navTab = userInfo.getElementsByTagName("ul");
        if (navTab.length === 0) {
            window.setTimeout(RE_init, 500);
            return;
        }
        if (typeof navTab[0] === "undefined") {
            window.setTimeout(RE_init, 500);
            return;
        }
        var tabContent = userInfo.getElementsByTagName("div");
        if (tabContent.length === 0) {
            window.setTimeout(RE_init, 500);
            return;
        }
        if (typeof tabContent[0] === "undefined") {
            window.setTimeout(RE_init, 500);
            return;
        }
        var editorURL = '';
        RE_addUserTab();
        RE_addFormBtn();
        function RE_addFormBtn() {
            RE_log(`adding form button`);
            var selection = W.selectionManager.getSelectedFeatures();
            var REDiv = document.createElement("div"),
                REMnu = document.createElement("select"),
                REBtn = document.createElement("button");
            var formWindowName = "Review Edits result",
                formWindowSpecs = "resizable=1,menubar=0,scrollbars=1,status=0,toolbar=0";
            var editPanel,
                selElem,
                formLink;
           REDiv.id = "reviewEditsDiv";
            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("reviewEditsDiv")) {
                //formfiller_log("Div already created");
                return;
            }

           var forms = [{
                name: "SER Editor Review",
                // testing url: "https://docs.google.com/forms/d/e/1FAIpQLSepKZpDjeHySl95eArUn5iwTuOTUPvpz0ZvqaHg7LbvmBB1Lw/viewform",
                url: "https://docs.google.com/forms/d/e/1FAIpQLSfc27FGWsN2RoX8WXYAYZ2xVIkJ1cI8u85ezV--AYsBCVuVKg/viewform",
                fields: {
                    editDate: "150500272",
                    specificPermalink: "760385393",
                    reviewingEditor: "1935699410",
                    sentToEditorPL: "325109063",
                    editorName: "343499315",
                    nameOfVenue: "418181794",
                    editorRank: "986567855"
                }
            }];

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

                if ($("#RE-open-in-tab").prop("checked")) {
                    window.open(formLink, "_blank");
                } else {
                    window.open(formLink, formWindowName, formWindowSpecs);
                }
            };
            REDiv.appendChild(REMnu);
            REDiv.appendChild(REBtn);
            selElem[0].appendChild(REDiv);

            return;
    } // end of RE_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 latOffset;
            var lonOffset;
            var zoomOffset;
            var type;
            var rank = venuesObject.rank + 1;
            geoOffset = setGeoOffset(rank);
//            zoomOffset = setZoom(rank);
            zoomOffset = 0;
            if (selection[0].model.type === "venue") {  // code for selection is a place venue
                RE_log(`Venue selected!`)
                if(selection[0].model.isPoint())

                { // get lat and lon for point place
                    RE_log(`Point Venue selected!`)
                    var latLon = WazeWrap.Geometry.ConvertTo4326(selection[0].geometry.x, selection[0].geometry.y)
                    lat = latLon.lat
                    lon = latLon.lon

                } else

                { // get lat and lon for area place
                    RE_log(`Area Venue selected!`)
                    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 + "&zoom=19&venues=" + W.selectionManager.getSelectedFeatures()[0].model.attributes.id;
                permalink += "env=" + env + "&lon=" + lon + "&lat=" + lat + "&zoomLevel=" + 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 = WazeWrap.Geometry.ConvertTo4326(latLon.x,latLon.y)
                    lat = latLon.lat;
                    lon = latLon.lon;
                }

                var zoomToRoadType = function (e) {
                    switch (e) {
                        case 12:
                        case 13:
                            return [];
                        case 14:
                            return [2, 3, 4, 6, 7, 15];
                        case 15:
                            return [2, 3, 4, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22];
                        case 16:
                        case 17:
                        case 18:
                        case 19:
                        case 20:
                        case 21:
                        case 22:
                        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: 16+\nOther drivable and Non-drivable: 15+\nHighways and PS: 14+");
                            RE_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();
 //               permalink += "env=" + env + "&lon=" + lon + "&lat=" + lat + "&zoom=7&" + type + "=" + segIDs.join();
            } // end of model.type if test
            latOffset = lat + geoOffset;
            lonOffset = lon - geoOffset;
            function setZoom(level)
            {
                switch (level)
                {
                    case 1:
                    case 2:
                        zoomOffset = 7;
                        break;
                    case 3:
                        zoomOffset = 6;
                        break;
                    case 4:
                        zoomOffset = 6;
                        break;
                    case 5:
                    case 6:
                        zoomOffset = 6;
                        break;
                }
                return zoomOffset;
            }
            function setGeoOffset(level)
            {
                // Added 1/3/20
                geoOffset = 0;
                return geoOffset;
                switch (level)
                {
                    case 1:
                    case 2 :
                        geoOffset = .003;
                        break;
                    case 3:
                        geoOffset = .004
                        break;
                    case 4:
                        geoOffset = .005
                        break;
                    case 5:
                    case 6:
                        geoOffset = .006
                        break;
                }
                return geoOffset;
            }
            var strStartURL = 'https://www.waze.com/en-US/editor?env=usa&lon=';
            var correctURL;
            var newURL;
            editorURL = strStartURL + lonOffset + '&lat=' + latOffset + '&zoomLevel=' + zoomOffset;
            return permalink;
        } // end of createURL function

        function RE_getLastEditor(selection) {
            var editorNames = "";
            if(selection[0].model.type === "venue") {
                if(selection[0].model.attributes.residential) {
                    return venuesObject.userName;

                } else { // it's a venue but not an RPP
 //                   editorNameConcat(selection);
                    return venuesObject.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") {
                        RE_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 RE_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") {
            RE_log(`Nothing selected.`);
            return;
        } else
        {
            venuesObject = obtainVenuesObject();
  //debugger;
            checkForVenue();
        }
        function checkForVenue()
        {
            if (venuesObject === undefined)
            {
                setTimeout (function()
                            {
                               checkForVenue();
                            }, 200);
            } else
            {
                completeForm();
                return;
            }
        }

        function obtainVenuesObject()
        {
           var venueEditor;
           var a;
           var selection = W.selectionManager.getSelectedFeatures();
           var eID;
           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;
               a = $.ajax({
                   url:objUrl,
                   datatype: 'json',
                   success: function(data) {
                       RE_log(`Descartes API call complete`)
                   },
                   async: false
               }).responseJSON.users.objects[0];
               console.log(a);
               return a;
            } else { // it's either a point place, area place or segment but not an RPP
                eID = selection[0].model.attributes.updatedBy;
                if (typeof eID === "undefined") {
                    RE_log(`Unable to get updatedBy on ${selection[0].model.attributes.id}`);
                    eID = selection[0].model.attributes.createdBy;
                }
                venueEditor = W.model.users.getObjectById(eID);
                return venueEditor;
           }
        }
        function completeForm()
        {
            var onePL;
            Object.keys(formFields).forEach(function (key, index) {
                switch (key) {

                    case "reviewingEditor":
                        formValues[key] = W.loginManager.user.userName;
                        break;
                    case "specificPermalink":
                    //debugger;
                        onePL = createURL(selection);
                        formValues[key] = onePL;
                        if (typeof formValues.specificPermalink === "undefined") {
                            RE_log(`No permalink generated`);
                            return;
                        }
                        break;
                    case "sentToEditorPL":
                    //debugger;
                        formValues[key] = onePL;
                        // formValues[key] = editorURL;
                        break;
                    case "editDate":
                        var a;
                        if(selection[0].model.attributes.updatedOn === undefined)
                        {
                            a = selection[0].model.attributes.createdOn;
                        } else
                        {
                            a = selection[0].model.attributes.updatedOn;
                        }
                        var b = new Date(a).toLocaleDateString();
                        formValues[key] = b;
                        break;
                    case "editorName":
                        var c = RE_getLastEditor(selection);
                        formValues[key] = c;
                        break;
                    case "nameOfVenue":
                        if(selection[0].model.type === 'venue')
                        {
                            if(selection[0].model.attributes.residential)
                            {
                                formValues[key] = 'N/A';
                            } else
                            {
                                formValues[key] = selection[0].model.attributes.name;
                            }
                        } else {
                            formValues[key] = 'N/A';
                        }
                        break;
                    case "editorRank":
                        if(selection[0].model.type === 'venue')
                        {
                            formValues[key] = venuesObject.rank + 1;
                        } else
                        {
                            formValues[key] = W.model.users.getObjectById(eID).rank + 1;
                        }
                        break;
                    default:
                        RE_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.");

        RE_log(`${formLink}`);
        return formLink;
    }  // end of createFormLink

        var reviewEditsObserver = 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) {
                            RE_addFormBtn();
                        }
                    }
                }
            });
        });
        reviewEditsObserver.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) {
                    //debugger;
                   RE_addUserTab();
                }
            });
        }

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

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

    function tabBuilder()
    {
        var $section = $("<div>");
        $section.html([
            '<div>',
            '<h2>RE_Tab</h2>',
            '<input type="checkbox" id="RE_Enabled" class="RE_SettingsCheckbox"><label for="RE_Enabled">Enable This Script</label>',
            '<hr>',
            '<hr>',
            '<div>',
            '</div>',
            '</div>'
        ].join(' '));
    } // end of tabBuilder function
    function RE_addUserTab() {
        RE_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 RETab = document.createElement("li"),
            REPanel = document.createElement("div"),
            RENewTabBox = document.createElement("input"),
            RENewTabLabel = document.createElement("label"),
            RETabInfo = document.createElement("div");

        RETab.innerHTML = '<a title="Review Edits" href="#sidepanel-reviewEdits" data-toggle="tab">Review Edits</a>';
        REPanel.id = "sidepanel-reviewEdits";
        REPanel.className = "tab-pane";
        RE_log(`name: ${RE_Name}, Version: ${RE_Version}`);
        RETabInfo.innerHTML = '<b>' + RE_Name + '</b> v' + RE_Version;
        RENewTabBox.id = "RE-open-in-tab";
        RENewTabBox.type = "checkbox";
        RENewTabBox.name = "RE_open_tab";
        RENewTabLabel.innerHTML = "Open form in new tab";
        RENewTabLabel.for = "RE_open_tab";
        REPanel.appendChild(RETabInfo);
        REPanel.appendChild(RENewTabBox);
        REPanel.appendChild(RENewTabLabel);
        navTabs[0].appendChild(RETab);
        tabContent[0].appendChild(REPanel);
        RE_loadSettings();

    }
    function RE_loadSettings() {

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

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

})();