featureLayerUtils.js 6.1 KB

12345
  1. /*
  2. All material copyright ESRI, All Rights Reserved, unless otherwise specified.
  3. See https://js.arcgis.com/4.25/esri/copyright.txt for details.
  4. */
  5. import{difference as e}from"../../core/arrayUtils.js";import t from"../../core/Error.js";import r from"../../core/Logger.js";import{isNone as a,isSome as o}from"../../core/maybe.js";import{debounce as s,eachAlways as l}from"../../core/promiseUtils.js";import{updateOrigins as i}from"../../core/accessorSupport/originUtils.js";import n from"../FeatureLayer.js";import{parse as u}from"../support/arcgisLayerUrl.js";import{fetchFeatureService as p}from"../support/fetchService.js";import{isFeatureCollectionLayer as c,isFeatureServiceLayer as y}from"../support/layerUtils.js";import d from"../../portal/Portal.js";import m from"../../portal/PortalItem.js";import{createForItemWrite as f}from"../../portal/support/jsonContext.js";import{addTypeKeyword as w,TypeKeyword as h,getWGS84ExtentForItem as v,removeTypeKeyword as b}from"../../portal/support/portalItemUtils.js";const I=r.getLogger("esri.layers.FeatureLayer"),S="Feature Service";function g(e,t){return`Layer (title: ${e.title}, id: ${e.id}) of type '${e.declaredClass}' ${t}`}function j(e,r){if(r.type!==S)throw new t("feature-layer:portal-item-wrong-type",g(e,`should have portal item of type "${S}"`))}async function L(e){if(await e.load(),c(e))throw new t("feature-layer:save",g(e,"using an in-memory source cannot be saved to a portal item"))}function P(e,r){let a=(e.messages??[]).filter((({type:e})=>"error"===e)).map((({name:e,message:r,details:a})=>new t(e,r,a)));if(r?.ignoreUnsupported&&(a=a.filter((({name:e})=>"layer:unsupported"!==e&&"symbol:unsupported"!==e&&"symbol-layer:unsupported"!==e&&"property:unsupported"!==e&&"url:unsupported"!==e))),a.length>0)throw new t("feature-layer:save","Failed to save feature layer due to unsupported or invalid content. See 'details.errors' for more detailed information",{errors:a})}async function J(e,t,r){"beforeSave"in e&&"function"==typeof e.beforeSave&&await e.beforeSave();const a=e.write({},t);return P(t,r),a}function N(e){const{layer:t,layerJSON:r}=e;return t.isTable?{layers:[],tables:[r]}:{layers:[r],tables:[]}}function O(e){w(e,h.JSAPI),e.typeKeywords&&(e.typeKeywords=e.typeKeywords.filter(((e,t,r)=>r.indexOf(e)===t)))}function E(e){const r=e.portalItem;if(!r)throw I.error("save: requires the portalItem property to be set"),new t("feature-layer:portal-item-not-set",g(e,"requires the portalItem property to be set"));if(!r.loaded)throw new t("feature-layer:portal-item-not-loaded",g(e,"cannot be saved to a portal item that does not exist or is inaccessible"));j(e,r)}async function T(e,t){return/\/\d+\/?$/.test(e.url??"")?N(t[0]):$(e,t)}async function $(e,t){const{layer:{url:r,customParameters:a,apiKey:o}}=t[0];let s=await e.fetchData("json");s&&null!=s.layers&&null!=s.tables||(s=await x(s,{url:r??"",customParameters:a,apiKey:o},t.map((e=>e.layer.layerId))));for(const l of t)K(l.layer,l.layerJSON,s);return s}async function x(e,t,r){var a,o;e||(e={}),(a=e).layers||(a.layers=[]),(o=e).tables||(o.tables=[]);const{url:s,customParameters:l,apiKey:i}=t,{serviceJSON:n,layersJSON:u}=await p(s,{customParameters:l,apiKey:i}),c=A(e.layers,n.layers,r),y=A(e.tables,n.tables,r);e.layers=c.itemResources,e.tables=y.itemResources;const d=[...c.added,...y.added],m=u?[...u.layers,...u.tables]:[];return await U(e,d,s,m),e}function A(t,r,a){const o=e(t,r,((e,t)=>e.id===t.id));t=t.filter((e=>!o.removed.some((t=>t.id===e.id))));const s=o.added.map((({id:e})=>({id:e})));return s.forEach((({id:e})=>{t.push({id:e})})),{itemResources:t,added:s.filter((({id:e})=>!a.includes(e)))}}async function U(e,t,r,o){const s=t.map((({id:e})=>new n({url:r,layerId:e,sourceJSON:o.find((({id:t})=>t===e))})));await l(s.map((e=>e.load()))),s.forEach((t=>{const{layerId:r,loaded:o,defaultPopupTemplate:s}=t;if(!o||a(s))return;K(t,{id:r,popupInfo:s.toJSON()},e)}))}function K(e,t,r){e.isTable?F(r.tables,t):F(r.layers,t)}function F(e,t){if(!e)return;const r=e.findIndex((({id:e})=>e===t.id));-1===r?e.push(t):e[r]=t}function R(e){const{portalItem:t}=e;return y(e)&&!e.dynamicDataSource&&!!t?.loaded&&t.type===S}async function D(e){if(!e?.length)throw new t("feature-layer-utils-saveall:missing-parameters","'layers' array should contain at least one feature layer");await Promise.all(e.map((e=>e.load())));for(const o of e)if(!R(o))throw new t("feature-layer-utils-saveall:invalid-parameters",`'layers' array should only contain layers or tables in a feature service loaded from 'Feature Service' item. ${g(o,"does not conform")}`,{layer:o});const r=e.map((e=>e.portalItem.id));if(new Set(r).size>1)throw new t("feature-layer-utils-saveall:invalid-parameters","All layers in the 'layers' array should be loaded from the same portal item");const a=e.map((e=>e.layerId));if(new Set(a).size!==a.length)throw new t("feature-layer-utils-saveall:invalid-parameters","'layers' array should contain only one instance each of layer or table in a feature service")}function _(e,t){var r,a;let o=m.from(t);return o.id&&(o=o.clone(),o.id=null),(r=o).type??(r.type=S),(a=o).portal??(a.portal=d.getDefault()),j(e,o),o}async function q(e,t){const{url:r,layerId:a,title:s,fullExtent:l,isTable:i}=e,n=u(r),p=o(n)&&"FeatureServer"===n.serverType;t.url=p?r:`${r}/${a}`,t.title||(t.title=s),t.extent=null,!i&&o(l)&&(t.extent=await v(l)),b(t,h.METADATA),b(t,h.MULTI_LAYER),w(t,h.SINGLE_LAYER),i&&w(t,h.TABLE),O(t)}async function z(e,t,r){const a=e.portal;await(a?._signIn()),await(a?.user?.addItem({item:e,data:t,folder:r?.folder}))}const C=s(M);async function M(e,t){await L(e),E(e);const r=e.portalItem,a=f(r),o=await J(e,a,t),s=await T(r,[{layer:e,layerJSON:o}]);return O(r),await r.update({data:s}),i(a),r}const Y=s((async(e,t)=>{await D(e);const r=e[0].portalItem,a=f(r),o=await Promise.all(e.map((e=>J(e,a,t)))),s=await T(r,e.map(((e,t)=>({layer:e,layerJSON:o[t]}))));return O(r),await r.update({data:s}),await Promise.all(e.slice(1).map((e=>e.portalItem.reload()))),i(a),r.clone()})),B=s(G);async function G(e,t,r){await L(e);const a=_(e,t),o=f(a),s=N({layer:e,layerJSON:await J(e,o,r)});return await q(e,a),await z(a,s,r),e.portalItem=a,i(o),a}export{C as save,Y as saveAll,B as saveAs};