From 79edf4ad60b3adc67a4df6b091646543d2481a9a Mon Sep 17 00:00:00 2001 From: Mark Cooney Date: Mon, 18 Dec 2017 16:12:33 -0800 Subject: [PATCH] Map Tour 2.10.0 --- MapTour/src/app/maptour-config.js | 4 +- MapTour/src/app/storymaps/builder/Builder.js | 360 ++++++------ .../builder/SettingsPopupTabExtent.js | 24 +- MapTour/src/app/storymaps/core/Core.js | 11 +- .../app/storymaps/maptour/builder/AddPopup.js | 14 +- .../builder/InitPopupViewHostedFSCreation.js | 2 +- .../storymaps/maptour/builder/PopupViewCSV.js | 16 +- .../maptour/builder/PopupViewGeoTag.js | 14 +- MapTour/src/app/storymaps/utils/Helper.js | 110 ++-- .../src/app/storymaps/utils/WebMapHelper.js | 24 +- MapTour/src/index.html | 10 +- MapTour/src/resources/nls/da/template.js | 2 +- MapTour/src/resources/nls/sl/template.js | 553 ++++++++++++++++++ MapTour/src/resources/nls/template.js | 1 + 14 files changed, 873 insertions(+), 272 deletions(-) create mode 100644 MapTour/src/resources/nls/sl/template.js diff --git a/MapTour/src/app/maptour-config.js b/MapTour/src/app/maptour-config.js index 8567e1a..9a5476b 100644 --- a/MapTour/src/app/maptour-config.js +++ b/MapTour/src/app/maptour-config.js @@ -190,8 +190,8 @@ APPCFG = { // Edit those to set a custom sharing or proxy URL // You have to edit those only if your webmap is deployed on Portal for ArcGIS instance and if you are not deploying the template on the Portal webserver // If you are using ArcGIS Online or deploying the template on a Portal instance, you don't have to edit those URL - DEFAULT_SHARING_URL: "//www.arcgis.com/sharing/content/items", - //DEFAULT_SHARING_URL: "//portal.internal.com/arcgis/sharing/content/items", + DEFAULT_SHARING_URL: "//www.arcgis.com/sharing/rest/content/items", + //DEFAULT_SHARING_URL: "//portal.internal.com/arcgis/sharing/rest/content/items", DEFAULT_PROXY_URL: "//www.arcgis.com/sharing/proxy" //DEFAULT_PROXY_URL: "//portal.internal.com/arcgis/sharing/proxy" }; diff --git a/MapTour/src/app/storymaps/builder/Builder.js b/MapTour/src/app/storymaps/builder/Builder.js index fe0a680..0828fc1 100644 --- a/MapTour/src/app/storymaps/builder/Builder.js +++ b/MapTour/src/app/storymaps/builder/Builder.js @@ -17,27 +17,27 @@ define(["esri/arcgis/Portal", "dojo/topic" ], function( - esriPortal, - WebApplicationData, - FeatureServiceManager, - BuilderPanel, - SettingsPopup, + esriPortal, + WebApplicationData, + FeatureServiceManager, + BuilderPanel, + SettingsPopup, MapTourHelper, - MapTourBuilderHelper, - Helper, - WebMapHelper, - lang, + MapTourBuilderHelper, + Helper, + WebMapHelper, + lang, array, - has, + has, arcgisUtils, - IdentityManager, + IdentityManager, esriRequest, Multipoint, topic ) { var _core = null; var _builderView = null; - + var _builderPanel = new BuilderPanel( $('#builderPanel'), saveAppThenWebmap, @@ -45,8 +45,8 @@ define(["esri/arcgis/Portal", builderGalleryCreationFirstSave ); var _settingsPopup = new SettingsPopup( - $('#settingsPopup'), - APPCFG.COLOR_SCHEMES, + $('#settingsPopup'), + APPCFG.COLOR_SCHEMES, APPCFG.HEADER_LOGO_URL ); @@ -54,10 +54,10 @@ define(["esri/arcgis/Portal", { _core = core; _builderView = builderView; - + $(document).ready(lang.hitch(this, function(){ console.log("maptour.builder.Builder - init"); - + if( ! Helper.getAppID(_core.isProd()) && ! app.isDirectCreation ) { console.error("maptour.builder.Builder - abort builder initialization, no appid supplied"); return; @@ -66,71 +66,71 @@ define(["esri/arcgis/Portal", console.log("maptour.builder.Builder - Builder start in direct creation mode"); else if ( app.isGalleryCreation ) console.log("maptour.builder.Builder - Builder start in gallery creation mode"); - + $("body").addClass("builder-mode"); - + _builderView.init(_settingsPopup); _builderPanel.init(_builderView); - + _settingsPopup.init(_builderView); _settingsPopup.initLocalization(); - - topic.subscribe("BUILDER_INCREMENT_COUNTER", _builderPanel.incrementSaveCounter); + + topic.subscribe("BUILDER_INCREMENT_COUNTER", _builderPanel.incrementSaveCounter); topic.subscribe("HEADER_EDITED", headerEdited); - + // Reload / close confirmation if there is unsaved change window.onbeforeunload = function (e) { e = e || window.event; - + if( ! _builderPanel.hasPendingChange() ) return; - + if (e) e.returnValue = i18n.viewer.builderJS.closeWithPendingChange; - + // Safari return i18n.viewer.builderJS.closeWithPendingChange; }; - + app.cleanApp = cleanApp; })); } - + function appInitComplete() { var storyTitle = "", itemTitle = ""; - + if ( WebApplicationData.getTitle() ) { storyTitle = WebApplicationData.getTitle().trim(); } - + if ( app.data.getAppItem() && app.data.getAppItem().title ) { itemTitle = app.data.getAppItem().title.trim(); } - + // The title may be inherited from the app or web map if ( ! storyTitle ) { storyTitle = itemTitle; - + if ( ! storyTitle ) { if ( app.data.getWebMapItem() && app.data.getWebMapItem().item && app.data.getWebMapItem().item.title ) { storyTitle = app.data.getWebMapItem().item.title.trim(); } } } - + app.builder.titleMatchOnLoad = itemTitle == storyTitle; - + // Handle reusing image/webmap title in fromScratch if ( app.isDirectCreation || app.isGalleryCreation ) { app.builder.titleMatchOnLoad = true; } - + _builderPanel.updateSharingStatus(); _builderView.appInitComplete(saveApp); } - + function resize(cfg) { _builderPanel.resize(); @@ -138,23 +138,23 @@ define(["esri/arcgis/Portal", if (app.data.getCurrentGraphic() && app.data.sourceIsEditable()) { app.builder.updateBuilderMoveable(app.data.getCurrentGraphic()); - + if (cfg.isMobileView) app.mapTips && app.builder.hidePinPopup(); - else + else app.mapTips && app.mapTips.show(); } } - + // // Header // - + function headerEdited(param) { // Title and subtile initially comes from the web map // They are saved in web app data only if they are edited - // So if they are never edited in the app, web map edition are reflected in the app + // So if they are never edited in the app, web map edition are reflected in the app if( param.src == "title" ) { if( param.value != app.data.getWebMapItem().item.title ) { if( param.value != WebApplicationData.getTitle() ) { @@ -176,33 +176,33 @@ define(["esri/arcgis/Portal", WebApplicationData.setSubtitle(""); } } - + // // Save // - + function saveAppThenWebmap(doNotOverwriteTitle) - { + { if ( ! app.portal ) { console.error("Fatal error - not signed in"); appSaveFailed("APP"); return; } - + app.portal.signIn().then( - function(){ + function(){ saveApp(doNotOverwriteTitle, function(response){ if (!response || !response.success) { appSaveFailed("APP"); return; } - + saveWebmap(function(response2){ if (!response2 || !response2.success) { appSaveFailed("WEBMAP"); return; } - + appSaveSucceeded({ success: true }); }); }); @@ -212,7 +212,7 @@ define(["esri/arcgis/Portal", } ); } - + function builderDirectCreationFirstSave(title, subtitle) { if ( ! app.portal ) { @@ -220,9 +220,9 @@ define(["esri/arcgis/Portal", appSaveFailed("APP"); return; } - + var uid = IdentityManager.findCredential(getPortalURL()).userId; - + // Create the app item app.data.setAppItem( lang.mixin( @@ -237,11 +237,11 @@ define(["esri/arcgis/Portal", } ) ); - + // Update the webmap item var webMapItem = app.data.getWebMapItem(); lang.mixin( - webMapItem.item, + webMapItem.item, { title: title, snippet: subtitle, @@ -251,8 +251,8 @@ define(["esri/arcgis/Portal", access: 'private' } ); - - // Not sure why but the JS API add those unnecessary properties that WPF runtime doesn't like at all + + // Not sure why but the JS API add those unnecessary properties that WPF runtime doesn't like at all try { delete webMapItem.itemData.operationalLayers[0].featureCollection.layers[0].id; delete webMapItem.itemData.operationalLayers[0].featureCollection.layers[0].opacity; @@ -261,37 +261,37 @@ define(["esri/arcgis/Portal", } catch(e){ } app.portal.signIn().then( - function(){ + function(){ saveWebmap(function(response){ if( ! response || ! response.success ) { appSaveFailed("WEBMAP"); return; } - + // Save the webmp id in the app definition WebApplicationData.setWebmap(response.id); - + // Update the webmap item var webMapItem = app.data.getWebMapItem(); lang.mixin( - webMapItem.item, + webMapItem.item, { id: response.id, item: response.item } ); - + // Save the app saveApp(true, function(response2){ if (!response2 || !response2.success) { appSaveFailed("APP"); return; } - + var baseUrl = document.location.protocol + '//' + document.location.host + document.location.pathname; if ( ! baseUrl.match(/index\.html$/) ) baseUrl += "index.html"; - + // Update the app item app.data.setAppItem( lang.mixin( @@ -303,20 +303,20 @@ define(["esri/arcgis/Portal", } ) ); - + // Save the app a second time saveApp(false, function(response3){ if (!response3 || !response3.success) { appSaveFailed("APP"); return; - } - + } + console.log('maptour.builder.Builder - firstSaveForDirectCreation - appid:', response3.id, ' webmap:', response.id); - + appSaveSucceeded({ success: true }); app.isDirectCreationFirstSave = false; _builderPanel.updateSharingStatus(); - + History.replaceState({}, "", "index.html?appid=" + response3.id + "&edit"); }); }); @@ -327,7 +327,7 @@ define(["esri/arcgis/Portal", } ); } - + function builderGalleryCreationFirstSave() { if ( ! app.portal ) { @@ -335,13 +335,13 @@ define(["esri/arcgis/Portal", appSaveFailed("APP"); return; } - + var uid = IdentityManager.findCredential(getPortalURL()).userId; - + // Update the webmap item var webMapItem = app.data.getWebMapItem(); lang.mixin( - webMapItem.item, + webMapItem.item, { title: app.data.getAppItem().title, uploaded: Date.now(), @@ -349,12 +349,12 @@ define(["esri/arcgis/Portal", owner: uid } ); - + // Save the webmap in the same folder than the app if( app.data.getAppItem().ownerFolder ) webMapItem.item.ownerFolder = app.data.getAppItem().ownerFolder; - - // Not sure why but the JS API add those unnecessary properties that WPF runtime doesn't like at all + + // Not sure why but the JS API add those unnecessary properties that WPF runtime doesn't like at all try { delete webMapItem.itemData.operationalLayers[0].featureCollection.layers[0].id; delete webMapItem.itemData.operationalLayers[0].featureCollection.layers[0].opacity; @@ -363,61 +363,61 @@ define(["esri/arcgis/Portal", } catch(e){ } app.portal.signIn().then( - function(){ + function(){ saveWebmap(function(response){ if( ! response || ! response.success || ! response.id ) { appSaveFailed("WEBMAP"); return; } - + // Save the webmp id in the app definition WebApplicationData.setWebmap(response.id); - + // Update the webmap item var webMapItem = app.data.getWebMapItem(); lang.mixin( - webMapItem.item, + webMapItem.item, { id: response.id, item: response.item } ); - + // Save the app saveApp(false, function(response2){ if (!response2 || !response2.success) { appSaveFailed("APP"); return; } - + var successCallback = function() { console.log('maptour.builder.Builder - builderGalleryCreationFirstSave - appid:', response2.id, ' webmap:', response.id); - + appSaveSucceeded({ success: true }); app.isGalleryCreation = false; _builderPanel.updateSharingStatus(); - + History.replaceState({}, "", "index.html?appid=" + response2.id + "&edit"); }; - + // Share the webmap and eventual FS if the app isn't private var sharingMode = app.data.getAppItem().access; if( sharingMode != 'private' ) { var targetItems = [app.data.getWebMapItem().item.id]; - if ( app.data.sourceIsFS() && app.data.getFSSourceLayerItemId() ) + if ( app.data.sourceIsFS() && app.data.getFSSourceLayerItemId() ) targetItems.push(app.data.getFSSourceLayerItemId()); - + shareItems(targetItems.join(','), sharingMode).then(function(response){ - var success = response - && response.results + var success = response + && response.results && response.results.length == targetItems.length; - + if (success) { $.each(response.results, function(i, result){ if( ! result.success ) success = false; }); - + if ( success ) successCallback(); else @@ -437,7 +437,7 @@ define(["esri/arcgis/Portal", } ); } - + // // Web mapping application save // @@ -445,7 +445,7 @@ define(["esri/arcgis/Portal", function saveApp(doNotOverwriteTitle, nextFunction) { var portalUrl = getPortalURL(), - appItem = lang.clone(app.data.getAppItem()), + appItem = lang.clone(app.data.getAppItem()), uid = appItem.owner || IdentityManager.findCredential(portalUrl).userId, token = IdentityManager.findCredential(portalUrl).token; @@ -456,90 +456,90 @@ define(["esri/arcgis/Portal", delete appItem.numRatings; delete appItem.numViews; delete appItem.size; - + // // Add/edit the typeKeyword property to be able to identify the app and the layout // - + if ( ! appItem.typeKeywords ) appItem.typeKeywords = []; - + // App not created through the builder fromScratch mode don't get those keywords appItem.typeKeywords = appItem.typeKeywords.concat(APPCFG.WEBAPP_KEYWORD_APP); - + // Those should only be necessary to be able to convert an appid that wasn't already selfConfigured appItem.typeKeywords = appItem.typeKeywords.concat(APPCFG.WEBAPP_KEYWORD_GENERIC); - + // Layout var layouts = $.map(['integrated', 'three-panel'], function(layout){ return "layout-" + layout; }); // Filter previous layout keyword appItem.typeKeywords = $.grep(appItem.typeKeywords, function(keyword) { - return $.inArray(keyword, layouts) == -1; + return $.inArray(keyword, layouts) == -1; }); // Add actual layout keyword appItem.typeKeywords.push("layout-" + (app.data.getWebAppData().values.layout || "three-panel")); - + // Make the typeKeywords array unique appItem.typeKeywords = $.grep(appItem.typeKeywords, function(keyword, index) { return index == $.inArray(keyword, appItem.typeKeywords); }); - + // Transform arrays appItem.tags = appItem.tags ? appItem.tags.join(',') : ''; appItem.typeKeywords = appItem.typeKeywords.join(','); - + // App proxies appItem.serviceProxyParams = JSON.stringify(appItem.serviceProxyParams); - + // Story extent if ( app.data.getTourLayer() && app.data.getTourLayer().graphics && app.data.getTourLayer().graphics.length ) { try { var sr = app.data.getTourLayer().graphics[0].geometry.spatialReference; - + if ( sr && (sr.wkid == 102100 || sr.wkid == 4326) ) { - var mp = new Multipoint(sr); - - $.each(app.data.getTourLayer().graphics, function(i, g){ - mp.addPoint(g.geometry); - }); - + var mp = new Multipoint(sr); + + $.each(app.data.getTourLayer().graphics, function(i, g){ + mp.addPoint(g.geometry); + }); + // TODO: serializeExtentToItem only support WGS and Mercator appItem.extent = JSON.stringify(Helper.serializeExtentToItem(mp.getExtent())); } - + } catch( e ) { } } - + // Title if ( ! doNotOverwriteTitle ) { appItem.title = WebApplicationData.getTitle(); } - if ( appItem.properties ) { + if ( appItem.properties ) { appItem.properties = JSON.stringify(appItem.properties); } - + // Edit URL of hosted apps to always include index.html if ( appItem.url && appItem.url.match(/apps\/[a-zA-Z]+\/\?appid=/) ) { appItem.url = appItem.url.replace('/?appid=', '/index.html?appid='); } - + appItem = lang.mixin(appItem, { f: "json", token: token, overwrite: true, text: JSON.stringify(WebApplicationData.get()) }); - - var url = portalUrl + "/sharing/content/users/" + uid + (appItem.ownerFolder ? ("/" + appItem.ownerFolder) : ""); - + + var url = portalUrl + "/sharing/rest/content/users/" + uid + (appItem.ownerFolder ? ("/" + appItem.ownerFolder) : ""); + // Updating if ( appItem.id ) url += "/items/" + appItem.id + "/update"; // creating else url += "/addItem"; - + var saveRq = esriRequest( { url: url, @@ -550,23 +550,23 @@ define(["esri/arcgis/Portal", usePost: true } ); - + saveRq.then(nextFunction, appSaveFailed); } - + // // Web Map save // - + function saveWebmap(nextFunction) { // // TODO: should be replaced by the improved WebMapHelper.saveWebmap // - + // Store data when the map tour data layer is a feature collection saved as an item var fcItem = null; - + // Look for modified or new points if the tour use an embedded layer var webmapEmbeddedLayerChange = false; if( app.data.sourceIsWebmap() ) { @@ -574,18 +574,18 @@ define(["esri/arcgis/Portal", if( tourPoint.hasBeenUpdated() ) webmapEmbeddedLayerChange = true; }); - + if( app.data.getDroppedPoints().length || app.data.pointsAdded() ) webmapEmbeddedLayerChange = true; } - - // If the extent or data has changed + + // If the extent or data has changed // or it's a direct creation initial save // or the basemap has changed - if( app.data.initialExtentHasBeenEdited - || webmapEmbeddedLayerChange - || app.isDirectCreationFirstSave - || app.isGalleryCreation + if( app.data.initialExtentHasBeenEdited + || webmapEmbeddedLayerChange + || app.isDirectCreationFirstSave + || app.isGalleryCreation || app.basemapChanged ) { var portalUrl = getPortalURL(), @@ -593,7 +593,7 @@ define(["esri/arcgis/Portal", itemData = app.data.getWebMapItem().itemData, uid = item.owner || IdentityManager.findCredential(portalUrl).userId, token = IdentityManager.findCredential(portalUrl).token; - + // Data change if( webmapEmbeddedLayerChange ) { // Find the index of the layer in the webmap definition @@ -602,20 +602,20 @@ define(["esri/arcgis/Portal", if( layer.id == app.data.getSourceLayer().id.split('_').slice(0,-1).join('_') ) layerIndex = i; }); - + var layer = itemData.operationalLayers[layerIndex], data = serializeMapTourGraphicsLayerToFeatureCollection( - app.data.getTourLayer(), app.data.getAllFeatures(), + app.data.getTourLayer(), app.data.getAllFeatures(), app.data.getSourceLayer() ); - + // If the map tour data layer is a feature collection saved as an item if ( layer.itemId ){ fcItem = { id: layer.itemId, data: data }; - + if ( layer.featureCollection ) { delete layer.featureCollection; } @@ -626,27 +626,27 @@ define(["esri/arcgis/Portal", layer.featureCollection = data; } } - + // Cleanup item data WebMapHelper.prepareWebmapItemForCloning({ itemData: itemData }); - + // Transform arrays item.tags = item.tags ? item.tags.join(',') : ''; item.typeKeywords = item.typeKeywords ? item.typeKeywords.join(',') : ''; - + // Check layers for app proxies URL var layersToCheck = itemData.baseMap.baseMapLayers.concat(itemData.operationalLayers); $.each(layersToCheck, function(i, layer){ if ( layer.url ) { - var matchingAppProxiesLayer = $.grep(app.data.getAppProxies() || [], function(l){ - return l && l.mixin && l.mixin.url == layer.url; + var matchingAppProxiesLayer = $.grep(app.data.getAppProxies() || [], function(l){ + return l && l.mixin && l.mixin.url == layer.url; }); - + if ( matchingAppProxiesLayer.length ) layer.url = matchingAppProxiesLayer[0].url; } }); - + var rqData = { f: 'json', item: item.item, @@ -661,16 +661,16 @@ define(["esri/arcgis/Portal", thumbnailURL: item.thumbnailURL, token: token }; - - var url = portalUrl + "/sharing/content/users/" + uid + (item.ownerFolder ? ("/" + item.ownerFolder) : ""); - + + var url = portalUrl + "/sharing/rest/content/users/" + uid + (item.ownerFolder ? ("/" + item.ownerFolder) : ""); + // Updating if ( item.id ) url += "/items/" + item.id + "/update"; // creating else url += "/addItem"; - + var saveRq = esriRequest( { url: url, @@ -681,7 +681,7 @@ define(["esri/arcgis/Portal", usePost: true } ); - + saveRq.then( function(response){ app.basemapChanged = false; @@ -706,19 +706,19 @@ define(["esri/arcgis/Portal", appSaveFailed(); return; } - + var ownerFolder = responseItem.item.ownerFolder; - + var rqData = { f: 'json', text: JSON.stringify(fcItem.data), overwrite: true, token: token }; - - var url = portalUrl + "/sharing/content/users/" + uid + (ownerFolder ? ("/" + ownerFolder) : "") + "/items/" + fcItem.id + "/update"; + + var url = portalUrl + "/sharing/rest/content/users/" + uid + (ownerFolder ? ("/" + ownerFolder) : "") + "/items/" + fcItem.id + "/update"; // Need to know the folder because for some reason, the following request don't works - //var url = portalUrl + "/sharing/rest/content/items/" + fcItem.id + "/update"; + //var url = portalUrl + "/sharing/rest/content/items/" + fcItem.id + "/update"; var saveRq = esriRequest( { url: url, @@ -729,7 +729,7 @@ define(["esri/arcgis/Portal", usePost: true } ); - + saveRq.then( function(){ nextFunction(response); @@ -761,34 +761,34 @@ define(["esri/arcgis/Portal", else nextFunction({success: true}); } - + function serializeMapTourGraphicsLayerToFeatureCollection(tourLayer, tourGraphics, sourceLayer) { var graphics = []; var droppedPoints = app.data.getDroppedPoints(); - + $.each(tourGraphics, function(i, graphic){ // Do not save the graphic if it's in dropped points if( $.inArray(graphic, droppedPoints) == -1 ) graphics.push(graphic.getUpdatedFeature()); }); - + return WebMapHelper._serializeGraphicsLayerToFeatureCollection(sourceLayer, tourLayer.visible, graphics); } - + // // Sharing // - + function shareAppAndWebmap(sharingMode, callback) { // Can only be used to add more privilege - // Looks like sharing to private imply a unshareItems request first + // Looks like sharing to private imply a unshareItems request first // => don't use it that code to share private without more test if ( sharingMode != "public" && sharingMode != "account" ) sharingMode = "public"; - - // Find items to share - only if they aren't already shared to the proper level + + // Find items to share - only if they aren't already shared to the proper level var targetItems = []; if( sharingMode == "account" ) { if( (app.data.getWebMapItem().item.access == "private"||app.data.getWebMapItem().item.access == "shared"||!app.data.getWebMapItem().item.access) && app.data.getWebMapItem().item.owner == app.portal.getPortalUser().username ) @@ -802,32 +802,32 @@ define(["esri/arcgis/Portal", if ( app.data.getAppItem().access != "public" ) targetItems.push(app.data.getAppItem().id); } - + // Also update eventual FS if needed // TODO: no check if user is the owner or not - if ( app.data.sourceIsFS() && app.data.getFSSourceLayerItemId() ) + if ( app.data.sourceIsFS() && app.data.getFSSourceLayerItemId() ) targetItems.push(app.data.getFSSourceLayerItemId()); - + shareItems(targetItems.join(','), sharingMode).then(function(response){ - var success = response - && response.results + var success = response + && response.results && response.results.length == targetItems.length; - + if (success) { $.each(response.results, function(i, result){ if( ! result.success ) success = false; }); - + app.data.getWebMapItem().item.access = sharingMode; app.data.getAppItem().access = sharingMode; _builderPanel.updateSharingStatus(); } - + callback(success); - }); + }); } - + function shareItems(items, sharing) { var portalUrl = getPortalURL(), @@ -842,7 +842,7 @@ define(["esri/arcgis/Portal", everyone: '', account: '' }; - + if ( sharing == "public" ) params.everyone = true; if ( sharing == "account" ) @@ -850,7 +850,7 @@ define(["esri/arcgis/Portal", return esriRequest( { - url: portalUrl + "/sharing/content/users/" + uid + "/shareItems", + url: portalUrl + "/sharing/rest/content/users/" + uid + "/shareItems", handleAs: 'json', content: params }, @@ -878,23 +878,23 @@ define(["esri/arcgis/Portal", { _builderPanel.saveFailed(source, error); } - + // // Misc // - + function getPortalURL() { return arcgisUtils.arcgisUrl.split('/sharing/')[0]; } - + function cleanApp() { if ( ! app.portal ) { console.error("Fatal error - not signed in"); return; } - + app.portal.signIn().then( function(){ var portalUrl = getPortalURL(), @@ -919,7 +919,7 @@ define(["esri/arcgis/Portal", var saveRq = esriRequest( { - url: portalUrl + "/sharing/content/users/" + uid + (appItem.ownerFolder ? ("/" + appItem.ownerFolder) : "") + "/addItem", + url: portalUrl + "/sharing/rest/content/users/" + uid + (appItem.ownerFolder ? ("/" + appItem.ownerFolder) : "") + "/addItem", handleAs: 'json', content: appItem }, @@ -927,7 +927,7 @@ define(["esri/arcgis/Portal", usePost: true } ); - + saveRq.then( function(){ console.log("Web Application data cleaned successfully"); @@ -940,10 +940,10 @@ define(["esri/arcgis/Portal", console.error("Web Application data cleaning has failed", error); } ); - + return "Cleaning ..."; } - + return { init: init, resize: resize, @@ -951,4 +951,4 @@ define(["esri/arcgis/Portal", shareAppAndWebmap: shareAppAndWebmap }; } -); \ No newline at end of file +); diff --git a/MapTour/src/app/storymaps/builder/SettingsPopupTabExtent.js b/MapTour/src/app/storymaps/builder/SettingsPopupTabExtent.js index c62bfe1..07d5b13 100644 --- a/MapTour/src/app/storymaps/builder/SettingsPopupTabExtent.js +++ b/MapTour/src/app/storymaps/builder/SettingsPopupTabExtent.js @@ -212,16 +212,22 @@ define(["storymaps/utils/Helper", _extentMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId))); if(!basemap) basemap = app.map.getLayer(layerId); - } else if(app.map.getLayer(layerId).url == bmLayer.styleUrl){ - _extentMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); - if(!basemap) - basemap = app.map.getLayer(layerId); + } else if(app.map.getLayer(layerId).url && bmLayer.styleUrl){ + var parser1 = document.createElement('a'); + parser1.href = app.map.getLayer(layerId).url; + var parser2 = document.createElement('a'); + parser2.href = bmLayer.styleUrl; + if(parser1.hostname + parser1.pathname == parser2.hostname + parser2.pathname){ + _extentMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); + if(!basemap) + basemap = app.map.getLayer(layerId); + } } }); }); } - if (extent.spatialReference.wkid != basemap.spatialReference.wkid) { + if (basemap && extent.spatialReference.wkid != basemap.spatialReference.wkid) { esriConfig.defaults.geometryService.project([extent], basemap.spatialReference).then(function(features){ if (features && features[0]) { _projectedExtent = features[0]; @@ -229,6 +235,14 @@ define(["storymaps/utils/Helper", _extentMap.addLayer(extentLayer); } }); + } else if(!basemap && app.data.getWebMapItem().itemData.baseMap.baseMapLayers[0].type == "VectorTileLayer"){ + esriConfig.defaults.geometryService.project([extent], app.data.getWebMapItem().itemData.spatialReference).then(function(features){ + if (features && features[0]) { + _projectedExtent = features[0]; + extentLayer.add(createExtentGraphics(features[0])); + _extentMap.addLayer(extentLayer); + } + }); } else { extentLayer.add(createExtentGraphics(extent)); diff --git a/MapTour/src/app/storymaps/core/Core.js b/MapTour/src/app/storymaps/core/Core.js index 049f109..60a28b1 100644 --- a/MapTour/src/app/storymaps/core/Core.js +++ b/MapTour/src/app/storymaps/core/Core.js @@ -184,7 +184,7 @@ define(["esri/map", // Get the portal instance name var instance = location.pathname.substr(0,appLocation); - configOptions.sharingurl = "//" + location.host + instance + "/sharing/content/items"; + configOptions.sharingurl = "//" + location.host + instance + "/sharing/rest/content/items"; configOptions.proxyurl = "//" + location.host + instance + "/sharing/proxy"; } else @@ -233,7 +233,7 @@ define(["esri/map", // Get portal info and configure the app esriRequest({ - url: arcgisUtils.arcgisUrl.split('/sharing/')[0] + "/sharing/rest/portals/self", + url: arcgisUtils.arcgisUrl.split('/sharing/')[0] + "/sharing/portals/self", content: {"f": "json"}, callbackParamName: "callback" }).then(lang.hitch(this, function(response){ @@ -282,6 +282,11 @@ define(["esri/map", if( response.isPortal && ! response.supportsSceneServices && ! response.supportsHostedServices) APPCFG.AUTHORIZED_IMPORT_SOURCE.featureService = false; + // Not common, but some systems might be set up as a managed egdb instead of an arcgis data store. See here for more info: + // https://devtopia.esri.com/WebGIS/arcgis-for-server/issues/4741#issuecomment-973189 + if( response.isPortal && !response.hasRelationalArcGISDataStore ) + APPCFG.AUTHORIZED_IMPORT_SOURCE.featureService = false; + // Disable feature service creation as Portal for ArcGIS 10.2 doesn't support that yet //if( response.isPortal && APPCFG && APPCFG.AUTHORIZED_IMPORT_SOURCE ) //APPCFG.AUTHORIZED_IMPORT_SOURCE.featureService = false; @@ -403,7 +408,7 @@ define(["esri/map", }); // Pass cookie onto API to avoid infinite redirects - IdentityManager.checkSignInStatus(app.org.url); + IdentityManager.checkSignInStatus(app.org.url+'/sharing/rest/'); // If forceLogin parameter in URL OR builder if ( forceLogin || app.isInBuilderMode ) diff --git a/MapTour/src/app/storymaps/maptour/builder/AddPopup.js b/MapTour/src/app/storymaps/maptour/builder/AddPopup.js index 83eb75a..264cfa1 100644 --- a/MapTour/src/app/storymaps/maptour/builder/AddPopup.js +++ b/MapTour/src/app/storymaps/maptour/builder/AddPopup.js @@ -946,10 +946,16 @@ define(["esri/dijit/Search", _map.addLayer(Helper.cloneLayer(app.map.getLayer(layerId))); if(!basemap) basemap = app.map.getLayer(layerId); - } else if(app.map.getLayer(layerId).url == bmLayer.styleUrl){ - _map.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); - if(!basemap) - basemap = app.map.getLayer(layerId); + } else if(app.map.getLayer(layerId).url && bmLayer.styleUrl){ + var parser1 = document.createElement('a'); + parser1.href = app.map.getLayer(layerId).url; + var parser2 = document.createElement('a'); + parser2.href = bmLayer.styleUrl; + if(parser1.hostname + parser1.pathname == parser2.hostname + parser2.pathname){ + _map.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); + if(!basemap) + basemap = app.map.getLayer(layerId); + } } }); }); diff --git a/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js b/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js index 3cd9a8a..c2a1159 100644 --- a/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js +++ b/MapTour/src/app/storymaps/maptour/builder/InitPopupViewHostedFSCreation.js @@ -65,7 +65,7 @@ define([ }, "layers": [{ "id": 0, - "name": "arcgis.arcgis.MAP_TOUR", + "name": "MAP_TOUR", "type": "Feature Layer", "description": "", "copyrightText": "", diff --git a/MapTour/src/app/storymaps/maptour/builder/PopupViewCSV.js b/MapTour/src/app/storymaps/maptour/builder/PopupViewCSV.js index cea31fe..3f5d108 100644 --- a/MapTour/src/app/storymaps/maptour/builder/PopupViewCSV.js +++ b/MapTour/src/app/storymaps/maptour/builder/PopupViewCSV.js @@ -428,15 +428,21 @@ define(["storymaps/utils/Helper", if(app.data.getWebMapItem() && app.data.getWebMapItem().itemData.baseMap){ $.each(app.data.getWebMapItem().itemData.baseMap.baseMapLayers, function(i, bmLayer){ $.each(app.map.layerIds, function(i, layerId){ - var basemap; - if(app.map.getLayer(layerId).url == bmLayer.url){ + var basemap; + if(app.map.getLayer(layerId).url && bmLayer.url){ _csvMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId))); if(!basemap) basemap = app.map.getLayer(layerId); } else if(app.map.getLayer(layerId).url == bmLayer.styleUrl){ - _csvMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); - if(!basemap) - basemap = app.map.getLayer(layerId); + var parser1 = document.createElement('a'); + parser1.href = app.map.getLayer(layerId).url; + var parser2 = document.createElement('a'); + parser2.href = bmLayer.styleUrl; + if(parser1.hostname + parser1.pathname == parser2.hostname + parser2.pathname){ + _csvMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); + if(!basemap) + basemap = app.map.getLayer(layerId); + } } }); }); diff --git a/MapTour/src/app/storymaps/maptour/builder/PopupViewGeoTag.js b/MapTour/src/app/storymaps/maptour/builder/PopupViewGeoTag.js index 7ee7400..a773506 100644 --- a/MapTour/src/app/storymaps/maptour/builder/PopupViewGeoTag.js +++ b/MapTour/src/app/storymaps/maptour/builder/PopupViewGeoTag.js @@ -248,14 +248,20 @@ define(["storymaps/maptour/core/MapTourHelper", $.each(app.data.getWebMapItem().itemData.baseMap.baseMapLayers, function(i, bmLayer){ $.each(app.map.layerIds, function(i, layerId){ var basemap; - if(app.map.getLayer(layerId).url == bmLayer.url){ + if(app.map.getLayer(layerId).url && bmLayer.url){ _geotagMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId))); if(!basemap) basemap = app.map.getLayer(layerId); } else if(app.map.getLayer(layerId).url == bmLayer.styleUrl){ - _geotagMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); - if(!basemap) - basemap = app.map.getLayer(layerId); + var parser1 = document.createElement('a'); + parser1.href = app.map.getLayer(layerId).url; + var parser2 = document.createElement('a'); + parser2.href = bmLayer.styleUrl; + if(parser1.hostname + parser1.pathname == parser2.hostname + parser2.pathname){ + _geotagMap.addLayer(Helper.cloneLayer(app.map.getLayer(layerId), bmLayer)); + if(!basemap) + basemap = app.map.getLayer(layerId); + } } }); }); diff --git a/MapTour/src/app/storymaps/utils/Helper.js b/MapTour/src/app/storymaps/utils/Helper.js index 6f89cce..ab6167f 100644 --- a/MapTour/src/app/storymaps/utils/Helper.js +++ b/MapTour/src/app/storymaps/utils/Helper.js @@ -1,5 +1,5 @@ -define(["dojo/cookie", - "dojo/has", +define(["dojo/cookie", + "dojo/has", "esri/arcgis/utils", "esri/urlUtils", "esri/geometry/webMercatorUtils", @@ -8,10 +8,11 @@ define(["dojo/cookie", "esri/geometry/Polygon", "esri/layers/ArcGISDynamicMapServiceLayer", "esri/layers/ArcGISTiledMapServiceLayer", - "esri/layers/OpenStreetMapLayer"], + "esri/layers/OpenStreetMapLayer", + "esri/layers/VectorTileLayer"], function( - cookie, - has, + cookie, + has, arcgisUtils, urlUtils, webMercatorUtils, @@ -20,19 +21,20 @@ define(["dojo/cookie", Polygon, ArcGISDynamicMapServiceLayer, ArcGISTiledMapServiceLayer, - OpenStreetMapLayer) + OpenStreetMapLayer, + VectorTileLayer) { /** * Helper * @class Helper - * + * * Collection of helper functions */ return { isMobile: function() { return navigator.userAgent.match(/iPhone|iPad|iPod/i) - || navigator.userAgent.match(/Android/i) + || navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/BlackBerry/i) || navigator.userAgent.match(/IEMobile/i); }, @@ -50,22 +52,22 @@ define(["dojo/cookie", var urlParams = urlUtils.urlToObject(document.location.search).query; if ( urlParams ) return urlParams; - + if( ! this.browserSupportHistory() && ! urlParams ) return urlUtils.urlToObject(document.location.hash).query || {}; - + return {}; }, getWebmapID: function(isProd) { var urlParams = this.getUrlParams(); - + if( configOptions && configOptions.webmap ) return configOptions.webmap; - + if ( this.isArcGISHosted() || ! isProd ) return urlParams.webmap; - + // Only authorize URL params outside of arcgis.com if a webmap owner is specified if( configOptions.authorizedOwners && configOptions.authorizedOwners.length > 0 && configOptions.authorizedOwners[0] ) return urlParams.webmap; @@ -73,20 +75,20 @@ define(["dojo/cookie", getAppID: function(isProd) { var urlParams = this.getUrlParams(); - + if( configOptions && configOptions.appid ) return configOptions.appid; - + if ( this.isArcGISHosted() || ! isProd ) return urlParams.appid; - + // Only authorize URL params outside of arcgis.com if a webmap/app owner is specified if( configOptions.authorizedOwners && configOptions.authorizedOwners.length > 0 && configOptions.authorizedOwners[0] ) return urlParams.appid; }, getSharingHost: function() { var urlParams = this.getUrlParams(); - + if (urlParams.sharinghost) { return '//' + urlParams.sharinghost; } @@ -108,21 +110,21 @@ define(["dojo/cookie", { if( ! item.extent || item.extent.length != 2 ) return null; - + var bottomLeft = webMercatorUtils.geographicToWebMercator( new Point( item.extent[0][0], item.extent[0][1] ) ); - + var topRight = webMercatorUtils.geographicToWebMercator( new Point( item.extent[1][0], item.extent[1][1] ) ); - + return new Extent({ xmax: topRight.x, xmin: bottomLeft.x, @@ -137,9 +139,9 @@ define(["dojo/cookie", { if( ! extent || ! extent.spatialReference ) return null; - + var extentWgs = extent.spatialReference.wkid == 4326 ? extent : webMercatorUtils.webMercatorToGeographic(extent); - + return [ [Math.round(extentWgs.xmin*10000)/10000, Math.round(extentWgs.ymin*10000)/10000], [Math.round(extentWgs.xmax*10000)/10000, Math.round(extentWgs.ymax*10000)/10000] @@ -147,7 +149,7 @@ define(["dojo/cookie", }, serializedExtentEquals: function(extent1, extent2) { - return extent1 + return extent1 && extent2 && extent1.length == extent2.length && extent1.length == 2 @@ -160,7 +162,7 @@ define(["dojo/cookie", * Clone Bing/OSM/Tile/Dynamic Map layer * Default to light grey canvas if bing or not tile/dynamic */ - cloneLayer: function(layer) + cloneLayer: function(layer, layerResponse) { if( layer.url && layer.url.match(/virtualearth\./) ) return new ArcGISTiledMapServiceLayer("//services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer"); @@ -170,7 +172,9 @@ define(["dojo/cookie", return new ArcGISDynamicMapServiceLayer(layer.url); else if (layer.id == "OpenStreetMap" || layer.id == "layer_osm" ) return new OpenStreetMapLayer(); - + else if (layerResponse && layerResponse.type == "VectorTileLayer") + return new VectorTileLayer(layer.url); + return new ArcGISTiledMapServiceLayer("//services.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Light_Gray_Base/MapServer"); }, extentToPolygon: function(extent) @@ -178,10 +182,10 @@ define(["dojo/cookie", var p = new Polygon(extent.spatialReference); p.addRing( [ - [extent.xmin, extent.ymin], - [extent.xmin, extent.ymax], - [extent.xmax, extent.ymax], - [extent.xmax, extent.ymin], + [extent.xmin, extent.ymin], + [extent.xmin, extent.ymax], + [extent.xmax, extent.ymax], + [extent.xmax, extent.ymin], [extent.xmin, extent.ymin] ] ); @@ -192,49 +196,49 @@ define(["dojo/cookie", var mapWidth = map.width; var mapHeight = map.height; var lods = map._params.lods; - + if ( ! lods ) return -1; - + for (var l = lods.length - 1; l >= 0; l--) { if( mapWidth * map._params.lods[l].resolution > extent.getWidth() && mapHeight * map._params.lods[l].resolution > extent.getHeight() ) return l; } - + return -1; }, getPortalUser: function() { var esriCookie = cookie('esri_auth'); - + if( ! esriCookie ) return; - + esriCookie = JSON.parse(esriCookie.replace('"ssl":undefined','"ssl":""')); - + // Cookie has to be set on the same organization - if( esriCookie.urlKey - && esriCookie.customBaseUrl + if( esriCookie.urlKey + && esriCookie.customBaseUrl && (esriCookie.urlKey + '.' + esriCookie.customBaseUrl).toLowerCase() != document.location.hostname.toLowerCase()) return; - + return esriCookie ? esriCookie.email : null; }, getPortalRole: function() { var esriCookie = cookie('esri_auth'); - + if( ! esriCookie ) return; - + esriCookie = JSON.parse(esriCookie.replace('"ssl":undefined','"ssl":""')); - + // If the cookie is not set on the same organization - if( esriCookie.urlKey - && esriCookie.customBaseUrl + if( esriCookie.urlKey + && esriCookie.customBaseUrl && (esriCookie.urlKey + '.' + esriCookie.customBaseUrl).toLowerCase() != document.location.hostname.toLowerCase()) return; - + return esriCookie ? esriCookie.role : null; }, getMyStoriesURL: function() @@ -262,9 +266,9 @@ define(["dojo/cookie", }, browserSupportAttachementUsingFileReader: function() { - return !! window.FileReader - && !! window.FormData - && !! this.browserSupportCanvas() + return !! window.FileReader + && !! window.FormData + && !! this.browserSupportCanvas() && !! window.Blob /*&& has("ie") != 10*/; // IE10 unexpectedly fail to do the addAttachment request (with CORS or proxy) }, @@ -277,7 +281,7 @@ define(["dojo/cookie", { if( ! window.FileReader ) return false; - + var f = new window.FileReader(); return !! ('readAsArrayBuffer' in f); }, @@ -293,7 +297,7 @@ define(["dojo/cookie", { if( has("ie") <= 8 ) return; - + $("