// ==UserScript==
// @name WME Find Deleted Objects
// @namespace https://greasyfork.org/users/32336-joyriding
// @version 2022.08.13.01
// @description Attempts to show the history of a venue that has been deleted in an area.
// @author Joyriding
// @include https://beta.waze.com/*
// @include https://www.waze.com/editor*
// @include https://www.waze.com/*/editor*
// @exclude https://www.waze.com/user/editor*
// @icon data:image/png;base64,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
// @require https://greasyfork.org/scripts/24851-wazewrap/code/WazeWrap.js
// @contributionURL https://github.com/WazeDev/Thank-The-Authors
// @license GPLv3
// @grant none
// ==/UserScript==
/* global W */
/* global OpenLayers */
/* global I18n */
/* global $ */
/* global WazeWrap */
/* global require */
/* global google */
/* global Backbone */
(function() {
'use strict';
var settings = {};
var _wmeFdoFeatureLayer;
var _wmeFdoMarkerLayer;
var projection=new OpenLayers.Projection("EPSG:900913");
var displayProjection=new OpenLayers.Projection("EPSG:4326");
var requestStatus = [];
var seenVenueIds = [];
var subcategoryToParentCategories = [];
var flags = {
venue: { }
};
var externalProviderDetails = { };
var idMappings = {
users: [],
streets: [],
}
let userCache = [];
var userProgress = [];
let earliestScanDate = parseInt(new Date('2016-12-31').getTime());
let googleMapsApi = {
map: document.createElement('div'),
service: null
}
const DAY_MS = 1000 * 60 * 60 * 24;
const WEEK_MS = DAY_MS * 7;
function bootstrap(tries) {
tries = tries || 1;
if (W && W.map &&
W.model && W.loginManager.user &&
WazeWrap.Ready && $ ) {
init();
} else if (tries < 1000)
setTimeout(function () {bootstrap(tries++);}, 200);
}
function init()
{
let styleElements = getWmeStyles();
var $style = $("<style>");
$style.html([
'<style>',
'#wmeFdoStatusDate { margin-top:10px;margin-bottom:10px; }',
'.spinner-disable { opacity: 0; }',
'.wmeFdoFormInputLabel { display:inline-block;margin-right:10px;}',
'.wmeFdoFormInput { display:inline-block; width:150px;}',
'.wmeFdoButtonArea {margin-top:10px;margin-bottom:10px; }',
'.wmeFdoGoogleBtn { margin-top:10px;margin-bottom:10px; }',
'.wmeFdoRecreate a { color: #b5b5b5; cursor: pointer; text-decoration:none;}',
'.wmeFdoRecreate a:hover { text-decoration:underline; }',
'.wmeFdoResultDetail { position: relative; }',
'.wmeFdoDetailControls {position: absolute;right: 17px;top: 10px;}',
'.wmeFdoFlag a { text-decoration: none; }',
'.wmeFdoFlag { cursor:pointer; opacity:0.2; margin-right:5px;}',
'.wmeFdoFlag:hover { color:red; opacity:.75}',
'.wmeFdoFlag.flagged { color: red; opacity:1}',
'.wmeFdoHistoryContent { padding-left: 14px;padding-right: 14px; }',
'.wmeFdo-element-history-item:not(:last-child) { margin-bottom: 5px; }',
'.wmeFdo-element-history-item.closed .wmeFdo-tx-header {border-radius: 2px;background: #ededed;}',
'.wmeFdo-element-history-item.closed .wmeFdo-tx-header:hover {background: rgba(255, 255, 255, 0.5);}',
'.wmeFdo-element-history-item .wmeFdo-tx-header {display: flex;flex-direction: row; justify-content: space-between;padding: 10px;border: 1px solid #e4e4e4;border-radius: 2px 2px 0px 0px;font-size: 11px;color: #687077;line-height: 14px;background: white;transition: all 0.3s;cursor: pointer;}',
'.wmeFdo-element-history-item .wmeFdo-tx-content {display: block;padding: 10px;padding-left: 22px; background-color: white;border: 1px solid #e4e4e4;border-top: none; font-size: 11px;}',
'.wmeFdo-element-history-item.closed .wmeFdo-tx-content {display: none;}',
'.wmeFdo-element-history-item.wmeFdo-tx-has-related .wmeFdo-tx-changed-attribute:last-child {margin-bottom: 10px;}',
'.wmeFdo-element-history-item.wmeFdo-tx-has-related .wmeFdo-tx-changed-attribute:last-child { margin-bottom: 10px;}',
'.wmeFdo-element-history-item .tx-toggle-closed {width: 30px;height: 30px;text-align: center;}',
'.wmeFdo-element-history-item:not(.tx-has-content) .tx-content, .element-history-item:not(.tx-has-content) .tx-toggle-closed {display: none;}',
'.wmeFdo-element-history-item .tx-toggle-closed {width: 30px;height: 30px;text-align: center;}',
'.wmeFdo-element-history-item.closed .wmeFdo-tx-toggle-closed::after { content: "\\F107";top: 8px;}',
'.wmeFdo-element-history-item .wmeFdo-tx-toggle-closed::after {display: inline-block;font: normal normal normal 14px/1 FontAwesome;font-size: inherit;text-rendering: auto;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;color: #3d3d3d;display: block;position: relative;top: 8px;content: "\\F106";font-size: 19px;}',
'.historySummaryItem { margin-left:10px; color:#a7a7a7; }',
'.historySummaryItem a, .historySummaryItem a:visited { color:#a7a7a7; }',
'.wmeFdo-place-delete { filter: saturate(17) hue-rotate(65deg); }',
'.wmeFdo-place-delete:hover { filter: brightness(110%) saturate(17) hue-rotate(65deg) !important; }',
'.wmeFdo-place-delete:after {',
'border-top: 3px solid #ffffff;',
'width: 69%;',
'height: 49%;',
'position: absolute;',
'bottom: 6px;',
'left: 8px;',
'content: "";',
'transform: rotate(-45deg);',
'}',
'#wmeFdoSubTabs, .wmeFdoFlag { display: none!important; }',
'.wmeFdoResultTypeVenue { opacity:0.5; margin-left:-3px;margin-right:5px;position:relative;top:3px;' + styleElements.resultTypeVenueStyle + '}',
'.wmeFdoResultTypeCamera { opacity:0.5; margin-left:-3px;margin-right:5px;position:relative;top:3px;' + styleElements.resultTypeCameraStyle + '}',
'.wmeFdoResultTypeArea { opacity:0.5; margin-left:-3px;margin-right:5px;position:relative;top:10px;' + styleElements.resultTypeAreaStyle + '}',
// '.wmeFdoResultTypeResidential { opacity:0.65; margin-left:-3px;margin-right:5px;position:relative;top:4px;' + styleElements.resultTypeResidentialNew + '}',
// '.wmeFdoResultTypeParking { opacity:0.65; margin-left:-1px;margin-right:3px;margin-bottom:6px;position:relative;top:4px;filter: saturate(0%);' + styleElements.resultTypeParkingNew + '}',
'.wmeFdoResultTypeResidential { filter:invert(.35); margin-left:-11px;margin-right:-1px;position:relative;top:-6px;' + styleElements.resultTypeResidentialNew + '}',
'.wmeFdoResultTypeParking { filter:invert(.35); margin-left:-11px;margin-right:-1px;position:relative;top:-6px;' + styleElements.resultTypeParkingNew + '}',
'.wmeFdoResultDeletedNewPlace:after { position:relative;content:"+";color:black;font-size:17px;font-weight:900;text-shadow: 0px 0px 2px white;top:7px;left:8px; }',
'.wmeFdoResultDeletedNewPlaceAlt:after { position:relative;content:"+";color:black;font-size:17px;font-weight:900;top:14px;left:20px; }',
'.wmeFdoResultDeletedFromRequest:after { position:relative;content:"\\002b06";color:black;font-size:13px;font-weight:900;text-shadow: 0px 0px 3px white;top:7px;left:8px; }',
'.wmeFdoResultDeletedFromRequestAlt:after { position:relative;content:"\\002b06";color:black;font-size:13px;font-weight:900;top:14px;left:20px;opacity: .8; }',
'.wmeFdoIconFilter { transform:rotate(90deg);margin-left:-1px;margin-right:3px;margin-bottom:6px;position:relative;top:4px;filter: saturate(0%);' + styleElements.iconFilter + '}',
//'.wmeFdoIconFilterInline { font-size:15px;margin-top:5px; }',
'.wmeFdoIconFilterInline:before { transform:rotate(90deg);filter:saturate(0%);content:"";position:relative;display:inline-block;top:3px;margin-right:10px;' + styleElements.iconFilter + '}',
'.wmeFdoScanAttributesDropdown { font-size:15px;margin-top:5px; }',
'.wmeFdoScanAttributesLabel { margin-left:10px; }',
'#wmeFdoStatusUsersList > li { margin-bottom:10px }',
'.wmeFdoStatusUserDates { width:200px; }',
'.wmeFdoStatusUserLatest { float:left; }',
'.wmeFdoStatusUserEarliest { float:right; }',
'.wmeFdoProgress {width:200px;height:5px;border:1px solid gray;border-radius:3px; }',
'#wmeFdoScanStatusHeader .wmeFdoProgress { margin-top: 5px;margin-left: 27px; }',
'.wmeFdoComplete { width:0%;height:4px;background-color:#5a7990; }',
'.wmeFdoProgressIcon { transform: scale(1.3,-1) rotate(90deg); }',
'.wmeFdoDropdownHeader { width: 80%; }',
'#wmeFdoStatusSummary { margin-bottom:10px; }',
'.wmeFdoHistorySummaryList > li { margin-bottom:2px; }',
'</style>'
].join(' '));
var $section = $('<div id="wmeFdoPanel">');
$section.html(
'<div id="wmeFdoHead">',
'</div>'
);
var $navTabs = $('<ul id="wmeFdoSubTabs" class="nav nav-tabs"><li class="active"><a data-toggle="tab" href="#wmeFdoTabFind">Find</a></li>' +
'<li><a data-toggle="tab" href="#wmeFdoTabFlagged" id="wmeFdoTabFlagEvent">Flagged</a></li>' +
'<li><a data-toggle="tab" href="#wmeFdoTabSettings"><span class="fa fa-gear"></span></a></li></ul>');
var $tabContent = $('<div class="tab-content" style="padding:5px;">');
var $fdoTabFind = $('<div id="wmeFdoTabFind" class="tab-pane active">');
$fdoTabFind.append([
'<h4 style="margin-top:0px;">Find Deleted Objects</h4>',
'<h6 style="margin-top:0px;">' + GM_info.script.version + '</h6>'
].join(' '));
createSettingsCheckbox($fdoTabFind, 'wmeFdoNearbyEditors','Nearby Editors');
$fdoTabFind.append([
'<div class="controls-container" style="padding-top: 2px;"><div class="wmeFdoFormInputLabel">Editor Name</div><input type="text" id="wmeFdoEditorName" class="form-control wmeFdoFormInput"><label for="wmeFdoEditorName"></label></div><br>',
].join(' '));
createSettingsCheckbox($fdoTabFind, 'wmeFdoIncludeSelf','Include Deletes By This Editor');
createSettingsCheckbox($fdoTabFind, 'wmeFdoLimitToScreen','Limit to Screen');
$fdoTabFind.append([
'<div class="controls-container" style="padding-top: 2px;"><div class="wmeFdoFormInputLabel">Find Prior To</div><input type="text" id="wmeFdoFindDate" class="form-control wmeFdoFormInput"><label for="wmeFdoFindDate"></label></div><br>',
].join(' '));
var $fdoTabFlagged = $('<div id="wmeFdoTabFlagged" class="tab-pane">');
$fdoTabFlagged.html('<h4>Flagged Objects<h4>');
let $fdoTabFlaggedResults = $('<div id="wmeFdoFlaggedResults>');
$fdoTabFlagged.append($fdoTabFlaggedResults);
var $fdoTabSettings = $('<div id="wmeFdoTabSettings" class="tab-pane">');
$fdoTabSettings.append([
'<h4>Settings</h4>',
'<div id="wmeFdoSettings">',
'<div class="controls-container" style="padding-top: 2px;">Rate Limit Delay: <input type="text" id="wmeFdoRateLimitDelay" ><label for="wmeFdoRateLimitDelay"></label></div>',
'</div>'
].join(' '));
$('#wmeFdoTabSettings').append('div').append('Reset Settings');
$tabContent.append($fdoTabFind,$fdoTabFlagged,$fdoTabSettings);
$section.append($navTabs, $tabContent);
$section.append($style);
let updateDesc = "<style>#wmeFdoUpdate > li {margin-top:6px;margin-left: -22px;}</style>This update addresses most known issues of the initial release:"
+ "<ul id='wmeFdoUpdate'>"
+ "<li><b>Better Rate Limiting</b><br>Completely rewritten API request layer.</li>"
+ "<li><b>Recreate Places</b><br>External Providers can now be added from Prod WME.</li>"
+ "<li><b>New Status Display</b><br>Shows the list of nearby editors used and the current progress. Completed scans now show correctly.</li>"
+ "<li><b>Filtering</b><br> </li>"
+ "<li><b>Result Type Icons</b><br>Different icons for Parking and Residential places</li>"
+ "</ul>"
+ "<span style='color:red'>Reminder that this is an SM+ script!</span>";
updateDesc = 'Fixes browser freeze when starting a scan.<br><br>';
//WazeWrap.Interface.ShowScriptUpdate("Find Deleted Objects", GM_info.script.version, updateDesc, "https://greasyfork.org/scripts/376861-wme-find-deleted-objects", "https://www.waze.com/forum/viewtopic.php?f=1286&t=275164&p=1922116#p1922116");
new WazeWrap.Interface.Tab('FiDO', $section.html(), initializeSettings);
prepareTab();
WazeWrap.Interface.AddLayerCheckbox("display", "Deleted Objects", settings.Enabled, onLayerCheckboxChanged);
onLayerCheckboxChanged(settings.Enabled);
buildFilterSection('#wmeFdoTabFind');
let buttons = document.createElement('div');
buttons.className = 'wmeFdoButtonArea';
$('#wmeFdoTabFind').append(buttons);
var findButton = document.createElement('button');
findButton.id = 'wmeFdoFindButton';
findButton.textContent = 'Start Scan';
findButton.className = 'btn btn-success center-block';
buttons.append(findButton);
var cancelButton = document.createElement('button');
cancelButton.id = 'wmeFdoCancelButton';
cancelButton.textContent = 'Cancel Scan';
cancelButton.className = 'btn btn-warning center-block hidden';
buttons.append(cancelButton);
findButton.addEventListener('click', function() {
findButton.className = 'btn btn-success center-block hidden';
cancelButton.className = 'btn btn-danger center-block ';
let tab = document.getElementById('wmeFdoTab');
tab.innerHTML = 'FiDO <span class="spinner-enable"><i class="icon-spinner icon-spin fa fa-spinner fa-spin"></i></span>';
$('#wmeFdoTabFind').data("status","running");
settings.Enabled = true;
onLayerCheckboxChanged(settings.Enabled); // TODO: Fix this so the Layer menu checkbox gets updated
clearResults();
beginScanNew();
findObjects();
});
cancelButton.addEventListener('click', function() {
cancelButton.textContent = 'Cancelling...';
cancelButton.className = 'btn btn-warning center-block disabled';
$('#wmeFdoTabFind').data("status","cancelled");
let tab = document.getElementById('wmeFdoTab');
tab.innerHTML = 'FiDO <span class="spinner-disable"><i class="icon-spinner icon-spin fa fa-spinner fa-spin"></i></span>';
cancelScanNew();
cancelScan(0);
});
$("#wmeFdoEditorName").keyup(function(event) {
if (event.keyCode === 13) {
$("#wmeFdoFindButton").click();
}
});
$("#wmeFdoFindDate").keyup(function(event) {
if (event.keyCode === 13) {
$("#wmeFdoFindButton").click();
}
});
$('#wmeFdoNearbyEditors').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
if(this.checked)
{
$("#wmeFdoEditorName").prop('disabled', true);
$("#wmeFdoIncludeSelf").prop('disabled', true);
$("#wmeFdoLimitToScreen").prop('disabled', true);
}
else
{
$("#wmeFdoEditorName").prop('disabled', false);
$("#wmeFdoIncludeSelf").prop('disabled', false);
$("#wmeFdoLimitToScreen").prop('disabled', false);
}
});
let flaggedTab = document.getElementById('wmeFdoTabFlagEvent');
flaggedTab.addEventListener('click', function() {
let flagList = '';
for (var id in flags.venue) {
flagList = flagList + id + '<br>';
console.log(id);
}
let results = document.getElementById('wmeFdoTabFlagged');
results.append(flagList);
});
var $usersDiv = $( '<div id="fdoUsersPanel"></div>');
//var dateSpan = document.createElement('div');
//dateSpan.id = 'wmeFdoStatusDate';
//$('#wmeFdoTabFind').append(dateSpan);
let inputDate = document.getElementById('wmeFdoFindDate');
inputDate.value = formatCurrentDate();
$('#wmeFdoTabFind').append(buildResultsPanel());
console.log($('#wmeFdoFilterResidential')[0].id);
$('#wmeFdoFilterResidential').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
applyFiltersToResults();
});
$('#wmeFdoFilterParkingLot').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
applyFiltersToResults();
});
$('#wmeFdoFilterAnyType').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
applyFiltersToResults();
});
$('#wmeFdoFilterNewRejected').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
applyFiltersToResults();
});
$('#wmeFdoFilterDeleteRequest').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
applyFiltersToResults();
});
initializeSettings();
console.log('FiDO: done');
}
function initializeSettings()
{
loadSettings();
setChecked('wmeFdoIncludeSelf', settings.IncludeSelf);
setChecked('wmeFdoLimitToScreen', settings.LimitToScreen);
setChecked('wmeFdoNearbyEditors', settings.NearbyEditors);
setChecked('wmeFdoFilterResidential', settings.FilterResidential);
setChecked('wmeFdoFilterParkingLot', settings.FilterParkingLot);
setChecked('wmeFdoFilterAnyType', settings.FilterAnyType);
setChecked('wmeFdoFilterNewRejected', settings.FilterNewRejected);
setChecked('wmeFdoFilterDeleteRequest', settings.FilterDeleteRequest);
// if(settings.Enabled)
// W.selectionManager.events.register("selectionchanged", null, drawSelection);
$('.wmeFdoSettingsCheckbox').change(function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = this.checked;
saveSettings();
if(this.checked)
{
// W.selectionManager.events.register("selectionchanged", null, drawSelection);
// processVenues(W.model.venues.getObjectArray());
}
else
{
// W.selectionManager.events.unregister("selectionchanged", null, drawSelection);
// wmeFdoSelectedLayer.removeAllFeatures();
// processVenues(W.model.venues.getObjectArray());
}
});
if(settings.NearbyEditors)
{
$("#wmeFdoEditorName").prop('disabled', true);
$("#wmeFdoIncludeSelf").prop('disabled', true);
$("#wmeFdoLimitToScreen").prop('disabled', true);
}
else
{
$("#wmeFdoEditorName").prop('disabled', false);
$("#wmeFdoIncludeSelf").prop('disabled', false);
$("#wmeFdoLimitToScreen").prop('disabled', false);
}
$('.wmeFdoSettingsText').on('input propertychange paste', function() {
var settingName = $(this)[0].id.substr(6);
settings[settingName] = parseInt($(this).val());
saveSettings();
//W.selectionManager.events.unregister("selectionchanged", null, drawSelection);
//processVenues(W.model.venues.getObjectArray());
});
}
function getWmeStyles() {
// Get the sprite icons from the native WME CSS so that we can use our own document structure
let styleElements = { };
let $tempDiv = null;
let tempQuerySelector = null;
let tempComputedStyle = null;
//.form-search .search-result-region .search-result .icon {
//background-image: url(//editor-assets.waze.com/production/img/toolbare2f6b31….png);
$tempDiv = $('<div class="form-search">').append($('<div class="search-result-region">').append($('<div class="search-result">').append($('<div class="icon">'))));
$('body').append($tempDiv);
tempQuerySelector = document.querySelector('.form-search .search-result-region .search-result .icon');
tempComputedStyle = window.getComputedStyle(tempQuerySelector);
styleElements.resultTypeVenueStyle =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
$tempDiv.remove();
//#edit-buttons .camera .item-icon::after {
//background-image: url(//editor-assets.waze.com/production/img/toolbare2f6b31….png);
tempQuerySelector = document.querySelector("#primary-toolbar > div > div.toolbar-group.toolbar-group-drawing > wz-menu > div > wz-menu-item.toolbar-group-item.camera.WazeControlDrawFeature > div > div.item-icon");
tempComputedStyle = window.getComputedStyle(tempQuerySelector,'::after');
styleElements.resultTypeCameraStyle =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
//#edit-buttons .toolbar-group .toolbar-group-item .drawing-controls .drawing-control.polygon:after {
//background-image: url(//editor-assets.waze.com/production/img/toolbare2f6b31….png);
tempQuerySelector = document.querySelector("#primary-toolbar > div > div.toolbar-group.toolbar-group-venues > wz-menu > div > wz-menu-item.toolbar-group-item.car-services.WazeControlDrawFeature > div > div.drawing-controls > wz-basic-tooltip:nth-child(2) > wz-tooltip > wz-tooltip-source > wz-button").shadowRoot.querySelector("button")
tempComputedStyle = window.getComputedStyle(tempQuerySelector,'::after');
styleElements.resultTypeAreaStyle =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
// .toolbar .toolbar-button.add-house-number .item-icon {
//background-image: url(//editor-assets.waze.com/production/img/toolbarcad3e90….png);
//$tempDiv = $('<div class="toolbar">').append($('<div class="toolbar-button add-house-number">').append($('<div class="item-icon">')));
//$('body').append($tempDiv);
//tempQuerySelector = document.querySelector('.toolbar .toolbar-button.add-house-number .item-icon');
//tempComputedStyle = window.getComputedStyle(tempQuerySelector);
//styleElements.resultTypeResidential = `background-image:${tempComputedStyle.getPropertyValue('background-image')};`
// + `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
// + `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
// + `width:${tempComputedStyle.getPropertyValue('width')};`
// + `height:${tempComputedStyle.getPropertyValue('height')};`;
//$tempDiv.remove();
//#edit-buttons .parking-lot .item-icon::after {
//background-image: url(//editor-assets.waze.com/production/img/toolbarcad3e90….png);
//tempQuerySelector = document.querySelector('#edit-buttons .parking-lot .item-icon');
//tempComputedStyle = window.getComputedStyle(tempQuerySelector,'::after');
//styleElements.resultTypeParking = `background-image:${tempComputedStyle.getPropertyValue('background-image')};`
// + `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
// + `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
// + `width:${tempComputedStyle.getPropertyValue('width')};`
// + `height:${tempComputedStyle.getPropertyValue('height')};`;
//#edit-panel .merge-landmarks .merge-item .do-merge:before, .edit-panel .merge-landmarks .merge-item .do-merge:before {
//background-image: url(//editor-assets.waze.com/production/img/buttons756c103….png);
$tempDiv = $('<div id="edit-panel">').append($('<div class="merge-landmarks">').append($('<div class="merge-item">').append($('<div class="do-merge">'))));
$('body').append($tempDiv);
tempQuerySelector = document.querySelector('#edit-panel .merge-landmarks .merge-item .do-merge');
tempComputedStyle = window.getComputedStyle(tempQuerySelector, '::before');
styleElements.iconFilter =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
$tempDiv.remove();
//#edit-panel .merge-landmarks .merge-item .icon.parking_lot:after
$tempDiv = $('<div id="edit-panel">').append($('<div class="merge-landmarks">').append($('<div class="merge-item">').append($('<div class="icon parking_lot">'))));
$('body').append($tempDiv);
tempQuerySelector = document.querySelector('#edit-panel .merge-landmarks .merge-item .icon.parking_lot');
tempComputedStyle = window.getComputedStyle(tempQuerySelector, '::after');
styleElements.resultTypeParkingNew =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
$tempDiv.remove();
//#edit-panel .merge-landmarks .merge-item .icon.parking_lot:after
$tempDiv = $('<div id="edit-panel">').append($('<div class="merge-landmarks">').append($('<div class="merge-item">').append($('<div class="icon residential_home">'))));
$('body').append($tempDiv);
tempQuerySelector = document.querySelector('#edit-panel .merge-landmarks .merge-item .icon.residential_home');
tempComputedStyle = window.getComputedStyle(tempQuerySelector, '::after');
styleElements.resultTypeResidentialNew =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
$tempDiv.remove();
return styleElements;
}
function getWmeStyle(selector) {
let $tempDiv = null;
let tempQuerySelector = null;
let tempComputedStyle = null;
let returnedStyle = null;
//.form-search .search-result-region .search-result .icon {
//background-image: url(//editor-assets.waze.com/production/img/toolbare2f6b31….png);
$tempDiv = $('<div class="form-search">').append($('<div class="search-result-region">').append($('<div class="search-result">').append($('<div class="icon">'))));
$('body').append($tempDiv);
tempQuerySelector = document.querySelector('.form-search .search-result-region .search-result .icon');
tempComputedStyle = window.getComputedStyle(tempQuerySelector);
returnedStyle =
`background-image:${tempComputedStyle.getPropertyValue('background-image')};`
+ `background-size:${tempComputedStyle.getPropertyValue('background-size')};`
+ `background-position:${tempComputedStyle.getPropertyValue('background-position')};`
+ `width:${tempComputedStyle.getPropertyValue('width')};`
+ `height:${tempComputedStyle.getPropertyValue('height')};`;
$tempDiv.remove();
return returnedStyle;
}
//historyContent
//element-history-item
function buildResultsPanel() {
return $('<div id="fdoResultsPanel">')
.append($('<div class="elementHistoryContainer">')
.append($('<div class="wmeFdoHistoryContent">')
.append($('<div class="transactions">')
.append($('<ul id="wmeFdoTransactionList">'))
)
)
);
}
function buildFilterSection(parentDivName) {
let $section = $('<div id="wmeFdoFilterSection">')
.append($('<div class="elementHistoryContainer">')
.append($('<div class="wmeFdoHistoryContent">')
.append($('<div class="transactions">')
.append($('<ul id="wmeFdoFilter">')
.append($('<li id="wmeFdoFilterDetails" class="wmeFdo-element-history-item wmeFdo-tx-has-content wmeFdo-tx-has-related closed">')
.append($('<div id="wmeFdoFilterDetailsHeader" class="wmeFdo-tx-header">')
// .append($('<div class="flex-noshrink wmeFdoIconFilter">')
// )
//.append($('<div class="flex-noshrink">'))
.append($('<div class="wmeFdo-tx-summary wmeFdoDropdownHeader">')
.append($('<div class="wmeFdoIconFilterInline wmeFdoScanAttributesDropdown">Filter Results</div>'))
)
.append($('<div class="flex-noshrink wmeFdo-tx-toggle-closed">')
)
)
.append($('<div class="wmeFdo-tx-content">')
.append($('<div id="wmeFdoFilterDetailsUsers">'))
.append($('<div id="wmeFdoFilterDetailsPlaces">'))
.append($('<div id="wmeFdoFilterDetailsCameras">')) //<ul><li class="tx-changed-attribute">'))
)
)
.append($('<li id="wmeFdoScanStatus" class="wmeFdo-element-history-item wmeFdo-tx-has-content wmeFdo-tx-has-related closed">')
.append($('<div id="wmeFdoScanStatusHeader" class="wmeFdo-tx-header">')
//.append($('<div class="flex-noshrink">'))
.append($('<div class="wmeFdo-tx-summary wmeFdoDropdownHeader">')
.append($('<div class="wmeFdoScanAttributesDropdown">')
.append($('<i class="fa fa-bar-chart wmeFdoProgressIcon" aria-hidden="true"></i>')
).append($('<span class="wmeFdoScanAttributesLabel"><span id="wmeFdoScanCurrentStatus">Status</span></span>'))
).append($('<div class="wmeFdoProgress hidden"><div class="wmeFdoComplete"></div></div>')
))
.append($('<div class="flex-noshrink wmeFdo-tx-toggle-closed">')
)
)
.append($('<div class="wmeFdo-tx-content">')
.append($('<div id="wmeFdoStatusSummary">')
.append($('<div><span>Total Requests: </span><span id="wmeFdoRequests">0<span></div>'))
.append($('<div><span>Requests per second: </span><span id="wmeFdoRequestsPerSecond">0<span></div>'))
)
.append($('<div id="wmeFdoStatusUsers">')
.append($('<ul id="wmeFdoStatusUsersList">')
))
)
)
)
)
)
);
let $parentDiv = $(parentDivName);
$parentDiv.append($section);
// $('#wmeFdoFilterDetailsUsers').append([
// '<div class="controls-container" style="padding-top: 2px;"><div class="wmeFdoFormInputLabel">Editor Name</div><input type="text" id="wmeFdoFilterEditorName" class="form-control wmeFdoFormInput"><label for="wmeFdoFilterEditorName"></label></div><br>',
// ].join(' '));
let $placeTypes = $('<ul>');
let $placeTypeLi = $('<li class="tx-changed-attribute">');
$placeTypes.append($placeTypeLi);
$('#wmeFdoFilterDetailsPlaces').append($placeTypes);
$placeTypeLi.append(['<div class="ca-name">Place Types</div>'].join(' '));
createSettingsCheckbox($placeTypeLi, 'wmeFdoFilterResidential','Residential');
createSettingsCheckbox($placeTypeLi, 'wmeFdoFilterParkingLot','Parking Lots');
createSettingsCheckbox($placeTypeLi, 'wmeFdoFilterAnyType','All Other Types');
let $purTypes = $('<ul>');
let $purTypeLi = $('<li class="tx-changed-attribute">');
$purTypes.append($purTypeLi);
$('#wmeFdoFilterDetailsPlaces').append($purTypes);
$purTypeLi.append(['<div class="ca-name">Deleted From PUR</div>'].join(' '));
createSettingsCheckbox($purTypeLi, 'wmeFdoFilterNewRejected','New Place Rejected PUR');
createSettingsCheckbox($purTypeLi, 'wmeFdoFilterDeleteRequest','Existing Place Delete Request');
// $('#wmeFdoFilterDetailsPlaces').append([
// '<div class="controls-container" style="padding-top: 2px;"><div class="wmeFdoFormInputLabel">Place Name</div><input type="text" id="wmeFdoFilterPlaceName" class="form-control wmeFdoFormInput"><label for="wmeFdoFilterPlaceName"></label></div><br>',
// ].join(' '));
document.getElementById('wmeFdoFilterDetailsHeader').onclick = function () {
toggleFilterDropDown();
}
document.getElementById('wmeFdoScanStatusHeader').onclick = function () {
toggleScanStatusDropDown();
}
}
function onLayerCheckboxChanged(checked) {
settings.Enabled = checked;
if (settings.Enabled && _wmeFdoFeatureLayer != undefined) {
_wmeFdoFeatureLayer.setVisibility(true);
_wmeFdoMarkerLayer.setVisibility(true);
} else if (_wmeFdoFeatureLayer != undefined) {
_wmeFdoFeatureLayer.setVisibility(false);
_wmeFdoMarkerLayer.setVisibility(false);
}
saveSettings();
}
function clearResults() {
if (_wmeFdoFeatureLayer != undefined) {
_wmeFdoFeatureLayer.removeAllFeatures();
_wmeFdoMarkerLayer.clearMarkers();
}
apiEndpointWazeCom = {};
userProgress = [];
userCache = [];
seenVenueIds = [];
requestStatus = {};
document.getElementById('wmeFdoTransactionList').innerHTML = '';
$('#wmeFdoStatusUsersList').empty();
$('#wmeFdoScanStatusHeader .wmeFdoProgress .wmeFdoComplete').css('width','0%');
}
function cancelScan(tries) {
//TODO: Move rest of cancel code into here
tries = tries || 1;
//console.log('incomplete: ' + incompleteRequestCount());
if (incompleteRequestCount() > 0 && tries < 10) {
console.log('Cancel requested, waiting for ' + incompleteRequestCount() + ' requests to complete');
setTimeout(function () {cancelScan(tries++);}, 500);
} else {
// TODO: Change button to Start Scan
let findButton = document.getElementById('wmeFdoFindButton');
let cancelButton = document.getElementById('wmeFdoCancelButton');
findButton.className = 'btn btn-success center-block';
cancelButton.className = 'btn btn-warning center-block hidden';
cancelButton.textContent = 'Cancel Scan';
//$('#wmeFdoStatusDate')[0].innerText = 'Scan Cancelled';
console.log('Cancelled');
}
}
function incompleteRequestCount() {
let incompleteCount = 0;
let failedCount = 0;
Object.keys(requestStatus).forEach(function (url) {
if (requestStatus[url].status != 'successful') {
if (Date.now() - requestStatus[url].lastAttempt < 10000) {
incompleteCount++;
} else {
failedCount++;
}
}
});
return incompleteCount;
}
function defaultRequestStatus() {
return {
status: 'initial',
attempts: 0,
lastAttempt: null
};
}
function requestParams(url) {
return {
url: url,
iteration: 0,
nextTransactionDate: null,
initiated: Date.now()
}
}
async function beginFind(lookFor, transactionLookup) {
// var findCenterPoint = new OL.Geometry.Point(lookFor.locationCenter.coordinates[0], lookFor.locationCenter.coordinates[1]).transform(W.map.displayProjection, W.map.projection);
if ( $('#wmeFdoTabFind').data("status") == "running"
&& transactionLookup.iteration < transactionLookup.maxIterations
)
{
transactionLookup.iteration++;
let requestParamsTransactions = requestParams(getApiUrlTransactions(transactionLookup.userId, transactionLookup.nextTransactionDate));
requestStatus[requestParamsTransactions.url] = defaultRequestStatus();
apiEndpointWazeCom.requests.push(requestParamsTransactions);
getEndpointResult(apiEndpointWazeCom, requestParamsTransactions, data => {
if (apiEndpointWazeCom.isRunning) {
if (typeof(data) == 'undefined') {
console.log('Request failed.');
}
transactionLookup.nextTransactionDate = data.nextTransactionDate
let nextDate = 'Complete';
if (data.nextTransactionDate != null)
{
nextDate = uuidToDate(data.nextTransactionDate);
//$('#wmeFdoStatusDate')[0].innerText = 'Scanning thru ' + nextDate + '...';
$('#wmeFdoScanCurrentStatus')[0].innerText = 'Scanning...';
}
var transactionCount = 0;
data.transactions.forEach(function(transaction) {
transaction.operations.forEach(async function(operation) {
if (operation.objectType == lookFor.objectType || operation.objectType == 'Camera')
{
transactionCount++;
var operationCenterPoint = new OpenLayers.Geometry.Point(operation.objectCentroid.coordinates[0], operation.objectCentroid.coordinates[1]).transform(displayProjection, projection);
//var distance = operationCenterPoint.distanceTo(findCenterPoint);
//if (distance < 1000)
if (!lookFor.limitToScreen || lookFor.searchArea.containsPoint(operationCenterPoint))
{
if (operation.objectType == 'Camera') {
console.log('camera: ' + operation.objectID);
} else {
if (!seenVenueIds.includes(operation.objectID))
{
getDeletedItemsVenue(operation, transactionLookup, lookFor, operationCenterPoint);
} //else { console.log('already seen: ' + operation.objectID); }
}
}
}
});
});
let earliestDate = userCache[transactionLookup.userId].earliestDate - DAY_MS;
let statusDate = 0;
let pctComplete = 100;
if (transactionLookup.nextTransactionDate != null) {
statusDate = uuidToUnixTime(transactionLookup.nextTransactionDate);
let latestDate = userCache[transactionLookup.userId].latestDate + DAY_MS;
//let earliestDate = userCache[transactionLookup.userId].earliestDate - DAY_MS;
let next = uuidToDate(transactionLookup.nextTransactionDate);
let totalTime = latestDate - earliestDate;
let progressTime = latestDate - statusDate;
pctComplete = (progressTime / totalTime) * 100;
// pctComplete = 100 - pctComplete;
let newCompletedMs = userCache[transactionLookup.userId].previousDate - statusDate;
apiEndpointWazeCom.progress.completeMs += newCompletedMs;
userCache[transactionLookup.userId].completeMs += newCompletedMs;
}
if (transactionLookup.nextTransactionDate == null || statusDate < earliestDate) {
apiEndpointWazeCom.users.complete++;
apiEndpointWazeCom.progress.completeMs -= userCache[transactionLookup.userId].completeMs;
apiEndpointWazeCom.progress.completeMs += userCache[transactionLookup.userId].totalMs;
updateStatusUser(transactionLookup.userId, 'Complete');
$('#wmeFdoStatusUser-' + transactionLookup.userId + ' .wmeFdoProgress .wmeFdoComplete').css('width','100%');
endScan("Scanning...", false);
} else {
updateStatusUser(transactionLookup.userId, uuidToDate(transactionLookup.nextTransactionDate));
$('#wmeFdoStatusUser-' + transactionLookup.userId + ' .wmeFdoProgress .wmeFdoComplete').css('width',pctComplete + '%');
userCache[transactionLookup.userId].previousDate = statusDate;
beginFind(lookFor, transactionLookup);
}
}
});
} else {
if (transactionLookup.iteration >= transactionLookup.maxIterations)
{
endScan("Transaction Limit Exceeded", false);
}
}
}
function updateStatusUser(userID, status) {
$('#wmeFdoStatusUser-' + userID + ' .wmeFdoStatusUser').text(status);
let pctComplete = (apiEndpointWazeCom.progress.completeMs / apiEndpointWazeCom.progress.totalMs) * 100;
if (status == 'Complete') {
$('#wmeFdoStatusUser-' + userID).appendTo('#wmeFdoStatusUsersList');
userCache[userID].completeMs = userCache[userID].totalMs;
//pctComplete = 100;
}
$('#wmeFdoScanStatusHeader .wmeFdoProgress .wmeFdoComplete').css('width',pctComplete + '%');
}
async function getDeletedItemsVenue(operation, transactionLookup, lookFor, operationCenterPoint) {
//console.log('element history for ' + data.nextTransactionDate);
let requestParamsElementHistory = requestParams(getApiUrlElementHistory('venue', operation.objectID, null));
requestStatus[requestParamsElementHistory.url] = defaultRequestStatus();
apiEndpointWazeCom.requests.push(requestParamsElementHistory);
getEndpointResult(apiEndpointWazeCom, requestParamsElementHistory, venueHistory => {
if (apiEndpointWazeCom.isRunning) {
venueHistory.transactions.objects.forEach(function(venueTransaction) {
venueTransaction.objects.forEach(function(venueAction) {
if (venueAction.actionType == 'DELETE') {
// console.log(venueAction);
if (venueAction.objectType == 'venue' && venueAction.oldValue != null)
{
let selfDelete = false;
if (transactionLookup.userId == venueTransaction.userID) {
selfDelete = true;
}
if (lookFor.includeSelf || !selfDelete) {
// Skip if searching for editor who deleted it
if (!seenVenueIds.includes(venueAction.objectID))
{
seenVenueIds.push(venueAction.objectID);
let historySummary = getVenueHistory(venueHistory);
var record = document.createElement('div');
record.id=venueTransaction.transactionID;
let username = null;
venueHistory.users.objects.forEach( function(user) {
if (user.id == venueTransaction.userID) {
let userRank = user.rank + 1;
username = user.userName + '(' + userRank + ')';
}
});
record.innerText = username + ": " + venueAction.oldValue.name + " - " + venueAction.objectID;
var details = document.createElement('li');
details.id = 'entry-' + venueAction.objectID;
details.className = 'wmeFdo-element-history-item wmeFdo-tx-has-content wmeFdo-tx-has-related closed';
var txHeader = document.createElement('div');
txHeader.className = 'wmeFdo-tx-header';
let detailsDisplayedOnce = false;
txHeader.onclick = function () {
if (!detailsDisplayedOnce && details.classList.contains('closed')) {
detailsDisplayedOnce = true;
displayExternalProviders(venueAction.objectID, venueItem.externalProviderIDs);
}
toggleDetailsDropDown(details.id, operationCenterPoint);
};
var txTypeDiv = document.createElement('div');
txTypeDiv.className = 'flex-noshrink';
txHeader.append(txTypeDiv);
var txTypeIcon = document.createElement('div');
// class name populated after venueItem is defined
txTypeDiv.append(txTypeIcon);
var txSummary = document.createElement('div');
txSummary.className = 'wmeFdo-tx-summary wmeFdoDropdownHeader';
txHeader.append(txSummary);
var txCollapse = document.createElement('div');
txCollapse.className = 'flex-noshrink wmeFdo-tx-toggle-closed';
txHeader.append(txCollapse);
var txAuthorDate = document.createElement('div');
txAuthorDate.className = 'wmeFdo-tx-author-date';
var txPreview = document.createElement('div');
txPreview.className = 'wmeFdo-tx-preview';
var txName = document.createElement('h4');
//txName.className = 'type';
txAuthorDate.append(txName);
txSummary.append(txAuthorDate);
txSummary.append(txPreview);
var txContent = document.createElement('div');
txContent.className = 'wmeFdo-tx-content wmeFdoResultDetail';
var txContentClass = document.createElement('div');
txContentClass.className = 'main-object-region wmeFdo-tx-changes';
txContent.append(txContentClass);
var txContentInfo = document.createElement('div');
txContentInfo.className = 'related-objects-region wmeFdo-tx-changes';
var txContentData = document.createElement('div');
var controls = document.createElement('div');
controls.className = 'wmeFdoDetailControls';
txContent.append(controls);
txContentInfo.append(txContentData);
txContent.append(txContentInfo);
details.append(txHeader);
details.append(txContent);
var venueItem = venueAction.oldValue;
if (typeof(venueItem.geometry) == 'undefined') {
// History does not contain any details for this place, other than it was deleted.
// TODO: create empty record to at least show that there was something here at one point.
console.log(`No history found for venue id ${venueAction.objectID}`);
} else {
if (typeof(venueItem.categories) != 'undefined' && venueItem.categories[0] == 'RESIDENCE_HOME') {
txTypeIcon.className = 'flex-noshrink wmeFdoResultTypeResidential';
if (historySummary.isRejectedNew) {
txTypeIcon.classList.add('wmeFdoResultDeletedNewPlaceAlt');
} else if (historySummary.isAcceptedDelete) {
txTypeIcon.classList.add('wmeFdoResultDeletedFromRequestAlt');
}
} else if (typeof(venueItem.categories) != 'undefined' && venueItem.categories[0] == 'PARKING_LOT') {
txTypeIcon.className = 'flex-noshrink wmeFdoResultTypeParking';
if (historySummary.isRejectedNew) {
txTypeIcon.classList.add('wmeFdoResultDeletedNewPlaceAlt');
} else if (historySummary.isAcceptedDelete) {
txTypeIcon.classList.add('wmeFdoResultDeletedFromRequestAlt');
}
} else {
txTypeIcon.className = 'flex-noshrink wmeFdoResultTypeVenue';
if (historySummary.isRejectedNew) {
txTypeIcon.classList.add('wmeFdoResultDeletedNewPlace');
} else if (historySummary.isAcceptedDelete) {
txTypeIcon.classList.add('wmeFdoResultDeletedFromRequest');
}
}
if (historySummary.isRejectedNew) {
details.setAttribute("data-pur-new-rejected", "true");
}
if (venueItem.geometry.type == 'Polygon') {
var txTypeArea = document.createElement('div');
txTypeArea.className = 'flex-noshrink wmeFdoResultTypeArea';
txTypeDiv.append(txTypeArea);
}
let streetName = formatFullStreetName(venueHistory, venueItem.streetID);
let address = streetName;
if (typeof(venueItem.houseNumber) != 'undefined') {
address = venueItem.houseNumber + ' ' + address;
}
var venueName = venueItem.name;
if (typeof venueName == 'undefined' || venueName == " " || venueName == "")
{
if (typeof(venueItem.categories) != 'undefined' && venueItem.categories[0] == 'RESIDENCE_HOME') {
let resiStreet = formatStreetName(venueHistory, venueItem.streetID);
if (typeof(venueItem.houseNumber) != 'undefined') {
resiStreet = venueItem.houseNumber + ' ' + resiStreet;
}
venueName = resiStreet;
} else if (typeof(venueItem.categories) != 'undefined') {
venueName = 'unnamed ' + I18n.t("venues.categories." + venueItem.categories[0]);
} else {
venueName = 'unnamed';
//console.log('No category: ' + venueAction.objectID);
}
}
txName.innerText = venueName;
if (historySummary.purDeletedBy != null)
{
username = historySummary.purDeletedBy;
}
txPreview.innerHTML = streetName + '<br>Deleted by ' + username + " " + timeConverterNoTime(venueTransaction.date);
if (historySummary.isAcceptedDelete) {
//txPreview.innerHTML += " via PUR";
details.setAttribute("data-pur-delete-request", "true");
}
var info = document.createElement('div');
info.id = 'details-' + venueAction.objectID;
let flagControl = document.createElement('div');
flagControl.className = 'focus-buttons';
let flag = document.createElement('a');
flag.className = 'wmeFdoFlag';
if (flags['venue'][venueAction.objectID]) { flag.className = 'wmeFdoFlag flagged'; }
flag.innerHTML = '<span class="fa fa-flag"></span>';
flag.onclick = function () {
toggleFlag(flag, 'venue', venueAction.objectID);
};
flagControl.append(flag);
controls.append(flagControl);
var focusButtons = document.createElement('div');
focusButtons.className = 'focus-buttons';
var focus = document.createElement('a');
focus.className = 'focus';
focus.onclick = function () {
var lonLat = new OpenLayers.LonLat(operationCenterPoint.x, operationCenterPoint.y);
W.map.setCenter(lonLat, 6);
highlightPin(pin);
};
focusButtons.append(focus);
controls.append(focusButtons);
let lockRank = venueItem.lockRank +1;
txContentData.append(info);
let searchText = venueItem.name + " " + streetName;
var searchButton = document.createElement('button');
searchButton.textContent = 'Google';
searchButton.className = 'wmeFdoGoogleBtn btn btn-default center-block';
searchButton.addEventListener('click', function() {
window.open('https://www.google.com/search?q=' + encodeURIComponent(searchText),'_blank');
});
let recreateDiv = document.createElement('div');
recreateDiv.className = 'wmeFdoRecreate';
let recreateButton = document.createElement('a');
recreateButton.textContent = 'Recreate Place';
recreateButton.className = 'focus';
recreateButton.addEventListener('click', function() {
recreatePlace(venueItem, venueHistory, operationCenterPoint);
});
recreateDiv.append(recreateButton);
txContentData.append(searchButton);
txContentData.append(recreateDiv);
let panelHTML = '<ul>';
//panelHTML += '<ul>';
let venueIdReference = 'details-venue-id-' + venueAction.objectID;
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Venue ID</div>';
panelHTML += '<div class="ca-description ca-preview" id="' + venueIdReference + '">';
panelHTML += '</div></li>';
if (address != null && address != "" && address != " ") {
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Address</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += address;
panelHTML += '</div></li>';
}
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Categories</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += formatCategories(venueItem.categories);
details.setAttribute("data-categories", formatCategoriesNative(venueItem.categories));
panelHTML += '</div></li>';
if (typeof(venueItem.description) != 'undefined') {
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Description</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += venueItem.description;
panelHTML += '</div></li>';
}
if (typeof(venueItem.url) != 'undefined') {
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Website</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += venueItem.url;
panelHTML += '</div></li>';
}
if (typeof(venueItem.phone) != 'undefined') {
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Phone</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += venueItem.phone;
panelHTML += '</div></li>';
}
if (typeof(venueItem.lockRank) != 'undefined') {
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">Lock Rank</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += lockRank;
panelHTML += '</div></li>';
}
if (typeof(venueItem.externalProviderIDs) != 'undefined') {
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">External Provider IDs</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += '<div id="wmeFdoExternalProviders-' + venueAction.objectID + '"></div>';
panelHTML += '</div></li>';
}
panelHTML+= '<li class="tx-changed-attribute"><div class="ca-name">History</div>';
panelHTML += '<div class="ca-description ca-preview">';
panelHTML += historySummary.html;
panelHTML += '</div></li>';
panelHTML += '</ul>';
info.innerHTML = panelHTML;
//info.innerHTML += 'Changed from';
//info.innerHTML += '<span class="ca-value ca-value-old">';
//info.innerHTML += 'Walmart';
//info.innerHTML += '</span>';
//info.innerHTML += '<span>';
//info.innerHTML += 'to';
//info.innerHTML += '</span>';
//info.innerHTML += '<span class="ca-value ca-value-new">';
//info.innerHTML += 'Walmart Supercenter';
//info.innerHTML += '</span>';
$('#wmeFdoTransactionList').append(details);
let venueIdDiv = document.getElementById(venueIdReference);
let venueIdLi = document.getElementById(details.id);
setFilteredState(venueIdLi);
let venueIdDisplay = document.createElement('span');
if (W.loginManager.user.userName == "Joyriding") {
venueIdDisplay.innerHTML = `<a href="https://${window.location.host}${W.Config.api_base}/ElementHistory?objectType=venue&objectID=${venueAction.objectID}" target="_blank">${venueAction.objectID}</a> `;
} else {
venueIdDisplay.innerHTML = venueAction.objectID;
}
venueIdDiv.append(venueIdDisplay);
let pin = displayPin(operation, venueAction.oldValue);
let areaPreview = null;
details.onmouseenter = function () {
highlightPin(pin);
areaPreview = showDeletedArea(operation, venueAction.oldValue);
};
details.onmouseleave = function () {
returnPin(pin);
//removeDeletedArea();
_wmeFdoFeatureLayer.removeFeatures([areaPreview]);
};
}
}
}
}
}
});
});
}
});
}
function toggleFlag (control, objectType, objectID) {
if (flags[objectType][objectID]) {
delete flags[objectType][objectID];
control.className = 'wmeFdoFlag';
} else {
flags[objectType][objectID] = true;
control.className = 'wmeFdoFlag flagged';
}
}
function displayDetails() {
}
async function recreatePlace(origVenue, venueHistory, operationCenterPoint) {
let lonLat = new OpenLayers.LonLat(operationCenterPoint.x, operationCenterPoint.y);
if(!W.map.getExtent().containsLonLat(lonLat)) {
// Move to pin so that the City can be populated correctly
W.map.setCenter(lonLat, 6);
await wait(1000); //TODO: Check to see that cities have loaded before continuing rather than guessing a time delay
}
let wazeActionUpdateFeatureGeometry = require("Waze/Action/UpdateFeatureGeometry");
let wazefeatureVectorLandmark = require("Waze/Feature/Vector/Landmark");
let wazeActionAddLandmark = require("Waze/Action/AddLandmark");
let wazeActionUpdateObject = require('Waze/Action/UpdateObject');
let wazeActionUpdateFeatureAddress = require('Waze/Action/UpdateFeatureAddress');
let wazeOpeningHour = require("Waze/Model/Objects/OpeningHour");
let landmark = new wazefeatureVectorLandmark();
if (origVenue.geometry.type == 'Polygon') {
let points = [];
origVenue.geometry.coordinates[0].forEach( function(coord) {
let point = new OpenLayers.Geometry.Point(coord[0],coord[1]);
point.transform(displayProjection,projection);
points.push(point);
});
points.push(points[0]);
let linearRing = new OpenLayers.Geometry.LinearRing(points);
let polygon = new OpenLayers.Geometry.Polygon(linearRing);
landmark.geometry = polygon;
} else {
let point = new OpenLayers.Geometry.Point(origVenue.geometry.coordinates[0],origVenue.geometry.coordinates[1]);
point.transform(displayProjection,projection);
landmark.geometry = point;
}
if (typeof(origVenue.name) != 'undefined') { landmark.attributes.name = origVenue.name; }
if (typeof(origVenue.aliases) != 'undefined') { landmark.attributes.aliases = origVenue.aliases; }
if (typeof(origVenue.categories) != 'undefined') { landmark.attributes.categories = origVenue.categories; }
if (typeof(origVenue.description) != 'undefined') { landmark.attributes.description = origVenue.description; }
if (typeof(origVenue.lockRank) != 'undefined') { landmark.attributes.lockRank = origVenue.lockRank; }
if (typeof(origVenue.phone) != 'undefined') { landmark.attributes.phone = origVenue.phone; }
if (typeof(origVenue.rank) != 'undefined') { landmark.attributes.rank = origVenue.rank; }
if (typeof(origVenue.residential) != 'undefined') { landmark.attributes.residential = origVenue.residential; }
if (typeof(origVenue.services) != 'undefined') { landmark.attributes.services = origVenue.services; }
if (typeof(origVenue.url) != 'undefined') { landmark.attributes.url = origVenue.url; }
if (origVenue.categories.indexOf('GAS_STATION') > -1 || origVenue.categories.indexOf('PARKING_LOT') > -1) {
if (typeof(origVenue.brand) != 'undefined') { landmark.attributes.brand = origVenue.brand; }
}
if (origVenue.categories.indexOf('PARKING_LOT') > -1)
{
if (typeof(origVenue.categoryAttributes) != 'undefined') { landmark.attributes.categoryAttributes = origVenue.categoryAttributes; }
}
if (typeof(origVenue.entryExitPoints) != 'undefined') { //TODO: and if # entry points > 0
origVenue.entryExitPoints.forEach(function(origEntryExitPoint) {
let point = new OpenLayers.Geometry.Point(origEntryExitPoint.point.coordinates[0],origEntryExitPoint.point.coordinates[1]);
point.transform(displayProjection, projection);
let entryExitPoint = new NavigationPointMEP(point);
entryExitPoint._name = origEntryExitPoint.name;
entryExitPoint._entry = origEntryExitPoint.entry;
entryExitPoint._exit = origEntryExitPoint.exit;
entryExitPoint._isPrimary = origEntryExitPoint.primary;
landmark.attributes.entryExitPoints.push(entryExitPoint);
});
}
W.model.actionManager.add(new wazeActionAddLandmark(landmark));
if (typeof(origVenue.openingHours) != 'undefined') {
let hours = [];
origVenue.openingHours.forEach(function (hourEntry) {
hours.push(new wazeOpeningHour(hourEntry));
});
W.model.actionManager.add(new wazeActionUpdateObject(landmark, { openingHours: hours }));
}
if (typeof(origVenue.streetID) != 'undefined') {
//TODO: Make this a separate function and use for all address building, cache after built by streetID
var addressParts = {
streetName: "",
emptyStreet: false,
cityName: "",
emptyCity: false,
streetID: origVenue.streetID,
stateID: null,
countryID: null,
addressFormShown: false,
editable: true,
fullAddress: "",
ttsLocales: [W.Config.tts.default_locale],
altStreets: new Backbone.Collection,
newAltStreets: new Backbone.Collection
};
venueHistory.streets.objects.forEach(function(street) {
if (street.id == origVenue.streetID) {
if (street.name == "")
addressParts.emptyStreet = true;
addressParts.streetName = street.name;
venueHistory.cities.objects.forEach(function(city) {
if (street.cityID == city.id) {
if (city.name == "")
addressParts.emptyCity = true;
addressParts.cityName = city.name;
addressParts.stateID = city.stateID;
venueHistory.states.objects.forEach(function(state) {
if (city.stateID == state.id) {
addressParts.countryID = state.countryID;
}
});
}
});
}
});
W.model.actionManager.add(new wazeActionUpdateFeatureAddress(landmark, addressParts,{streetIDField: 'streetID'}));
}
if (typeof(origVenue.houseNumber) != 'undefined') {
W.model.actionManager.add(new wazeActionUpdateObject(landmark,{houseNumber: origVenue.houseNumber}));
}
//console.log(landmark);
let foundFeature = null;
W.selectionManager._layers.forEach(function(layer) {
if (layer.featureType == 'venue') {
layer.features.forEach(function(feature) {
if (landmark.geometry.id == feature.geometry.id)
{
foundFeature = feature;
}
});
}
});
if (foundFeature != null) {
W.selectionManager.selectFeature(foundFeature);
W.selectionManager._triggerSelectionChanged()
}
var epm = Backbone.Model.extend({
defaults: {
uuid: null,
name: null,
url: null,
location: null
},
initialize: function() {
if (null === this.get("uuid")) return this.set({
uuid: this.id
})
},
getDetails: function(e) {
this.set({uuid: e});
return this.set({
name: externalProviderDetails[e].name,
location: externalProviderDetails[e].geometry.location,
url: externalProviderDetails[e].url
});
},
_getDetailsFromUuid: function(e) {
return this.set({
name: this.get("uuid"),
location: "",
url: ""
})
},
toJSON: function() {
return this.get("uuid")
}
});
if (typeof(origVenue.externalProviderIDs) != 'undefined') {
let ids = [];
origVenue.externalProviderIDs.forEach(function(externalProviderID) {
let newID = new epm();
newID.getDetails(externalProviderID);
newID.collection = new Backbone.Collection();
ids.push(newID);
}); //10521
W.model.actionManager.add(new wazeActionUpdateObject(landmark,{externalProviderIDs: ids}));
}
}
function displayExternalProviders(venueID, externalProviderIDs) {
if (typeof(externalProviderIDs) != 'undefined') {
externalProviderIDs.forEach(function(externalProviderID) {
let extProv = document.getElementById('wmeFdoExternalProviders-' + venueID);
let div = document.createElement('div');
div.innerHTML = externalProviderID;
extProv.append(div);
getExternalProviderDetail(externalProviderID, function(data) {
let closed = data.permanently_closed;
div.innerHTML = '<a href="' + data.url + '" target="_blank">' + externalProviderID + '</a>';
if (closed) {
div.innerHTML = div.innerHTML + ' <span style="color:red;">closed</span>';
}
});
});
}
}
function getExternalProviderDetail(externalProviderID, callback) {
if (googleMapsApi.service == null) {
googleMapsApi.service = new google.maps.places.PlacesService(googleMapsApi.map);
}
if (typeof(externalProviderDetails[externalProviderID]) == 'undefined') {
let request = {
placeId: externalProviderID,
fields: ['name','url','permanently_closed','geometry']
}
googleMapsApi.service.getDetails(request, function(place, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
externalProviderDetails[externalProviderID] = place;
callback(externalProviderDetails[externalProviderID]);
} else {
//TODO: callback with error response
callback(null);
}
});
} else {
callback(externalProviderDetails[externalProviderID]);
}
}
function toggleFilterDropDown() {
let details = document.getElementById('wmeFdoFilterDetails');
let openDropDown = false;
if (details.classList.contains('closed')) {
details.classList.remove('closed');
} else {
details.classList.add('closed');
}
}
function toggleScanStatusDropDown() {
let details = document.getElementById('wmeFdoScanStatus');
let openDropDown = false;
if (details.classList.contains('closed')) {
details.classList.remove('closed');
} else {
details.classList.add('closed');
}
}
function toggleDetailsDropDown(elementId, operationCenterPoint) {
let details = document.getElementById(elementId);
let openDropDown = false;
if (details.classList.contains('closed')) {
openDropDown = true;
}
closeAllDetailsDropDown();
if (openDropDown) {
details.classList.remove('closed');
settings.Enabled = true;
onLayerCheckboxChanged(settings.Enabled); // TODO: Fix this so the Layer menu checkbox gets updated
let lonLat = new OpenLayers.LonLat(operationCenterPoint.x, operationCenterPoint.y);
if(!W.map.getExtent().containsLonLat(lonLat)) {
W.map.setCenter(lonLat, 6);
}
}
}
function openDetailsDropDown(elementId, operationCenterPoint) {
let details = document.getElementById(elementId);
//details.className = 'element-history-item tx-has-content';
details.classList.remove('closed');
details.classList.remove('hidden');
// var lonLat = new OpenLayers.LonLat(operationCenterPoint.x, operationCenterPoint.y);
//W.map.setCenter(operationCenterPoint.toLonLat(), 6);
}
function closeDetailsDropDown(elementId) {
let details = document.getElementById(elementId);
details.classList.add('closed');
}
function closeAllDetailsDropDown() {
let ul = document.getElementById('wmeFdoTransactionList');
let items = ul.getElementsByTagName('li');
for (var i = 0; i < items.length; ++i) {
let elementId = items[i].id;
if (elementId.startsWith('entry-')) {
closeDetailsDropDown(elementId);
}
}
}
function displayPin(transactionOperation, deletedVenue) {
let deletedPlacePt=new OpenLayers.Geometry.Point(transactionOperation.objectCentroid.coordinates[0], transactionOperation.objectCentroid.coordinates[1]);
deletedPlacePt.transform(displayProjection, projection);
let point = new OpenLayers.Geometry.Point(deletedPlacePt.x, deletedPlacePt.y);
let style = {strokeColor: 'black',
strokeWidth: '5',
strokeDashstyle: 'solid',
pointRadius: '5',
fillOpacity: '1'};
let feature = new OpenLayers.Feature.Vector(point, {id:transactionOperation.objectID}, style);
var di = require("Waze/DivIcon");
var iconA = new di("place-update add_venue low map-marker wmeFdo-place-delete");
var lonlatA = new OpenLayers.LonLat(deletedPlacePt.x, deletedPlacePt.y);
// let markerLayer = W.map.getLayerByUniqueName('__wmeFdoMarkerLayer');
let marker = new OpenLayers.Marker(lonlatA, iconA);
marker.id = 1;
marker.events.register('click', marker, function(evt) {
W.selectionManager.unselectAll();
selectTab();
let elementId = 'entry-' + transactionOperation.objectID;
closeAllDetailsDropDown();
openDetailsDropDown(elementId, deletedPlacePt);
document.getElementById(elementId).scrollIntoView();
});
addLayers();
_wmeFdoFeatureLayer.addFeatures([feature]);
_wmeFdoMarkerLayer.addMarker(marker);
return feature;
}
function addLayers() {
if (_wmeFdoFeatureLayer == undefined) {
_wmeFdoFeatureLayer = new OpenLayers.Layer.Vector("_wmeFdoFeatureLayer",{uniqueName: "__wmeFdoFeatureLayer"});
_wmeFdoMarkerLayer = new OpenLayers.Layer.Markers("_wmeFdoMarkerLayer",{uniqueName: "__wmeFdoMarkerLayer"});
W.map.addLayer(_wmeFdoFeatureLayer);
W.map.addLayer(_wmeFdoMarkerLayer);
if (settings.Enabled) {
_wmeFdoFeatureLayer.setVisibility(true);
_wmeFdoMarkerLayer.setVisibility(true);
} else {
_wmeFdoFeatureLayer.setVisibility(false);
_wmeFdoMarkerLayer.setVisibility(false);
}
}
}
function showDeletedArea(transactionOperation, deletedVenue) {
let polygon = null;
if (deletedVenue.geometry.type == 'Polygon') {
let points = [];
deletedVenue.geometry.coordinates[0].forEach( function(coord) {
let point = new OpenLayers.Geometry.Point(coord[0],coord[1]);
point.transform(displayProjection,projection);
points.push(point);
});
points.push(points[0]);
let linearRing = new OpenLayers.Geometry.LinearRing(points);
polygon = new OpenLayers.Geometry.Polygon(linearRing);
}
let style = {strokeColor: 'orange',
strokeWidth: '4',
strokeDashstyle: 'solid',
fillOpacity: '0.2'};
let feature = new OpenLayers.Feature.Vector(polygon, {id:transactionOperation.objectID}, style);
_wmeFdoFeatureLayer.addFeatures([feature]);
return feature;
}
function getParentCategory(category) {
// Build subcategory > parent category mapping once
if (subcategoryToParentCategories.length == 0) {
let index = 0;
Object.keys(W.Config.venues.subcategories).forEach(function(parent) {
let parentName = Object.getOwnPropertyNames(W.Config.venues.subcategories)[index];
subcategoryToParentCategories[parentName] = parentName;
W.Config.venues.subcategories[parentName].forEach(function(subcategory) {
subcategoryToParentCategories[subcategory] = parentName;
});
index++;
});
}
return subcategoryToParentCategories[category];
}
function getCategoryIconClass(category) {
let parentCategory = getParentCategory(category);
// TODO: Lowercase and replace '_' with '-' instead?
switch(parentCategory) {
case 'TRANSPORTATION':
return 'transportation';
break;
case 'PROFESSIONAL_AND_PUBLIC':
return 'professional-and-public';
break;
case 'SHOPPING_AND_SERVICES':
return 'shopping-and-services';
break;
case 'FOOD_AND_DRINK':
return 'food-and-drink';
break;
case 'CULTURE_AND_ENTERTAINEMENT':
return 'culture-and-entertainement';
break;
case 'LODGING':
return 'lodging';
break;
case 'OUTDOORS':
return 'outdoors';
break;
case 'NATURAL_FEATURES':
return 'natural-features';
break;
case 'PARKING_LOT':
return 'parking-lot';
default:
return 'OTHER';
}
// WME CSS Example:
// #edit-buttons .transportation .item-icon::after {
// background-image: url(//editor-assets.waze.com/production/img/toolbare2f6b31….png);
// background-position: -13px -70px;
// width: 12px;
// height: 12px;
// }
}
function formatStreetName(venueHistory, streetId) {
// TODO: replace with address cache lookup/build function
let streetName = null;
venueHistory.streets.objects.forEach(function(street) {
if (street.id == streetId) {
streetName = street.name;
}
});
if (streetName == null) {
streetName = "";
}
return streetName;
}
function formatFullStreetName(venueHistory, streetId) {
// TODO: replace with address cache lookup/build function
let streetName = null;
venueHistory.streets.objects.forEach(function(street) {
if (street.id == streetId) {
streetName = street.name;
venueHistory.cities.objects.forEach(function(city) {
if (street.cityID == city.id) {
if (streetName != '') {
streetName = streetName + ", ";
}
streetName = streetName + city.name;
venueHistory.states.objects.forEach(function(state) {
if (city.stateID == state.id) {
if (city.name != '') {
streetName = streetName + ", ";
}
streetName = streetName + state.name;
}
});
}
});
}
});
if (streetName == null) {
streetName = "";
}
return streetName;
}
function formatCategories(categories) {
let output = ''
categories.forEach(function(category) {
output = output + ", " + I18n.t("venues.categories." + category);
});
output = output.substring(2);
return output;
}
function formatCategoriesNative(categories) {
let output = ''
categories.forEach(function(category) {
output = output + "," + category;
});
output = output.substring(1);
return output;
}
function formatExternalProviders(externalProviderIDs) {
let output = "<ul>";
if (typeof externalProviderIDs != 'undefined') {
externalProviderIDs.forEach(function(externalProviderID) {
output = output + "<li>" + externalProviderID + "</ul>";
});
}
output = output + "</ul>";
return output;
}
function getVenueHistory(venueHistory) {
let historySummary = {
html: null,
isRejectedNew: false,
isAcceptedDelete: false,
purDeletedBy: null
}
let output = "<ul class='wmeFdoHistorySummaryList'>";
let transactionCount = 0;
venueHistory.transactions.objects.forEach(function(venueTransaction) {
transactionCount++;
let username = null;
let usernameHtml = null;
venueHistory.users.objects.forEach( function(user) {
if (user.id == venueTransaction.userID) {
let userRank = user.rank + 1;
username = user.userName + '(' + userRank + ')';
usernameHtml = `<a target="_blank" href="https://${window.location.host}/user/editor/${user.userName}">${username}</a>`;
}
});
let detailCount = 0;
let requestType = venueTransaction.actionType;
let purText = null;
let addedPurNotation = false;
let previousObjectType = null;
venueTransaction.objects.forEach(function(venueSubObject) {
purText = null;
let addDate = false;
if (venueSubObject.objectType == 'venueUpdateRequest') {
if (transactionCount == 2 && previousObjectType == 'venue') {
historySummary.purDeletedBy = username;
}
previousObjectType = venueSubObject.objectType;
if (!addedPurNotation) {
addedPurNotation = true;
requestType = requestType + " (PUR)";
}
if (typeof(venueSubObject.oldValue) != 'undefined') {
let rejected = false;
if (typeof(venueSubObject.oldValue.approve) == 'undefined') {
purText = "(Unknown Action) ";
} else if (venueSubObject.oldValue.approve) {
purText = "Approved ";
} else {
purText = "Rejected ";
rejected = true;
}
if (typeof(venueSubObject.oldValue.type) == 'undefined'
&& (venueSubObject.oldValue.id.includes('-') && !venueSubObject.oldValue.id.includes('.'))
) {
// Older entries did not contain the type, test to see if it's a rejected image
venueSubObject.oldValue.type = 'IMAGE';
}
if (venueSubObject.oldValue.type == 'VENUE') {
//rejectedNew = true;
purText = purText + "New Place";
addDate = true;
if (rejected) {
historySummary.isRejectedNew = true;
}
} else if (venueSubObject.oldValue.type == 'REQUEST') {
if (venueSubObject.oldValue.subType == 'DELETE') {
purText = purText + "Delete Request";
if (!rejected) {
historySummary.isAcceptedDelete = true;
}
} else if (venueSubObject.oldValue.subType == 'UPDATE') {
purText = purText + "Update Request";
}
addDate = true;
} else if (venueSubObject.oldValue.type == 'IMAGE') {
purText += "Photo";
purText = `<a target="_blank" href="https://venue-image.waze.com/${venueSubObject.oldValue.id}">${purText}</a>`;
}
if (addDate) {
let origPurUnixTime = parseInt(venueSubObject.oldValue.id.split('.')[0]);
let newPurDate = timeConverter(origPurUnixTime);
purText = purText + " (" + newPurDate + ")";
}
} else if (typeof(venueSubObject.newValue) != 'undefined') {
purText = "Submitted ";
if (typeof(venueSubObject.newValue.type) != 'undefined') {
if (venueSubObject.newValue.type == 'VENUE') {
//rejectedNew = true;
purText = purText + "New Place";
addDate = true;
} else if (venueSubObject.newValue.type == 'REQUEST') {
if (venueSubObject.newValue.subType == 'DELETE') {
purText = purText + "Delete Request";
} else if (venueSubObject.newValue.subType == 'UPDATE') {
purText = purText + "Update Request";
}
addDate = true;
}
} else if (venueSubObject.newValue.id.includes('-') && !venueSubObject.newValue.id.includes('.')) {
// Older entries did not contain the type, test to see if it's a rejected image
//venueSubObject.oldValue.type = 'IMAGE';
purText += "Photo";
purText = `<li><a target="_blank" href="https://venue-image.waze.com/${venueSubObject.newValue.id}">Rejected Photo</a></li>`;
}
if (addDate) {
let origPurUnixTime = parseInt(venueSubObject.newValue.id.split('.')[0]);
let newPurDate = timeConverter(origPurUnixTime);
purText = purText + " (" + newPurDate + ")";
}
}
}
});
output = output + "<li><div>" + timeConverter(venueTransaction.date) + " " + requestType + " " + usernameHtml + "</div>";
output = output + '<ul class="historySummaryItem">';
if (purText != null) {
output = output + '<li>' + purText + '</li>';
}
if (typeof(venueTransaction.objects[0].newValue) != 'undefined' && typeof(venueTransaction.objects[0].newValue.name) != 'undefined')
{
detailCount++;
output = output + '<li>Name: ' + venueTransaction.objects[0].newValue.name + '</li>';
if (venueTransaction.objects[0].actionType == 'UPDATE') {
output = output + '<li>Was: ' + venueTransaction.objects[0].oldValue.name + '</li>';
}
}
// if (typeof(venueTransaction.objects[0].oldValue) != 'undefined' && venueTransaction.objects[0].oldValue.type == 'IMAGE') {
// output = output + `<li><a target="_blank" href="https://venue-image.waze.com/${venueTransaction.objects[0].oldValue.id}">Rejected Photo</a></li>`;
// }
output = output + '</ul>';
if (detailCount > 0) {
output = output + '</li style="margin-bottom:4px">';
} else {
output = output + "</li>";
}
// console.log(venueTransaction);
});
output = output + "</ul>";
historySummary.html = output;
return historySummary;
}
function applyFiltersToResults() {
let ul = document.getElementById('wmeFdoTransactionList');
let items = ul.getElementsByTagName('li');
for (var i = 0; i < items.length; ++i) {
let elementId = items[i].id;
let element = document.getElementById(elementId);
if (elementId.startsWith('entry-')) {
setFilteredState(element);
}
}
}
function setFilteredState(element) {
let filtered = false;
let filterTypeCount = 0;
if (!settings.FilterResidential) {
filterTypeCount++;
if (element.getAttribute('data-categories') == 'RESIDENCE_HOME') {
filtered = true;
}
}
if (!settings.FilterParkingLot) {
filterTypeCount++;
if (element.getAttribute('data-categories') == 'PARKING_LOT') {
filtered = true;
}
}
if (!settings.FilterAnyType) {
filterTypeCount++;
if (element.getAttribute('data-categories') != 'RESIDENCE_HOME' && element.getAttribute('data-categories') != 'PARKING_LOT') {
filtered = true;
}
}
let allTypesFiltered = false;
if (filterTypeCount == 3) {
allTypesFiltered = true;
}
if (element.getAttribute('data-pur-new-rejected') == "true") {
if (!settings.FilterNewRejected) {
filtered = true;
} else if (allTypesFiltered && filtered) {
filtered = false;
}
}
//
if (element.getAttribute('data-pur-delete-request') == "true") {
if (!settings.FilterDeleteRequest) {
filtered = true;
} else if (allTypesFiltered && filtered) {
filtered = false;
}
}
if (filtered) {
element.classList.add('hidden');
} else {
element.classList.remove('hidden');
}
}
function endScan(reasonText, setEndedFlag) {
if (setEndedFlag) {
var findButton = document.getElementById('wmeFdoFindButton');
findButton.className = 'btn btn-success center-block';
var cancelButton = document.getElementById('wmeFdoCancelButton');
cancelButton.className = 'btn btn-warning center-block hidden';
$('#wmeFdoTabFind').data("status","ended");
let tab = document.getElementById('wmeFdoTab');
tab.innerHTML = 'FiDO <span class="spinner-disable"><i class="icon-spinner icon-spin fa fa-spinner fa-spin"></i></span>';
cancelScanNew();
}
$('#wmeFdoScanCurrentStatus')[0].innerText = reasonText;
}
async function findObjects() {
let editorList = [];
let searchAreaGeometry = getSearchArea();
var lookFor = {
objectType:'Venue',
actionType:'DELETE',
searchArea: searchAreaGeometry,
limitToScreen: settings.LimitToScreen,
includeSelf: settings.IncludeSelf
}
//var centerCoords = W.map.getCenter().clone().transform(W.map.projection, W.map.displayProjection);
if (settings.NearbyEditors) {
lookFor.limitToScreen = true;
lookFor.includeSelf = true;
//TODO: use W.model if zoom <= 3
let editorListScreen = getNearbyEditors();
let featuresList = await getScreenFeatures();
let editorListFeatures = getNearbyEditorsFromFeatures(featuresList);
let editorListTemp = [];
editorListFeatures.forEach(function(userID) {
editorListTemp[userID] = true;
apiEndpointWazeCom.users.total++;
});
Object.keys(editorListTemp).forEach(function(userID) {
editorList.push(userID);
});
processUsers(lookFor, editorList);
} else {
lookFor.limitToScreen = settings.LimitToScreen;
lookFor.includeSelf = settings.IncludeSelf;
Date.prototype.addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
let startDate = null;
let startDateInput = document.getElementById('wmeFdoFindDate');
let dateInput = null;
if (Date.parse(startDateInput.value) != null) {
dateInput = new Date(startDateInput.value).addDays(1);
startDate = dateToUuid(dateInput);
dateInput = new Date(dateInput).getTime();
} else {
dateInput = new Date.now();
}
var transactionLookup = {
username:$('#wmeFdoEditorName')[0].value,
userId:null,
nextTransactionDate:startDate,
iteration:0,
maxIterations:100000
};
if (transactionLookup.username == null || transactionLookup.username == "") {
endScan('Please enter an editor name!', true);
} else {
let requestParamsUserProfile = requestParams(getApiUrlUserProfile(transactionLookup.username));
requestStatus[requestParamsUserProfile.url] = defaultRequestStatus();
apiEndpointWazeCom.requests.push(requestParamsUserProfile);
getEndpointResult(apiEndpointWazeCom, requestParamsUserProfile, userProfile => {
if (typeof(userProfile.userID) == 'undefined') {
endScan('Editor name not found!', true);
} else {
apiEndpointWazeCom.users.total++;
addUserCache(userProfile.userID, userProfile.username, userProfile.rank)
if (userProfile.firstEditDate > earliestScanDate) {
userCache[userProfile.userID].earliestDate = userProfile.firstEditDate;
} else {
userCache[userProfile.userID].earliestDate = earliestScanDate;
}
userCache[userProfile.userID].latestDate = dateInput;
editorList.push(userProfile.userID);
}
processUsers(lookFor, editorList);
});
}
}
}
function processUsers(lookFor, editorList) {
$('#wmeFdoScanStatus .wmeFdoProgress').removeClass('hidden');
apiEndpointWazeCom.gotFeatures = true;
editorList.forEach(function (userID) {
Date.prototype.addDays = function(days) {
var date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
let startDate = null;
let startDateInput = document.getElementById('wmeFdoFindDate');
if (Date.parse(startDateInput.value) != null) {
let dateInput = new Date(startDateInput.value).addDays(1);
startDate = dateToUuid(dateInput);
}
var transactionLookup = {
username:null,
userId:userID,
nextTransactionDate:startDate,
iteration:0,
maxIterations:100000
};
let latestDate = timeConverter(userCache[userID].latestDate + DAY_MS);
transactionLookup.nextTransactionDate = dateToUuid(latestDate);
let username = `<a target="_blank" href="https://${window.location.host}/user/editor/${userCache[userID].username}">${userCache[userID].username}(${(userCache[userID].rank + 1)})</a>`;
$('#wmeFdoStatusUsersList').append('<li id="wmeFdoStatusUser-' + userID + '">'
+ username + ': <span class="wmeFdoStatusUser">Not Started</span>'
+ '<div class="wmeFdoProgress"><div class="wmeFdoComplete"></div></div>'
+ '<div class="wmeFdoStatusUserDates">'
+ '<div class="wmeFdoStatusUserLatest">' + timeConverterNoTime(userCache[userID].latestDate) + '</div>'
+ '<div class="wmeFdoStatusUserEarliest">' + timeConverterNoTime(userCache[userID].earliestDate) + '</div>'
+ '<div style="clear:both;"></div>'
+ '</div>'
+ '</li>');
userCache[userID].previousDate = userCache[userID].latestDate + DAY_MS;
let totalMs = (userCache[userID].latestDate + DAY_MS) - (userCache[userID].earliestDate - DAY_MS);
userCache[userID].totalMs = totalMs;
apiEndpointWazeCom.progress.totalMs += userCache[userID].totalMs;
beginFind(lookFor, transactionLookup);
});
}
function getSearchArea() {
var theVenue = null;
var count = 0;
for (var v in W.model.venues.objects) {
if (W.model.venues.objects.hasOwnProperty(v) === false) {
continue;
}
var venue = W.model.venues.objects[v];
if (venue.isPoint() === true) {
continue;
}
if ($.isNumeric(venue.attributes.id) && parseInt(venue.attributes.id) <= 0) {
theVenue = venue;
count++;
}
}
if (count === 0) {
console.log("using screen");
return W.map.getExtent().toGeometry();
}
if (theVenue.geometry.components.length !== 1) {
alert("Can't parse the geometry");
return;
} else {
console.log("using unsaved place area");
return theVenue.geometry.clone();
}
}
function getNearbyEditors() {
$('#wmeFdoScanCurrentStatus')[0].innerText = 'Finding Nearby Editors';
//let earliestDate = parseInt(new Date('2016-12-31').getTime());
let editorList = [];
let editorListReturn = [];
Object.keys(W.model.venues.objects).forEach(function (venueId) {
let venue = W.model.venues.objects[venueId].attributes;
if (typeof(venue.createdOn) != 'undefined' && venue.createdOn > earliestScanDate) {
editorList[venue.createdBy] = venue.createdOn;
}
if (typeof(venue.updatedOn) != 'undefined' && venue.updatedOn > earliestScanDate) {
editorList[venue.updatedBy] = venue.updatedBy;
}
//console.log(W.model.venues.objects[venueId].attributes.createdBy)
});
Object.keys(W.model.segments.objects).forEach(function (segmentId) {
let segment = W.model.segments.objects[segmentId].attributes;
if (typeof(segment.createdOn) != 'undefined' && segment.createdOn > earliestScanDate) {
editorList[segment.createdBy] = segment.createdOn;
}
if (typeof(segment.updatedOn) != 'undefined' && segment.updatedOn > earliestScanDate) {
editorList[segment.updatedBy] = segment.updatedBy;
}
//console.log(W.model.venues.objects[venueId].attributes.createdBy)
});
Object.keys(editorList).forEach(function (editorId) {
if (editorId != 'undefined') {
editorListReturn.push(editorId);
}
});
return editorListReturn;
}
function getNearbyEditorsFromFeatures(featuresList) {
$('#wmeFdoScanCurrentStatus')[0].innerText = 'Finding Nearby Editors';
let editorList = [];
let editorListReturn = [];
featuresList.forEach(function (features) {
if (typeof(features.error) == 'undefined') {
if (typeof(features.venues) != 'undefined') {
features.users.objects.forEach(function (user) {
addUserCache(user.id, user.userName, user.rank);
});
}
if (typeof(features.venues) != 'undefined') {
features.venues.objects.forEach(function (venue) {
if (typeof(venue.createdOn) != 'undefined' && venue.createdOn > earliestScanDate) {
editorList[venue.createdBy] = venue.createdOn;
updateUserCache(venue.createdBy, venue.createdOn);
}
if (typeof(venue.updatedOn) != 'undefined' && venue.updatedOn > earliestScanDate) {
editorList[venue.updatedBy] = venue.updatedBy;
updateUserCache(venue.updatedBy, venue.updatedOn);
}
seenVenueIds.push(venue.id); // Venue exists, no need to check its history
});
}
if (typeof(features.segments) != 'undefined') {
features.segments.objects.forEach(function (segment) {
if (typeof(segment.createdOn) != 'undefined' && segment.createdOn > earliestScanDate) {
editorList[segment.createdBy] = segment.createdOn;
updateUserCache(segment.createdBy, segment.createdOn);
}
if (typeof(segment.updatedOn) != 'undefined' && segment.updatedOn > earliestScanDate) {
editorList[segment.updatedBy] = segment.updatedBy;
updateUserCache(segment.updatedBy, segment.updatedOn);
}
});
}
}
});
Object.keys(editorList).forEach(function (editorId) {
if (editorId != 'undefined') {
editorListReturn.push(editorId);
}
});
return editorListReturn;
}
function addUserCache(userID, userName, rank) {
if (typeof(userCache[userID]) == 'undefined') {
userCache[userID] = defaultUserCache(userID, userName, rank);
}
}
function updateUserCache(userID, actionDate) {
if (typeof(userCache[userID]) == 'undefined') {
} else {
if (actionDate > userCache[userID].latestDate) {
userCache[userID].latestDate = actionDate;
}
if (actionDate < userCache[userID].earliestDate) {
userCache[userID].earliestDate = actionDate;
}
}
}
async function getScreenFeatures() {
return new Promise( async resolve => {
let urlList = [];
let paramsList = [];
let featuresList = [];
let maxDegrees = 0.125;
let minDegrees = 0.0625;
let extent = W.map.getExtent().transform(projection,displayProjection);
//NW: LT - left top
//NE: RT - right top
//SW: LB - left bottom
//SE: RB - right bottom
let geoLT = new OpenLayers.Geometry.Point(extent.left,extent.top);
let geoRB = new OpenLayers.Geometry.Point(extent.right,extent.bottom);
let geoLTSplit = new OpenLayers.Geometry.Point(geoLT.x,geoLT.y);
let geoRBSplit = new OpenLayers.Geometry.Point(geoRB.x,geoRB.y);
let geoTempY = new OpenLayers.Geometry.Point(geoLT.x,geoLT.y);
let xSplit = geoLT.x;
let ySplit = geoLT.y;
//console.log(extent);
//console.log(geoLT);
//console.log(geoRB);
while (ySplit >= geoRB.y) {
geoTempY.y = geoTempY.y - maxDegrees;
ySplit = geoTempY.y;
let degreesFromGeoRBY = geoRB.y - ySplit;
if (ySplit > geoRB.y)
geoRBSplit.y = ySplit
else if (degreesFromGeoRBY <= minDegrees)
geoRBSplit.y = ySplit - (minDegrees - degreesFromGeoRBY);
else
geoRBSplit.y = geoRB.y;
while (xSplit <= geoRB.x) {
geoTempY.x = geoTempY.x + maxDegrees;
xSplit = geoTempY.x;
let degreesFromGeoRBX = geoRB.x - xSplit;
if (xSplit > geoRB.x)
geoRBSplit.x = xSplit
else if (degreesFromGeoRBX <= minDegrees)
geoRBSplit.x = xSplit - (minDegrees - degreesFromGeoRBX);
else
geoRBSplit.x = geoRB.x;
// let bboxGeoLT = geoLTSplit.clone();
// let bboxGeoEB = geoEBSplit.clone();
let bbox = `${geoLTSplit.x},${geoLTSplit.y},${geoRBSplit.x},${geoRBSplit.y}`;
let url = getApiUrlFeatures(bbox);
urlList.push(url);
//console.log(url);
let params = requestParams(url);
requestStatus[url] = defaultRequestStatus();
// let features = null;
// features = await getApiRequest(params);
// featuresList.push(features);
paramsList.push(params);
apiEndpointWazeCom.requests.push(params);
geoLTSplit.x = xSplit;
}
geoLTSplit.y = ySplit;
geoLTSplit.x = geoLT.x;
xSplit = geoLT.x;
geoTempY.x = xSplit;
}
getEndpointResultFromArray(apiEndpointWazeCom, paramsList, featuresList => {
resolve(featuresList);
});
});
}
function getApiUrlUserProfile(username) {
return `https://${window.location.host}${W.Config.api_base}/UserProfile/Profile?username=${username}`;
}
function getApiUrlTransactions(userId, nextTransactionDate) {
let url = `https://${window.location.host}${W.Config.api_base}/UserProfile/Transactions?userID=${userId}`;
if (nextTransactionDate != null) {
url = url + '&till=' + nextTransactionDate;
}
return url;
}
function getApiUrlElementHistory(objectType, objectId, nextTransactionDate) {
let url = `https://${window.location.host}${W.Config.api_base}/ElementHistory?objectType=${objectType}&objectID=${objectId}`;
if (nextTransactionDate != null) {
url = url + '&till=' + nextTransactionDate;
}
return url;
}
function getApiUrlFeatures(bbox) {
let url = `https://${window.location.host}${W.Config.api_base}/Features?language=en-US&bbox=${bbox}&roadTypes=2%2C3%2C4%2C6%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21%2C22&venueLevel=4&venueFilter=3%2C3%2C3`;
return url;
}
async function highlightPin(pin) {
if (pin.onScreen()) {
let layer = W.map.getLayerByUniqueName('__wmeFdoFeatureLayer');
let enableAnimation = false;
if (enableAnimation) {
pin.data.mouseout = false;
pin.style.strokeColor = 'red';
for (var i=100;i>=1;i--) {
await wait(10);
pin.style.strokeWidth = i;
layer.redraw();
if (pin.data.mouseout == true) {
i = 1;
returnPin(pin);
}
}
pin.style.strokeWidth = 4;
pin.style.pointRadius = 5;
pin.style.strokeColor = 'orange';
layer.redraw();
if (pin.data.mouseout == true) {
returnPin(pin);
}
} else {
pin.style.strokeWidth = 4;
pin.style.pointRadius = 5;
pin.style.strokeColor = 'orange';
layer.redraw();
}
}
}
function returnPin(pin) {
let style = {strokeColor: 'black',
strokeWidth: '4',
strokeDashstyle: 'solid',
pointRadius: '4',
fillOpacity: '1'};
if (pin.onScreen()) {
let layer = W.map.getLayerByUniqueName('__wmeFdoFeatureLayer');
pin.data.mouseout = true;
//pin.style.strokeColor = 'black';
//pin.style.strokeWidth = 5;
pin.style = style;
layer.redraw();
}
}
function createSettingsCheckbox($div, settingID, textDescription) {
let $checkbox = $('<input>', {type:'checkbox', id:settingID, class:'wmeFdoSettingsCheckbox'});
$div.append(
$('<div>', {class:'controls-container'}).css({paddingTop:'2px'}).append(
$checkbox,
$('<label>', {for:settingID}).text(textDescription).css({whiteSpace:'pre-line'})
)
);
return $checkbox;
}
function setChecked(checkboxId, checked) {
$('#' + checkboxId).prop('checked', checked);
}
function saveSettings() {
if (localStorage) {
var localsettings = {
Enabled: settings.Enabled,
IncludeSelf: settings.IncludeSelf,
LimitToScreen: settings.LimitToScreen,
NearbyEditors: settings.NearbyEditors,
FilterResidential: settings.FilterResidential,
FilterParkingLot: settings.FilterParkingLot,
FilterAnyType: settings.FilterAnyType,
FilterNewRejected: settings.FilterNewRejected,
FilterDeleteRequest: settings.FilterDeleteRequest
};
localStorage.setItem("wmeFdo_Settings", JSON.stringify(localsettings));
}
}
function loadSettings() {
var loadedSettings = $.parseJSON(localStorage.getItem("wmeFdo_Settings"));
var defaultSettings = {
Enabled: true,
IncludeSelf: true,
LimitToScreen: true,
NearbyEditors: true,
FilterResidential: true,
FilterParkingLot: true,
FilterAnyType: true,
FilterNewRejected: true,
FilterDeleteRequest: true
};
settings = loadedSettings ? loadedSettings : defaultSettings;
for (var prop in defaultSettings) {
if (!settings.hasOwnProperty(prop))
settings[prop] = defaultSettings[prop];
}
}
function prepareTab() {
let tabs = document.getElementById('user-tabs');
let items = tabs.getElementsByTagName('li');
for (var i = 0; i < items.length; ++i) {
let a = items[i].getElementsByTagName('a')[0]
if (a.href.includes('sidepanel-fido')) {
a.id = "wmeFdoTab";
a.innerHTML = 'FiDO <span class="spinner-disable"><i class="icon-spinner icon-spin fa fa-spinner fa-spin"></i></span>';
}
}
}
function selectTab() {
let tabs = document.getElementById('user-tabs');
let items = tabs.getElementsByTagName('li');
for (var i = 0; i < items.length; ++i) {
let a = items[i].getElementsByTagName('a')[0]
if (a.href.includes('sidepanel-fido')) {
items[i].getElementsByTagName('a')[0].click();
}
}
}
function dateToUuid(inputDate) {
let timestamp = parseInt(new Date(inputDate).getTime());
// uuid = "a02102cd-19df-11e9-bd87-1201fde9baf6"
// timestamp = 1547678386643;
let a = timestamp * 10000;
let b = a + 122192928000000000;
let c = b.toString(16);
//if (c.length % 2) {
// c = '0' + c;
//}
let d = c.substring(7) + '-' + c.substring(3,7) + '-1' + c.substring(0,3) + '-bd87-1201fde9baf6';
return d;
}
function get_time_int(uuid_str) {
var uuid_arr = uuid_str.split( '-' ),
time_str = [
uuid_arr[ 2 ].substring( 1 ),
uuid_arr[ 1 ],
uuid_arr[ 0 ]
].join( '' );
return parseInt( time_str, 16 );
};
function uuidToUnixTime(uuid_str) {
var int_time = get_time_int( uuid_str ) - 122192928000000000,
int_millisec = Math.floor( int_time / 10000 );
return int_millisec;
};
function uuidToDate(uuid_str) {
var int_time = get_time_int( uuid_str ) - 122192928000000000,
int_millisec = Math.floor( int_time / 10000 );
//return new Date( int_millisec );
return timeConverter(int_millisec);
};
function formatCurrentDate() {
var today = new Date();
var dd = today.getDate();
var mm = today.getMonth() + 1; //January is 0!
var yyyy = today.getFullYear();
if (dd < 10) {
dd = '0' + dd;
}
if (mm < 10) {
mm = '0' + mm;
}
return yyyy + '-' + mm + '-' + dd;
}
function timeConverter(UNIX_timestamp){
var a = new Date(UNIX_timestamp);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate();
if (date.toString().length == 1) {
date = "0" + date;
}
var hour = a.getHours();
if (hour.toString().length == 1) {
hour = "0" + hour;
}
var min = a.getMinutes();
if (min.toString().length == 1) {
min = "0" + min;
}
var sec = a.getSeconds();
if (sec.toString().length == 1) {
sec = "0" + sec;
}
//Dec 08, 2018
var time = month + ' ' + date + ', ' + year + ' ' + hour + ':' + min;
return time;
}
function timeConverterNoTime(UNIX_timestamp){
var a = new Date(UNIX_timestamp);
var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
var year = a.getFullYear();
var month = months[a.getMonth()];
var date = a.getDate();
if (date.toString().length == 1) {
date = "0" + date;
}
var hour = a.getHours();
if (hour.toString().length == 1) {
hour = "0" + hour;
}
var min = a.getMinutes();
if (min.toString().length == 1) {
min = "0" + min;
}
var sec = a.getSeconds();
if (sec.toString().length == 1) {
sec = "0" + sec;
}
//Dec 08, 2018
var time = month + ' ' + date + ', ' + year;
return time;
}
async function wait(ms) {
return new Promise(resolve => {
setTimeout(resolve, ms);
});
}
// ------------- Begin Web Request/Rate Limiting -----------
var apiEndpointWazeCom = null;
function defaultEndpointSettings() {
return {
state: 'idle',
isRunning: false,
requests: [],
results: [],
requestInterval: null,
statusInterval: null,
count: 0,
beginTime: Date.now(),
timeout: 100000,
gotFeatures: false,
rateLimit: {
baseDelay: 50,
addedDelay: 0,
stepUp: 20,
stepDown: 10,
lastCheck: Date.now(),
lastAdjusted: Date.now(),
intervalDelay: 5000,
checkInterval: null,
errorCount: 0,
errorCountMax: 50
},
users: {
total: 0,
complete: 0
},
progress: {
totalMs: 0,
completeMs: 0
}
};
}
function defaultUserCache(userID, username, rank) {
return {
userID: userID,
username: username,
rank: rank,
isRunning: false,
currentScanDate: null,
earliestDate: Date.now(),
latestDate: 0,
previousDate: 0,
totalMs: 0,
completeMs: 0
}
}
function defaultUserProgress(userID) {
return {
userID: userID,
username: null,
rank: null,
isRunning: false,
currentScanDate: null,
earliestDate: Date.now(),
previousDate: 0,
latestDate: 0,
totalMs: 0
}
}
function beginScanNew() {
// start api request handler
apiEndpointWazeCom = defaultEndpointSettings();
apiEndpointWazeCom.state = 'running';
apiEndpointWazeCom.isRunning = true;
apiEndpointWazeCom.requestInterval = setInterval(function() { apiHandlerWazeCom(apiEndpointWazeCom) }, getRateLimit(apiEndpointWazeCom));
apiEndpointWazeCom.rateLimit.checkInterval = setInterval(function() { setRateLimitAdjustDown(apiEndpointWazeCom) }, apiEndpointWazeCom.rateLimit.intervalDelay);
apiEndpointWazeCom.statusInterval = setInterval(function() { populateStatus(); }, 1000);
//$('#wmeFdoScanStatus .wmeFdoProgress').removeClass('hidden');
}
function cancelScanNew() {
// end api request handler
apiEndpointWazeCom.state = 'cancelled';
apiEndpointWazeCom.isRunning = false;
clearInterval(apiEndpointWazeCom.requestInterval);
clearInterval(apiEndpointWazeCom.rateLimit.checkInterval);
clearInterval(apiEndpointWazeCom.statusInverval);
$('#wmeFdoScanCurrentStatus')[0].innerText = 'Cancelled';
}
function apiHandlerWazeCom(apiEndpoint) {
if (apiEndpoint.requests.length > 0) {
//console.log("Handler " + apiEndpoint.count);
let requestParams = apiEndpoint.requests.shift();
getApiWebRequest(apiEndpoint, requestParams);
//apiEndpointWazeCom.count++;
}
}
function getApiWebRequest(apiEndpoint, requestParams) {
apiEndpoint.count++;
$.ajax({
type: 'GET',
url: requestParams.url,
success: function(data) {
//requestStatus[requestParams.url].status = 'successful';
if (typeof(data) == 'undefined') {
debugger;
}
apiEndpoint.results[requestParams.url] = data;
},
statusCode: {
406: function() { // Not Acceptable - bbox invalid?
apiEndpoint.results[requestParams.url] = {"error":true,reason:"error"};
},
429: function() { // Rate limit
setRateLimitAdjustUp(apiEndpoint);
apiEndpoint.requests.push(requestParams);
},
500: function() {
//debugger;
apiEndpoint.results[requestParams.url] = {"error":true,reason:"error"};
}
}
});
}
function getRateLimit(apiEndpoint) {
return apiEndpoint.rateLimit.baseDelay + apiEndpoint.rateLimit.addedDelay;
}
function setRateLimitAdjustUp(apiEndpoint) {
let currentTime = Date.now();
if (currentTime - apiEndpoint.rateLimit.lastAdjusted > 1000) {
apiEndpoint.rateLimit.lastAdjusted = currentTime;
apiEndpoint.rateLimit.errorCount++;
apiEndpoint.rateLimit.addedDelay += apiEndpoint.rateLimit.stepUp;
clearInterval(apiEndpoint.requestInterval);
apiEndpoint.requestInterval = setInterval(function() { apiHandlerWazeCom(apiEndpoint) }, getRateLimit(apiEndpoint));
console.log('rate limit adjusted up: ' + getRateLimit(apiEndpoint));
}
}
function setRateLimitAdjustDown(apiEndpoint) {
if (apiEndpoint.rateLimit.addedDelay > 0 && Date.now() - apiEndpoint.rateLimit.lastAdjusted > apiEndpoint.rateLimit.intervalDelay) { //&& apiEndpoint.rateLimit.errorCount <= apiEndpoint.rateLimit.errorCountMax) {
apiEndpoint.rateLimit.addedDelay -= apiEndpoint.rateLimit.stepDown;
clearInterval(apiEndpoint.requestInterval);
apiEndpoint.requestInterval = setInterval(function() { apiHandlerWazeCom(apiEndpoint) }, getRateLimit(apiEndpoint));
console.log('rate limit adjusted down: ' + getRateLimit(apiEndpoint));
}
}
function getEndpointResultFromArray(apiEndpoint, paramsList, callback) {
waitForAllUrlResults(apiEndpoint, paramsList, complete => {
let resultList = [];
paramsList.forEach(function (params) {
getEndpointResult(apiEndpoint, params, result => {
resultList.push(result);
});
});
callback(resultList);
});
}
function populateStatus() {
let runningSeconds = (Date.now() - apiEndpointWazeCom.beginTime) / 1000;
let requestsPerSecond = apiEndpointWazeCom.count / runningSeconds;
//console.log('queued requests: ' + Object.keys(apiEndpoint.requests).length + ', queued results: ' + Object.keys(apiEndpoint.results).length);
//console.log('users: ' + apiEndpoint.users.complete + '/' + apiEndpoint.users.total + ' complete, ' + (apiEndpoint.users.total - apiEndpoint.users.complete) + ' remaining');
//console.log('requests per second: ' + requestsPerSecond);
let remainingUsers = apiEndpointWazeCom.users.total - apiEndpointWazeCom.users.complete;
$('#wmeFdoRequests')[0].innerText = apiEndpointWazeCom.count;
$('#wmeFdoRequestsPerSecond')[0].innerText = Math.round(requestsPerSecond);
if (apiEndpointWazeCom.gotFeatures && remainingUsers == 0) {
endScan('Complete', true);
}
}
async function getEndpointResult(apiEndpoint, params, callback) {
let timeSinceRequest = Date.now() - params.initiated;
//console.log(typeof(apiEndpoint.results[params.url]));
while ( typeof(apiEndpoint.results[params.url]) == 'undefined' && apiEndpoint.isRunning ) {
// removed && timeSinceRequest < apiEndpoint.timeout
//console.log(typeof(apiEndpoint.results[params.url]));
await wait(50);
timeSinceRequest = Date.now() - params.initiated;
//console.log('waiting for: ' + params.url);
}
//if (timeSinceRequest >= apiEndpoint.timeout) {
// console.log('request timeout'); //TODO: handle this condition better
// }
let result = apiEndpoint.results[params.url];
delete apiEndpoint.results[params.url];
callback(result);
}
async function waitForAllUrlResults(apiEndpoint, paramsList, callback) {
let complete = false;
let listCount = paramsList.length;
while (!complete && apiEndpoint.isRunning) {
let foundCount = 0;
await wait(50);
paramsList.forEach(function (params) {
let foundUrl = false;
if (typeof(apiEndpoint.requests[params.url]) == 'undefined' && typeof(apiEndpoint.results[params.url]) != 'undefined') {
foundUrl = true;
foundCount++;
}
});
if (listCount == foundCount) {
complete = true;
}
}
callback(complete);
}
// ------------- End Web Request/Rate Limiting -----------
bootstrap();
})();
class NavigationPointMEP
{
constructor(point){
this._point = point.clone();
this._entry = true;
this._exit = true;
this._isPrimary = true;
this._name = "";
}
with(){
var e = arguments.length > 0 && void 0 !== arguments[0] ? arguments[0] : {};
if(e.point == null)
e.point = this.toJSON().point;
let val = new this.constructor((this.toJSON().point, e.point));
val._entry = this._entry;
val._exit = this._exit;
val._isPrimary = this._isPrimary;
val._name = this._name;
return val;
}
getPoint(){
return this._point.clone();
}
getEntry(){
return this._entry;
}
getExit(){
return this._exit;
}
getName(){
return this._name;
}
isPrimary(){
return this._isPrimary;
}
toJSON(){
return {
point: this._point,
entry: this._entry,
exit: this._exit,
primary: this._isPrimary,
name: this._name
};
}
clone(){
return this.with();
}
}