UNPKG

@arcgis/core

Version:

ArcGIS Maps SDK for JavaScript: A complete 2D and 3D mapping and data visualization API

3 lines (2 loc) • 21.6 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.0.8/LICENSE.txt */ import{__decorate as e}from"tslib";import t from"../../Graphic.js";import{remove as i}from"../../core/arrayUtils.js";import a from"../../core/Error.js";import{makeHandle as o}from"../../core/handleUtils.js";import r from"../../core/Logger.js";import{abortMaybe as s}from"../../core/maybe.js";import{createResolver as n,onAbort as l,createAbortError as d,throwIfAborted as c,debounce as p}from"../../core/promiseUtils.js";import u from"../../core/Queue.js";import{whenOnce as w,watch as h,sync as f,on as g,when as v}from"../../core/reactiveUtils.js";import{last as k}from"../../core/SetUtils.js";import{property as m,subclass as y}from"../../core/accessorSupport/decorators.js";import{getGraphicLayer as W}from"../../graphic/graphicOriginUtils.js";import{isEditableLayer as A}from"../../layers/support/editableLayers.js";import{isFeatureLayer as _,isSubtypeSublayer as b,isSubtypeGroupLayer as S,isTable as C}from"../../layers/support/layerUtils.js";import{createFeatureServices as M}from"../../rest/featureService/utils.js";import F from"../../views/draw/support/HighlightHelper.js";import{ViewEventPriorities as U}from"../../views/input/InputManager.js";import{temporaryHighlightName as R}from"../../views/support/HighlightDefaults.js";import E from"./CreateFeaturesWorkflow.js";import I from"./MergeFeaturesWorkflow.js";import j from"./SplitFeatureWorkflow.js";import V from"./UpdateFeaturesWorkflow.js";import{UpdateFeatureWorkflow as P}from"./UpdateFeatureWorkflow.js";import{UpdateRecordWorkflow as L}from"./UpdateRecordWorkflow.js";import N from"./UpdateWorkflowData.js";import O from"./Workflow.js";import{isFeatureFormViewModel as T,findEditorItemForLayer as x,isSplitFeatureWorkflow as D,workflowInfluencesOutcomeOfParent as H,isAnyUpdateLeafWorkflow as z,isUpdateRecordWorkflow as q,isParentWorkflow as G,findEditorItemForLayerOrThrow as Q,createWorkflowSteps as $,fetchCandidates as B,isUpdateFeaturesWorkflowOptions as J,toFeatureInfos as K,isMergeWorkflowOptions as X,isSplitWorkflowOptions as Y}from"./workflowUtils.js";import{assertFeaturesAreFromSameLayer as Z}from"./support/errors.js";import{findUtilityNetwork as ee,isGraphicForRelatableFeatureSupportedLayer as te}from"../Feature/support/featureUtils.js";var ie;let ae=ie=class extends O{constructor(e){super(e),this._workflowStack=new u(k),this._sketchStack=new u(k),this.data=void 0,this.type="update"}destroy(){this._drainWorkflowStack(e=>e.cancel({force:!0}))}get formViewModel(){return this.activeWorkflow?.formViewModel}get activeUtilityNetworkAssociationAddAssociationViewModel(){return"add-association"===this.activeWorkflow?.type?this.activeWorkflow.utilityNetworkAssociationAddAssociationViewModel:null}get activeSketchViewModel(){return this._sketchStack.peek()?.viewModel}get canDeleteAssociation(){const{formViewModel:e}=this;if(!this.activeWorkflow||!this.data.viewModel.view?.map||!T(e))return!1;const{activeAssociation:t,feature:i}=e;return!(!t||!i?.sourceLayer||!_(i?.sourceLayer)&&!b(i?.sourceLayer))}get activeWorkflow(){return this._workflowStack.last()}get updating(){return this._updatingHandles.updating||!!this.activeWorkflow?.updating}get hasPreviousStep(){const e=this.activeWorkflow?.formViewModel;return this._stepIndex>0||this.nestedWorkflowCount>1||this.activeWorkflow?.hasPreviousStep||"view"!==this.data.viewModel.attachmentsViewModel.mode||T(e)&&(null!=e.relationshipId||null!=e.associationId||null!=e.associatedLayer)}get hasUpdatableCandidates(){const{candidates:e,viewModel:t}=this.data;return e.some(({layer:e})=>x(t.editorItems,e)?.supportsUpdateWorkflow)}get nestedWorkflowCount(){return this._workflowStack.length}get shouldShowAttachments(){return this.activeWorkflow?.shouldShowAttachments??!1}get shouldAllowAttachmentEditing(){return this.activeWorkflow?.shouldAllowAttachmentEditing??!1}get hasPendingEdits(){return Array.from(this._workflowStack).some(e=>e.hasPendingEdits)}get helpMessage(){return this.activeWorkflow?.helpMessage?this.activeWorkflow.helpMessage:"awaiting-feature-to-update"===this.stepId?"select":void 0}get noticeMessage(){return this.activeWorkflow?.noticeMessage}get reliesOnOwnerAdminPrivileges(){return this.activeWorkflow?.reliesOnOwnerAdminPrivileges??!1}get hasInvalidFormTemplate(){return this.activeWorkflow?.hasInvalidFormTemplate??!1}get curveResizeDisabled(){return this.activeWorkflow?.curveResizeDisabled??!1}get curveUpdatesDisabled(){return this.activeWorkflow?.curveUpdatesDisabled??!1}async back(e=()=>Promise.resolve(!0)){const{activeWorkflow:t}=this,i=t?.formViewModel;if(T(i)){if(i?.activeRelationshipInput){const e=i.activeRelationshipInput;if(e.activeCategory)return void(e.activeCategory=null);if(null!=i.relationshipId)return void(i.relationshipId=null);if(e.showAllEnabled)return void(e.showAllEnabled=!1)}if("add-association"===t?.type){const{activeUtilityNetworkAssociationAddAssociationViewModel:e}=this;if(e?.filterOptionsVisible)return void(e.filterOptionsVisible=!1);e?.featureSpatialItems.length&&e.reset()}if(null!=i?.associatedLayer)return void(i.associatedLayer=null);if(null!=i?.associationId)return void(i.associationId=null)}if("create-features"===t?.type&&t.hasPreviousStep)await t.previous({cancelCurrentStep:!0});else{if(D(t)&&t.hasPreviousStep)return await t.back();if(t){if(t.hasPendingEdits){if(!await e())return}t.hasPreviousStep?await t.previous({cancelCurrentStep:!0}):await this.cancelActiveWorkflow({force:!0})}else this.hasPreviousStep?await this.previous({cancelCurrentStep:!0}):await this.cancel({force:!0})}}async cancelActiveWorkflow(e){await(this.activeWorkflow?.cancel(e)),await this._popWorkflowAndReconcile()}async commit(){await this._drainWorkflowStack(e=>e.commit()),await super.commit()}static create(e){const{startAt:t,applyEdits:i,applyEditsFeatureService:a,...o}=e,r=new ie({data:new N({applyEditsCallback:i,applyEditsFeatureServiceCallback:a,...o}),onCommit:async()=>{}});return r._set("steps",this._createWorkflowSteps(r,t)),r}async save(e){const{formViewModel:t}=this;if(t&&(t.submit(),!t.submittable||T(t)&&re(t)))return;if(this.nestedWorkflowCount<2)return await this.commit();const{activeWorkflow:i}=this;if(await(i?.commit(e)),!H(i))return void await this._popWorkflowAndReconcile();this._popWorkflow();const a=this._workflowStack.peek();if(a&&a===i?.parent&&(await a.cancel(),this._popWorkflow(),0===this.nestedWorkflowCount))return await this.commit();await this._reconcileWorkflowStack()}async startCreatingRelatedRecord(e){const t=this._makeUpdatingResolver();try{const t=this._createNestedCreateFeaturesWorkflow(e);await this._pushWorkflowAndReconcile(t)}catch(i){throw new a("editor:unable-to-start-creating","Could not begin updating the provided feature or table record.",{error:i})}finally{t.resolve()}}async startMergingFeatures(e,t){const i=this._makeUpdatingResolver();try{const i=await this._createNestedMergeFeaturesWorkflow(e,t);await this._pushWorkflowAndReconcile(i)}catch(o){throw new a("editor:unable-to-start-merging","Could not begin merging the provided features.",{error:o})}finally{i.resolve()}}async startSplittingFeature(e,t){const i=this._makeUpdatingResolver();try{const i=await this._createNestedSplitFeatureWorkflow(e,t);await this._pushWorkflowAndReconcile(i)}catch(o){throw new a("editor:unable-to-start-splitting","Could not begin splitting the provided feature.",{error:o})}finally{i.resolve()}}async startUpdatingSingle(e,t){const i=this._makeUpdatingResolver();try{const i=await this._createNestedUpdateWorkflow(e,t);await this._pushWorkflowAndReconcile(i)}catch(o){throw new a("editor:unable-to-start-updating","Could not begin updating the provided feature or table record.",{error:o})}finally{i.resolve()}}async startUpdatingMultiple(e,t){const i=this._makeUpdatingResolver();try{const i=await this._createNestedUpdateFeaturesWorkflow(e,t);await this._pushWorkflowAndReconcile(i)}catch(o){throw new a("editor:unable-to-start-updating","Could not begin updating the provided features or table records.",{error:o})}finally{i.resolve()}}async startAddAssociation(e,t,i){const o=this._makeUpdatingResolver();try{const a=await this._createNestedAddAssociationWorkflow(e,t,i);await this._pushWorkflowAndReconcile(a)}catch(r){throw new a("editor:unable-to-start-updating","Could not begin updating the provided feature or table record.",{error:r})}finally{o.resolve()}}async deleteActiveFeatures(){const{activeWorkflow:e}=this;if(!e)throw new a("editor:nothing-to-delete","There is no feature to delete");const t=z(e);if(t){e.data.stageDelete();const t=q(e)?e.data.edits.feature?[e.data.edits.feature]:[]:e.data.features;this._removeFeaturesFromCandidates(t)}else await e.cancel();this.nestedWorkflowCount<2?t?await this.commit():await this.cancel({force:!0}):(t&&await e.commit(),await this._popWorkflowAndReconcile(),await this._returnToPageWithContent())}async deleteActiveAssociation(){if(!this.canDeleteAssociation)throw new a("editor:nothing-to-delete","There is no association to delete");await this._deleteActiveAssociation(),await this._popWorkflowAndReconcile(),await this._returnToPageWithContent()}async cancelAll(){await this._drainWorkflowStack(e=>e.cancel({force:!0}))}async _deleteActiveAssociation(){const{formViewModel:e}=this;if(!T(e))throw new a("editing:failed-to-delete-association","The active workflow does not support editing associations");const{activeAssociation:t,feature:i}=e,{applyEditsFeatureServiceCallback:o,viewModel:r}=this.data,{sourceLayer:s}=i,n=b(s)&&s.parent?s.parent:s,l=M([n]),d=l.values().next().value?.featureService;if(!d)throw new a("editor:failed-to-delete-association","Could not retrieve feature service needed to delete association");await(d?.load());const c=r.view.map,p=ee(c,n);await(p?.networkSystemLayers.loadAssociationsTable());const u=p?.generateDeleteAssociations([t]);if(!u)throw new a("editor:failed-to-delete-association","Could not create payload needed to delete association");const w=p?.gdbVersion??void 0;await o(d,[u],{gdbVersion:w,globalIdUsed:!0})}_removeFeaturesFromCandidates(e){const{candidates:t}=this.data;if(0!==t.length&&0!==e.length)for(const a of e)i(t,a)}async _returnToPageWithContent(){const{formViewModel:e}=this;if(!T(e)||!e?.activeAssociationInput)return;const{activeAssociationInput:t,associationId:i}=e;await t.refresh(),t.associatedLayer&&!t.associatedFeatures?.length&&(e.associatedLayer=null),null==i||t.associatedFeatureInfos.size||(e.associationId=null)}_createNestedCreateFeaturesWorkflow(e){const{relatedLayer:t}=e,{addAttachmentsCallback:i,applyEditsCallback:o,applyEditsFeatureServiceCallback:r,sketchOptions:s,snappingManager:n,viewModel:l}=this.data;if(!A(t))throw new a("editor:unsupported-layer","Editing is not supported on the provided layer");const d=this._getCreationInfoForNestedCreateFeaturesWorkflow(e),c=d.template||d.initialFeature?"creating-features":"awaiting-feature-creation-info",p=G(this.activeWorkflow)?this.activeWorkflow:void 0;return E.create({addAttachmentsCallback:i,applyEdits:o,applyEditsFeatureService:r,creationInfo:d,isNested:!0,parent:p,sketchOptions:s,snappingManager:n,startAt:c,viewModel:l})}_getCreationInfoForNestedCreateFeaturesWorkflow(e){const{relatedLayer:i}=e;if(!A(i)||S(i))throw new a("editor:unsupported-layer","Editing is not supported on the provided layer");const{viewModel:o}=this.data,r={layer:i,maxFeatures:1},s=this._makeRelatedRecordAttributes(e),n=o.getTemplatesForLayer(i);return n?.length>0?(r.attributeOverrides=s,1===n.length&&(r.template=n[0])):r.initialFeature=new t({sourceLayer:i,attributes:s}),r}async _createNestedUpdateWorkflow(e,t={}){const i=C(e.sourceLayer)?L:P,{applyEditsCallback:a,applyEditsFeatureServiceCallback:o,sketchOptions:r,snappingManager:s,viewModel:n}=this.data,l=G(this.activeWorkflow)?this.activeWorkflow:void 0,d=await i.create({feature:e,parent:l,sketchOptions:r,snappingManager:s,viewModel:n,applyEdits:a,applyEditsFeatureService:o,featureFormCallbacks:{addRelatedRecord:e=>{this.startCreatingRelatedRecord(e)},editRelatedRecord:({relatedFeature:e,readOnly:t})=>{this.startUpdatingSingle(e,{readOnly:t})},selectAssociatedFeature:async({feature:e,association:t})=>await this.startUpdatingSingle(e,{association:t}),addAssociation:e=>{this.startAddAssociation(e.feature,e.utilityNetwork,e.associationType)}},...t});return await w(()=>!d.updating),d}async _createNestedUpdateFeaturesWorkflow(e,t={}){const{applyEditsCallback:i,applyEditsFeatureServiceCallback:a,viewModel:o}=this.data,r=V.create({applyEdits:i,applyEditsFeatureService:a,featureInfos:e,viewModel:o,...t});return await w(()=>!r.updating),r}async _createNestedAddAssociationWorkflow(e,t,i){const{AddAssociationWorkflow:o}=await import("./AddAssociationWorkflow.js"),{applyEditsCallback:r,applyEditsFeatureServiceCallback:s,viewModel:n}=this.data,l=G(this.activeWorkflow)?this.activeWorkflow:void 0,{formViewModel:d}=this,c=T(d)?d.activeAssociationInput:null;if(!c)throw new a("editing:unable-to-add-association","There is no active association input in the current workflow's form.");const p=await o.create({utilityNetwork:t,associationType:i,feature:e,parent:l,viewModel:n,associationInput:c,applyEdits:r,applyEditsFeatureService:s});return await w(()=>!p.updating),p}async _createNestedMergeFeaturesWorkflow(e,t){const{applyEditsCallback:i,applyEditsFeatureServiceCallback:a,viewModel:o}=this.data;Z(e);const r=Q(this.data.viewModel.editorItems,W(e[0])),s=G(this.activeWorkflow)?this.activeWorkflow:void 0,n=await I.create({applyEdits:i,applyEditsFeatureService:a,editorItem:r,features:e,parent:s,viewModel:o,...t});return await w(()=>!n.updating),n}async _createNestedSplitFeatureWorkflow(e,t){const{applyEditsCallback:i,applyEditsFeatureServiceCallback:a,sketchOptions:o,snappingManager:r,viewModel:s}=this.data,n=G(this.activeWorkflow)?this.activeWorkflow:void 0,l=Q(s.editorItems,e.sourceLayer),d=j.create({applyEdits:i,applyEditsFeatureService:a,editorItem:l,feature:e,parent:n,sketchOptions:o,snappingManager:r,viewModel:s,...t});return await w(()=>!d.updating),d}async _drainWorkflowStack(e){const t=this._workflowStack,i=[];for(const a of t){const t=e(a).finally(()=>a.destroy());this._updatingHandles.addPromise(t),i.push(t)}await Promise.all(i),this._workflowStack.clear(),this._sketchStack.clear()}_makeUpdatingResolver(){const e=n();return this._updatingHandles.addPromise(e.promise),e}_makeRelatedRecordAttributes(e){const{parentFeature:t,relatedLayer:i,relationshipId:a}=e;if(!te(t))return;const o=i.relationships?.find(e=>e.id===a);if(!o)return void this._logContinuingWithoutRelationshipWarning("relationship-not-found","Could not begin creating a related record because the relationship specified could not be found on the destination layer.");if("origin"===o.role)return void this._logContinuingWithoutRelationshipWarning("unsupported-role","Creating new related records in the 'origin' table of a relationship is not yet supported");const r=t.sourceLayer;o.relatedTableId!==r.layerId&&this._logContinuingWithoutRelationshipWarning("invalid-argument-combination","The given parent feature does not belong to the relationship designated by the given relationship ID.");const s=r.relationships?.find(e=>e.id===a);if(!s)return void this._logContinuingWithoutRelationshipWarning("relationship-not-found","Could not begin creating a related record because the relationship specified could not be found on the origin layer.");const n=oe(r,s),l=t.getAttribute(n);l||this._logContinuingWithoutRelationshipWarning("no-key-on-origin-feature","The given parent feature does not have a value for the relationship's origin primary key field.");const d=oe(i,o);return{[d]:l}}_popWorkflow(){this._workflowStack.pop()?.destroy(),this._sketchStack.pop()}async _popWorkflowAndReconcile(){this._popWorkflow();const e=await this._reconcileWorkflowStack();if(e.failureCount>0)throw new a("editor:next-workflow-failed","Popped the top workflow, but the next workflow in the stack failed to activate",e)}async _pushWorkflowAndReconcile(e){const t=this._workflowRequiresSketchViewModel(e);this.activeWorkflow?.exit({removeSketchHandles:t});const i=this._sketchStack,o=await(e?.start()),r=i.peek();o?(r?.exit(),i.push(o)):i.push(this._cloneSketchController(r)),this._workflowStack.push(e);const s=await this._reconcileWorkflowStack();if(s.failureCount>0)throw new a("editor:failed-to-start-updating-feature","Failed to enter the provided workflow.",s)}async _reconcileWorkflowStack(){const e=this._workflowStack,t=this._sketchStack;try{const i=e.peek();return await(i?.enter()),await(t.peek()?.enter()),{activeWorkflow:i,failureCount:0}}catch(i){e.pop().destroy(),t.pop();const{activeWorkflow:a,failureCount:o}=await this._reconcileWorkflowStack();return{activeWorkflow:a,failureCount:o+1}}}_cloneSketchController(e){return{enter:e?.enter??(async()=>{}),exit:e?.exit??(async()=>{}),viewModel:e?.viewModel}}_workflowRequiresSketchViewModel(e){const{type:t}=e;return"update-feature"===t||"create-features"===t&&!C(e.data.creationInfo?.layer)}static _createWorkflowSteps(e,t="awaiting-feature-to-update"){const{data:i}=e;return $(["awaiting-feature-to-update","awaiting-update-feature-candidate","editing-existing-feature","adding-attachment","editing-attachment"],t,{"awaiting-feature-to-update":()=>({id:"awaiting-feature-to-update",async setUp(){const{spinnerViewModel:t}=i.viewModel,a=i.viewModel.view;a.activeTool=null;let r=null;e.addHandles(o(()=>{r=s(r)}),this.id),i.rootFeatures.removeAll(),i.candidates=[];const p=a.on("immediate-click",async o=>{const s=n();e._updatingHandles.addPromise(s.promise);try{t.location=o.mapPoint,t.visible=!0,r?.abort();const{editorItems:s}=i.viewModel;r=new AbortController;const n=await o.defer(()=>new Promise((e,t)=>{l(r?.signal,()=>t(d())),e(B(s,a,o,r?.signal))}));if(c(r),i.candidates=n.filter(e=>"fulfilled"===e.status).flatMap(e=>e.value).filter(e=>!e.isAggregate),t.visible=1===i.candidates.length,0===i.candidates.length)return;if(o.stopPropagation(),1===i.candidates.length){const{rootFeatures:a}=i;a.removeAll(),a.add(i.candidates[0]),e.go("editing-existing-feature").catch(()=>{}).then(()=>t.visible=!1)}else e.next()}finally{s.resolve()}},U.TOOL),u=v(()=>null!=a.activeTool,()=>e.cancel({force:!0}),{once:!0});a.focus(),e.addHandles([p,u],this.id)},async tearDown(){0===i.candidates.length&&(i.viewModel.spinnerViewModel.visible=!1),e.removeHandles(this.id)}}),"awaiting-update-feature-candidate":()=>({id:"awaiting-update-feature-candidate",async setUp(){i.rootFeatures.removeAll();const{view:t}=i.viewModel;if(!t)return;const a=new F({view:t,highlightName:R});e.addHandles([g(()=>i.rootFeatures,"change",({added:e,removed:t})=>{t.forEach(e=>a.remove(e)),e.forEach(e=>a.add(e))},f),o(()=>a.removeAll())],this.id)},async tearDown(){e.removeHandles(this.id)}}),"editing-existing-feature":()=>({id:"editing-existing-feature",async setUp(){await se(e);const{data:t}=e;t.viewModel.spinnerViewModel.visible=!1;const i=p(async()=>{await w(()=>!e.updating),e.previous()});e.addHandles([h(()=>e.nestedWorkflowCount,(e,t)=>{0===e&&0!==t&&i()},f)],this.id)},async tearDown(){await e.cancelAll(),e.removeHandles(this.id)}}),"adding-attachment":()=>({id:"adding-attachment",parent:"editing-existing-feature",async setUp(){},async tearDown(){i.viewModel.attachmentsViewModel.mode="view"}}),"editing-attachment":()=>({id:"editing-attachment",parent:"editing-existing-feature",async setUp(){},async tearDown(){i.viewModel.attachmentsViewModel.mode="view"}})})}_logContinuingWithoutRelationshipWarning(e,t){r.getLogger(this).warn(`editor:${e}`,t,"The create operation will be allowed to proceed, but the resulting feature may not be related to the given parent feature.")}};function oe(e,{keyField:t}){return e.getField(t)?.name??t}function re(e){if(e.pendingSubtypeChoice)return!0;const t=e.getValues();return e.validateContingencyConstraints(t,{includeIncompleteViolations:!0}).length>0}async function se(e){const{data:t}=e,{rootWorkflowOptions:i}=t;if(J(i)){const{rootFeatureInfos:o}=t,r=o.length>0?o:K(t.rootFeatures.toArray());if(0===r.length)throw new a("editing:invalid-parameter","Must supply `rootFeatureInfos` or `rootFeatures` when root workflow type is 'update-multiple'");return await e.startUpdatingMultiple(r,i.props)}const{rootFeatures:o}=t,r=o.getItemAt(0);if(!r)throw new a("editor:no-feature-specified","Cannot setup the 'updating-existing-feature' step until one or more root features are provided");X(i)?await e.startMergingFeatures(o.toArray(),i.props):Y(i)?await e.startSplittingFeature(r,i.props):await e.startUpdatingSingle(r)}e([m()],ae.prototype,"formViewModel",null),e([m()],ae.prototype,"activeUtilityNetworkAssociationAddAssociationViewModel",null),e([m()],ae.prototype,"activeSketchViewModel",null),e([m()],ae.prototype,"canDeleteAssociation",null),e([m()],ae.prototype,"activeWorkflow",null),e([m()],ae.prototype,"updating",null),e([m()],ae.prototype,"data",void 0),e([m()],ae.prototype,"hasPreviousStep",null),e([m()],ae.prototype,"hasUpdatableCandidates",null),e([m()],ae.prototype,"nestedWorkflowCount",null),e([m()],ae.prototype,"shouldShowAttachments",null),e([m()],ae.prototype,"shouldAllowAttachmentEditing",null),e([m()],ae.prototype,"hasPendingEdits",null),e([m()],ae.prototype,"helpMessage",null),e([m()],ae.prototype,"noticeMessage",null),e([m()],ae.prototype,"reliesOnOwnerAdminPrivileges",null),e([m()],ae.prototype,"hasInvalidFormTemplate",null),e([m()],ae.prototype,"curveResizeDisabled",null),e([m()],ae.prototype,"curveUpdatesDisabled",null),ae=ie=e([y("esri.widgets.Editor.UpdateWorkflow")],ae);const ne=ae;export{ne as default};