UNPKG

@arcgis/map-components

Version:
259 lines (258 loc) • 8.96 kB
/* COPYRIGHT Esri - https://js.arcgis.com/5.1/LICENSE.txt */ import { forceInteractive as _ } from "@arcgis/core/applications/Components/analysisUtils.js"; import f from "@arcgis/core/core/Accessor.js"; import { property as o, subclass as V } from "@arcgis/core/core/accessorSupport/decorators.js"; import { ignoreAbortErrors as v } from "@arcgis/core/core/promiseUtils.js"; import { when as m, watch as w, on as A, whenOnce as g } from "@arcgis/core/core/reactiveUtils.js"; import { log as p } from "@arcgis/toolkit/log"; import { c as u, t as O, i as I, a as b } from "./async-utils.js"; import { a as h } from "./maybe.js"; import { getDefaultUnitForView as F } from "@arcgis/core/applications/Components/getDefaultUnits.js"; var T = Object.defineProperty, R = Object.getOwnPropertyDescriptor, n = (e, s, t, a) => { for (var r = a > 1 ? void 0 : a ? R(s, t) : s, l = e.length - 1, c; l >= 0; l--) (c = e[l]) && (r = (a ? c(s, t, r) : c(r)) || r); return a && r && T(s, t, r), r; }; const y = /* @__PURE__ */ Symbol("interactiveHandle"); let i = class extends f { // #region Lifecycle // Intentionally keep constructor side-effect free: callers may set properties in any order after instantiation. constructor() { super({}), this.operationState = "inactive", this._ownsAnalysis = !1, this.shouldForceInteractive = !0, this._changeFromReconnect = !1, this._userOperationInfo = null, this._loggedUnsupportedErrorMessage = !1; } initialize() { this._set("analysis", this.constructAnalysis()), this._ownsAnalysis = !0; const e = () => { !this._changeFromReconnect && !this._viewHasAnalysis && (this._ownsAnalysis = !1); const s = !this._changeFromReconnect; this._changeFromReconnect = !1, s && this._scheduleViewReconnect(); }; this.addHandles([ m( () => this.view?.ready && !this.supported, () => { this._loggedUnsupportedErrorMessage || p("error", this, this.unsupportedErrorMessage); }, { sync: !0, initial: !0 } ), w(() => [this.analysis, this._viewHasAnalysis], e, { sync: !0 }), A( () => this.view, "analysis-view-destroy", (s) => { s.analysis === this.analysis && e(); } ), w( () => ({ view: this.view, ready: !!this.view?.ready, supported: this.supported }), ({ view: s }, t) => { const a = t?.view; s !== a && (this._userOperationInfo = h(this._userOperationInfo), this._disconnectFromView(a)), this._scheduleViewReconnect(); }, { sync: !0, initial: !0 } ) ]); } destroy() { this._reconnectViewTask = h(this._reconnectViewTask), this._userOperationInfo = h(this._userOperationInfo), this.analysisView != null && (this.analysisView.visible = void 0), this._disconnectFromView(this.view), this._set("view", null), this._ownsAnalysis && this.analysis?.destroy(); } get defaultMeasurementSystem() { return this.view?.ready ? F(this.view) : "metric"; } get active() { return this._userOperationInfo?.state === "running"; } set analysis(e) { e !== this._get("analysis") && (this._userOperationInfo = h(this._userOperationInfo), this._disconnectFromView(this.view), this._setExternalAnalysis(e), this._scheduleViewReconnect()); } get connectingToView() { return !!this._reconnectViewTask; } get disabled() { return !this.view?.ready || !this.supported; } set hideVisualization(e) { this._set("hideVisualization", e), this.analysisView && (this.analysisView.visible = !e); } get ready() { return !!this.analysisView && !this.connectingToView; } get supported() { return !this.view || this.supportedViewType === "both" || this.view.type === this.supportedViewType; } get _viewHasAnalysis() { const { view: e } = this; return e?.analyses.includes(this.analysis) === !0; } // #endregion // #region Public Methods /** * Reset analysis inputs and cancel any active user operation. */ clear() { this._userOperationInfo = h(this._userOperationInfo), this.clearAnalysis(); } /** * Start the user operation. * * If the required analysis inputs are missing, this calls `place()` once the view is ready. You can provide a custom * `operation` to override the default behavior. Set `clear: false` to retain existing analysis inputs. */ async start(e) { if (this.hideVisualization) { p("warn", this, "Cannot start analysis when not visible"); return; } this.stop(), e?.clear !== !1 && this.clear(); const s = { task: null, abort: null, state: "pending" }, t = u(async (a) => { if (s.state = "wait-for-view-ready", await g(() => this.ready, a), s.state = "running", !this.analysisView || !this.view) return; this.operationState = "active"; const r = e?.operation?.({ signal: a }) ?? this.place({ signal: a }); await v(r); }); return t.promise.finally(() => { (this._userOperationInfo === s || !this._userOperationInfo) && (this.operationState = "inactive"); }), s.task = t, s.abort = () => t.abort(), this._userOperationInfo = s, await t.promise; } /** * Stop the active user operation, if any. */ stop() { this._userOperationInfo = h(this._userOperationInfo); } // #endregion // #region Private/Protected Methods /** * Define the interactive placement workflow for the analysis. * Implement in subclasses to collect required inputs. Honor `AbortSignal`. */ place(e) { throw new Error("place() not implemented for this analysis view model"); } /** * Hook for subclasses to clear analysis inputs when `clear()` is called. */ clearAnalysis() { } /** * Hook for subclasses managing an analysis that belongs to a layer. * Called when the view is ready and the `analysisView` is created. */ onConnectToAnalysisView(e) { } /** * Hook for subclasses to react when the view becomes unready and the * internal analysis is removed from the map/analyses. */ onDisconnectFromAnalysisView() { } _scheduleViewReconnect() { this._reconnectViewTask = h(this._reconnectViewTask); const e = u(async (s) => { try { await this._reconnectView(s); } catch (t) { if (O(s), !I(t)) { p("warn", this, `Failed to use analysis in view model. ${String(t)}`); return; } throw t; } finally { e === this._reconnectViewTask && (this._reconnectViewTask = void 0); } }); this._reconnectViewTask = e; } /** * Reconnect the analysis to the current view, obtaining an `analysisView` when supported and ready. * Aborts active operations that are past the "waiting for view" phase. */ async _reconnectView(e) { const { view: s } = this, t = s?.ready && this.supported, a = this.analysis; if (this._userOperationInfo = d(this._userOperationInfo), this._disconnectFromView(s), !t || !s || !a) return; this._ownsAnalysis && (this._changeFromReconnect = !0, s.analyses.add(a)); const r = await s.whenAnalysisView(a); if (this.analysisView = r, b(e)) { this._userOperationInfo = d(this._userOperationInfo); return; } r.visible = !this.hideVisualization, this.shouldForceInteractive && this.addHandles(_(r), y), this.onConnectToAnalysisView(r); } /** * Disconnect the analysis from the given view. */ _disconnectFromView(e) { this._ownsAnalysis && e?.analyses.includes(this.analysis) && (this._changeFromReconnect = !0, this.clearAnalysis(), e.analyses.remove(this.analysis)), this.onDisconnectFromAnalysisView(), this.removeHandles(y), this.analysisView = void 0; } /** * Set an externally owned analysis. */ _setExternalAnalysis(e) { this.analysisView && !this._ownsAnalysis && (this.analysisView.visible = void 0, this.removeHandles(y)), this.analysisView = void 0, this._ownsAnalysis = !1, this._set("analysis", e), this._changeFromReconnect = !1; } // #endregion }; n([ o() ], i.prototype, "defaultMeasurementSystem", 1); n([ o() ], i.prototype, "active", 1); n([ o() ], i.prototype, "analysis", 1); n([ o() ], i.prototype, "connectingToView", 1); n([ o() ], i.prototype, "disabled", 1); n([ o() ], i.prototype, "hideVisualization", 1); n([ o() ], i.prototype, "operationState", 2); n([ o() ], i.prototype, "ready", 1); n([ o() ], i.prototype, "supported", 1); n([ o() ], i.prototype, "view", 2); n([ o() ], i.prototype, "_ownsAnalysis", 2); n([ o() ], i.prototype, "_viewHasAnalysis", 1); n([ o() ], i.prototype, "_reconnectViewTask", 2); n([ o() ], i.prototype, "analysisView", 2); n([ o() ], i.prototype, "shouldForceInteractive", 2); i = n([ V("esri.components.support.AnalysisViewModel") ], i); function d(e) { return e?.state === "running" ? (e.abort(), null) : e; } export { i as A };