@arcgis/map-components
Version:
ArcGIS Map Components
259 lines (258 loc) • 8.96 kB
JavaScript
/* 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 "/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
};