terriajs
Version:
Geospatial data visualization platform.
280 lines • 10.4 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import i18next from "i18next";
import { action, computed, observable, makeObservable } from "mobx";
import filterOutUndefined from "../Core/filterOutUndefined";
import Result from "../Core/Result";
import TerriaError, { TerriaErrorSeverity } from "../Core/TerriaError";
import CatalogMemberMixin, { getName } from "../ModelMixins/CatalogMemberMixin";
import ChartableMixin from "../ModelMixins/ChartableMixin";
import MappableMixin from "../ModelMixins/MappableMixin";
import ReferenceMixin from "../ModelMixins/ReferenceMixin";
import TimeFilterMixin from "../ModelMixins/TimeFilterMixin";
import LayerOrderingTraits from "../Traits/TraitsClasses/LayerOrderingTraits";
import CommonStrata from "./Definition/CommonStrata";
import hasTraits from "./Definition/hasTraits";
import MappableTraits from "../Traits/TraitsClasses/MappableTraits";
const keepOnTop = (model) => hasTraits(model, LayerOrderingTraits, "keepOnTop") && model.keepOnTop;
const supportsReordering = (model) => hasTraits(model, LayerOrderingTraits, "supportsReordering") &&
model.supportsReordering;
export default class Workbench {
_items = observable.array();
constructor() {
makeObservable(this);
}
/**
* Gets or sets the list of items on the workbench.
*/
get items() {
return this._items.map(dereferenceModel);
}
set items(items) {
// Run items through a set to remove duplicates.
const setItems = new Set(items);
this._items.spliceWithArray(0, this._items.length, Array.from(setItems).slice());
}
/**
* Gets the unique IDs of the items in the workbench.
*/
get itemIds() {
return filterOutUndefined(this._items.map((item) => item.uniqueId));
}
/**
* Gets the unique IDs of the items in the workbench.
*/
get shouldExpandAll() {
return this.items.every((item) => !item.isOpenInWorkbench);
}
/**
* Checks if the workbench contains time-based WMS
*/
get hasTimeWMS() {
return this._items.some((item) => item.type === "wms" &&
TimeFilterMixin.isMixedInto(item) &&
item.discreteTimesAsSortedJulianDates?.length);
}
/**
* Removes a model or its dereferenced equivalent from the workbench.
* @param item The model.
*/
remove(item) {
const index = this.indexOf(item);
if (index >= 0) {
this._items.splice(index, 1);
}
}
/**
* Removes all models from the workbench.
*/
removeAll() {
this._items.clear();
}
/**
* Collapses all models from the workbench.
*/
collapseAll() {
this.items.map((item) => {
item.setTrait(CommonStrata.user, "isOpenInWorkbench", false);
});
}
/**
* Expands all models from the workbench.
*/
expandAll() {
this.items.map((item) => {
item.setTrait(CommonStrata.user, "isOpenInWorkbench", true);
});
}
/**
* Disable all items in the workbench.
*/
disableAll() {
this.items.forEach((item) => {
if (hasTraits(item, MappableTraits, "show")) {
item.setTrait(CommonStrata.user, "show", false);
}
});
}
enableAll() {
this.items.forEach((item) => {
if (hasTraits(item, MappableTraits, "show")) {
item.setTrait(CommonStrata.user, "show", true);
}
});
}
/**
* Adds an item to the workbench. If the item is already present, this method does nothing.
* Note that the model's dereferenced equivalent may appear in the {@link Workbench#items} list
* rather than the model itself.
* @param item The model to add.
*/
insertItem(item, index = 0) {
if (this.contains(item)) {
return;
}
const targetItem = dereferenceModel(item);
// Keep reorderable data sources (e.g.: imagery layers) below non-orderable ones (e.g.: GeoJSON).
if (supportsReordering(targetItem)) {
while (index < this.items.length &&
!supportsReordering(this.items[index])) {
++index;
}
}
else {
while (index > 0 &&
this.items.length > 0 &&
supportsReordering(this.items[index - 1])) {
--index;
}
}
if (!keepOnTop(targetItem)) {
while (index < this.items.length &&
keepOnTop(this.items[index]) &&
supportsReordering(this.items[index]) === supportsReordering(targetItem)) {
++index;
}
}
else {
while (index > 0 &&
this.items.length > 0 &&
!keepOnTop(this.items[index - 1]) &&
supportsReordering(this.items[index - 1]) ===
supportsReordering(targetItem)) {
--index;
}
}
// Make sure the reference, rather than the target, is added to the items list.
const referenceItem = item.sourceReference ? item.sourceReference : item;
this._items.splice(index, 0, referenceItem);
}
/**
* Adds or removes a model to/from the workbench. If the model is a reference,
* it will also be dereferenced. If, after dereferencing, the item turns out not to
* be {@link AsyncMappableMixin} or {@link ChartableMixin} but it is a {@link GroupMixin}, it will
* be removed from the workbench. If it is mappable, `loadMapItems` will be called.
*
* If an error occurs, it will only be added to the workbench if the severity is TerriaError.Warning - otherwise it will not be added
*
* @param item The item to add to or remove from the workbench.
*/
async add(item) {
if (Array.isArray(item)) {
const results = await Promise.all(item.reverse().map((i) => this.add(i)));
return Result.combine(results, {
title: i18next.t("workbench.addItemErrorTitle"),
message: i18next.t("workbench.addItemErrorMessage"),
importance: -1
});
}
if (MappableMixin.isMixedInto(item) && item.shouldShowInitialMessage) {
await item.showInitialMessage();
}
this.insertItem(item);
let error;
if (ReferenceMixin.isMixedInto(item)) {
error = (await item.loadReference()).error;
if (item.target) {
this.remove(item);
return this.add(item.target);
}
}
// Add warning message if item isn't mappable or chartable
if (!error &&
!MappableMixin.isMixedInto(item) &&
!ChartableMixin.isMixedInto(item)) {
error = TerriaError.from(`${getName(item)} doesn't have anything to visualize`, TerriaErrorSeverity.Warning);
}
if (!error && CatalogMemberMixin.isMixedInto(item))
error = (await item.loadMetadata()).error;
if (!error && MappableMixin.isMixedInto(item)) {
error = (await item.loadMapItems()).error;
if (!error && item.zoomOnAddToWorkbench && !item.disableZoomTo) {
item.terria.currentViewer.zoomTo(item);
}
}
// Remove item if TerriaError severity is Error
if (error?.severity === TerriaErrorSeverity.Error) {
this.remove(item);
}
return Result.none(error, {
title: i18next.t("workbench.addItemErrorTitle"),
message: i18next.t("workbench.addItemErrorMessage"),
importance: -1
});
}
/**
* Determines if a given model or its dereferenced equivalent exists in the workbench list.
* @param item The model.
* @returns True if the model or its dereferenced equivalent exists on the workbench; otherwise, false.
*/
contains(item) {
return this.indexOf(item) >= 0;
}
/**
* Returns the index of a given model or its dereferenced equivalent in the workbench list.
* @param item The model.
* @returns The index of the model or its dereferenced equivalent, or -1 if neither exist on the workbench.
*/
indexOf(item) {
return this.items.findIndex((model) => model === item || dereferenceModel(model) === dereferenceModel(item));
}
/**
* Used to re-order the workbench list.
* @param item The model to be moved.
* @param newIndex The new index to shift the model to.
*/
moveItemToIndex(item, newIndex) {
if (!this.contains(item)) {
return;
}
this.remove(item);
this.insertItem(item, newIndex);
}
}
__decorate([
computed
], Workbench.prototype, "items", null);
__decorate([
computed
], Workbench.prototype, "itemIds", null);
__decorate([
computed
], Workbench.prototype, "shouldExpandAll", null);
__decorate([
computed
], Workbench.prototype, "hasTimeWMS", null);
__decorate([
action
], Workbench.prototype, "remove", null);
__decorate([
action
], Workbench.prototype, "removeAll", null);
__decorate([
action
], Workbench.prototype, "collapseAll", null);
__decorate([
action
], Workbench.prototype, "expandAll", null);
__decorate([
action
], Workbench.prototype, "disableAll", null);
__decorate([
action
], Workbench.prototype, "enableAll", null);
__decorate([
action
], Workbench.prototype, "insertItem", null);
__decorate([
action
], Workbench.prototype, "moveItemToIndex", null);
function dereferenceModel(model) {
if (ReferenceMixin.isMixedInto(model) && model.target !== undefined) {
return model.target;
}
return model;
}
//# sourceMappingURL=Workbench.js.map