/*! meta-admin/modules/editor */
/*jslint
browser, long
*/
/*global
Blob, confirm, L
*/
import {} from "leaflet";
import {} from "leaflet.markercluster";
import {saveAs} from "file-saver";
import Logger from "js-logger";
import ko from "knockout";
import logging from "meta-client/modules/logging";
import objects from "meta-client/modules/objects";
import model from "meta-core/modules/model";
import protocol from "meta-core/modules/protocol";
import _ from "underscore";
import dates from "util-web/modules/dates";
import ext from "util-web/modules/ext";
import i18next from "util-web/modules/i18next";
import keyval from "util-web/modules/keyval";
import nav from "util-web/modules/nav";
import ui from "util-web/modules/ui";
import template from "./editor.html";
const LOG = Logger.get("meta-admin/editor");
const EDITOR_OBJECT_QUERY_SELECTOR = "#editorObjectSearchQuery";
const LOG_SEARCH_QUERY_KEY = "admin-log-query";
const OBJECT_SEARCH_QUERY_KEY = "admin-obj-query";
const META_TYPES = Object.freeze([
{
id: model.META_TYPE_ACTION,
name: i18next.pureComputedT("meta_type_" + model.META_TYPE_ACTION)
},
{
id: model.META_TYPE_LOG,
name: i18next.pureComputedT("meta_type_" + model.META_TYPE_LOG)
},
{
id: model.META_TYPE_OBJECT,
name: i18next.pureComputedT("meta_type_" + model.META_TYPE_OBJECT)
},
{
id: model.META_TYPE_TYPE,
name: i18next.pureComputedT("meta_type_" + model.META_TYPE_TYPE)
}
]);
/**
* editor component.
*
* @module meta-admin/modules/component/editor
*/
export default Object.freeze({
template,
viewModel: {
createViewModel: function ({viewmodel}) {
const getSelectedValue = () => ui.getSelectedText("#objectValue");
const setSchemaRequired = function (schema) {
if (_.isObject(schema)) {
const obj = {};
_.get(schema, model.TYPE_SCHEMA_REQUIRED, []).forEach(function (property) {
obj[property] = null; // TODO use schema.properties[property].type for initial value
});
return obj;
}
};
const geoVisualizations = L.markerClusterGroup();
const searchTimer = logging.newMetricTimer(viewmodel.client, "meta-admin.editor.search");
const vm = {};
vm.viewmodel = viewmodel;
vm.model = model;
vm.metaTypes = META_TYPES;
vm.errorReply = ko.observable();
vm.activeTab = ko.observable();
vm.copyId = (meta) => navigator.clipboard.writeText(meta.id);
vm.getSchemaForTypeId = function (typeId) {
const predicate = {};
predicate[model.META_ID] = typeId;
return _.find(vm.viewmodel.types(), predicate)?.schema();
};
vm.newLog = () => vm.edit(model.metaLog({metaType: model.META_TYPE_OBJECT}));
vm.newObject = function (typeId) {
const schema = vm.getSchemaForTypeId(typeId);
const value = setSchemaRequired(schema);
vm.edit(model.metaObject({typeId, value}));
};
vm.viewmodel.metaCreateHook.subscribe(function (create) {
if (_.isEmpty(create) === false) {
let tab;
return vm.viewmodel.navigateToEditor().then(function () {
if (model.META_TYPE_LOG === create) {
vm.newLog();
tab = vm.viewmodel.EDITOR_TABS.LOGS;
}
if (create.indexOf(model.META_TYPE_OBJECT) === 0) {
const typeId = create.split(";")[1];
vm.newObject(typeId);
tab = vm.viewmodel.EDITOR_TABS.OBJECTS;
}
vm.navigateToTab(tab);
vm.viewmodel.metaCreateHook(undefined);
});
}
});
vm.logQuery = ko.observable();
keyval.get(LOG_SEARCH_QUERY_KEY).then(function (query) {
if (_.isEmpty(query) === false) {
vm.logQuery(query);
}
});
vm.logFrom = ko.observable();
vm.logTo = ko.observable();
const logFromSub = dates.insertDateTimes({
fromDateObservable: vm.logFrom,
toDateObservable: vm.logTo
});
vm.logSearchLimit = ko.observable(10);
vm.logSearchPurge = ko.observable();
vm.metaLogs = objects({
toVm: vm.viewmodel.metaToVm
});
vm.searchLogsInternal = function (limit, clearSearch) {
const logQuery = vm.logQuery();
const from = dates.parseDateTime(vm.logFrom());
const to = dates.parseDateTime(vm.logTo());
const queryParts = [model.lucene.META_LOG_QUERY];
const purge = vm.logSearchPurge();
LOG.debug(`searchLogsInternal, limit=${limit}, clearSearch=${clearSearch}`);
if (clearSearch) {
vm.metaLogs.clear();
}
if (_.isEmpty(logQuery) === false) {
queryParts.push(logQuery);
}
if (from && to) {
queryParts.push(`${model.lucene.META_LOG_FIELD_TIMESTAMP}:${model.lucene.newDateTimeRangeQuery(from, to)}`);
}
let timerContext;
return searchTimer.time().then(function (context) {
timerContext = context;
const searchRequest = protocol.searchRequest({
cursor: vm.metaLogs.searchCursor(),
limit,
purge: (
_.isEmpty(purge) === false
? purge.split(",")
: undefined
),
query: queryParts.join(" AND "),
sort: protocol.searchRequestSort({
field: model.lucene.LOGGING_FIELD_TIMESTAMP,
reverse: true
})
});
return vm.metaLogs.processSearch(
vm.viewmodel.client.search(searchRequest),
clearSearch
);
}).then(function () {
vm.errorReply(undefined);
return keyval.set(LOG_SEARCH_QUERY_KEY, logQuery || "");
}, function (exc) {
vm.errorReply(JSON.stringify(exc, undefined, 4));
}).then(function () {
return timerContext.stop();
});
};
vm.searchLogs = function (form) {
if (ui.validateForm(form) === false) {
return;
}
LOG.debug("searchLogs");
return vm.searchLogsInternal(vm.logSearchLimit(), true).then(function () {
ui.resetForm(form);
});
};
vm.loadMoreLogs = function () {
LOG.debug("loadMoreLogs");
return vm.searchLogsInternal(vm.logSearchLimit(), false);
};
vm.loadAllLogs = function () {
LOG.debug("loadAllLogs");
return vm.searchLogsInternal(0, false);
};
vm.searchTypeId = ko.observable();
vm.objectQuery = ko.observable();
keyval.get(OBJECT_SEARCH_QUERY_KEY).then(function (query) {
if (_.isEmpty(query) === false) {
vm.objectQuery(query);
}
});
vm.objectSearchLimit = ko.observable(100);
vm.objectDistanceFrom = ko.observable();
vm.objectDistanceMeters = ko.observable(500);
vm.objectDistanceCircle = L.circle([0, 0], {
color: "#800000",
radius: vm.objectDistanceMeters()
});
const objectDistanceComputed = ko.computed(function () {
const from = vm.objectDistanceFrom();
const meters = vm.objectDistanceMeters();
if (from) {
vm.objectDistanceCircle.setLatLng(from);
vm.objectDistanceCircle.setRadius(Number(meters));
} else {
vm.objectDistanceCircle.setLatLng([0, 0]);
}
}).extend({rateLimit: 500});
vm.sortableForType = ko.pureComputed(function () {
const sortable = [model.NAME];
const selectedType = vm.searchTypeId();
if (selectedType) {
const schema = vm.getSchemaForTypeId(selectedType);
if (_.has(schema, model.TYPE_SCHEMA_SORTABLE)) {
return sortable.concat(schema[model.TYPE_SCHEMA_SORTABLE]);
}
}
return sortable;
});
vm.searchSort = ko.observable();
vm.searchSortManual = ko.observable();
vm.searchSortReverse = ko.observable(false);
vm.objectSearchPurge = ko.observable();
vm.metaObjects = objects({
loadById: objects.loadByMetaId.bind(undefined, vm.viewmodel.client),
onAdd: function (object) {
const mapApi = vm.viewmodel.mapApiProvider();
if (mapApi) {
mapApi.objectMarkers.push(object);
}
},
onRemove: function (object) {
const mapApi = vm.viewmodel.mapApiProvider();
if (mapApi) {
mapApi.objectMarkers.remove((meta) => meta.id === object.id);
}
},
toVm: vm.viewmodel.metaToVm,
typeId: vm.searchTypeId
});
const eventHandle = vm.viewmodel.client.registerOnEvent(vm.metaObjects);
vm.editedId = ko.pureComputed(function () {
const edited = vm.viewmodel.edited();
if (edited) {
return ko.unwrap(edited.id);
}
});
vm.pickObjectDistanceFrom = function () {
return vm.pickPositionInternal().then(function (position) {
vm.objectDistanceFrom(position);
});
};
vm.clearObjectDistanceFrom = () => vm.objectDistanceFrom(undefined);
vm.insertObjectSearchQueryText = function (valueProvider) {
const selectedValue = ui.getSelectedText(EDITOR_OBJECT_QUERY_SELECTOR);
ui.insertText(EDITOR_OBJECT_QUERY_SELECTOR, valueProvider(selectedValue));
vm.objectQuery(vm.objectQuery());
};
vm.formatDateNumber = function () {
vm.insertObjectSearchQueryText(function (value) {
const dateTime = dates.parseDateTime(value);
return model.lucene.toDateNumber(dateTime);
});
};
vm.formatDateTimeNumber = function () {
vm.insertObjectSearchQueryText(function (value) {
const dateTime = dates.parseDateTime(value);
return model.lucene.toDateTimeNumber(dateTime);
});
};
vm.insertRangeQuery = function () {
vm.insertObjectSearchQueryText(function (value) {
const index = value.indexOf(":") + 1;
const dateRange = dates.getDateRange(value.substring(index));
return value.substring(0, index) + model.lucene.newDateTimeRangeQuery(dateRange.from, dateRange.to);
});
};
vm.searchObjectsInternal = function (limit, clearSearch) {
const typeId = vm.searchTypeId();
const query = vm.objectQuery();
const forgedQuery = objects.newSearchQuery(typeId, [query]);
const sortField = (
vm.searchTypeId()
? vm.searchSort()
: vm.searchSortManual()
);
const purge = vm.objectSearchPurge();
let spatial;
LOG.debug(`searchObjectsInternal, limit=${limit}, clearSearch=${clearSearch}, query=${query}`);
if (clearSearch) {
vm.metaObjects.clear();
}
if (vm.objectDistanceFrom()) {
spatial = [protocol.searchRequestSpatial({
distanceFrom: vm.objectDistanceFrom(),
distanceMeters: Number(vm.objectDistanceMeters()),
field: model.OBJECT_POSITION
})];
}
let timerContext;
return searchTimer.time().then(function (context) {
timerContext = context;
const searchRequest = protocol.searchRequest({
cursor: vm.metaObjects.searchCursor(),
limit,
purge: (
_.isEmpty(purge) === false
? purge.split(",")
: undefined
),
query: forgedQuery,
sort: (
_.isEmpty(sortField)
? undefined
: protocol.searchRequestSort({
field: sortField,
reverse: vm.searchSortReverse()
})
),
spatial
});
return vm.metaObjects.processSearch(
vm.viewmodel.client.search(searchRequest)
);
}).then(function () {
vm.errorReply(undefined);
return keyval.set(OBJECT_SEARCH_QUERY_KEY, query || "");
}, function (exc) {
vm.errorReply(JSON.stringify(exc, undefined, 4));
}).then(function () {
const mapApi = vm.viewmodel.mapApiProvider();
if (mapApi) {
mapApi.objectMarkers(vm.metaObjects.objects());
}
return timerContext.stop();
});
};
vm.searchObjects = function (form) {
if (ui.validateForm(form) === false) {
return;
}
LOG.debug("searchObjects");
return vm.searchObjectsInternal(Number(vm.objectSearchLimit()), true).then(function () {
ui.resetForm(form);
});
};
vm.loadMoreObjects = function () {
LOG.debug("loadMoreObjects");
return vm.searchObjectsInternal(Number(vm.objectSearchLimit()), false);
};
vm.loadAllObjects = function () {
LOG.debug("loadAllObjects");
return vm.searchObjectsInternal(0, false);
};
vm.edit = (meta) => vm.editInternal(meta, false);
vm.editInternal = function (meta, forceLoad = false) {
let edited = meta;
if (Boolean(edited) === false) {
geoVisualizations.clearLayers();
vm.viewmodel.edited(undefined);
return;
}
const metaId = _.get(edited, model.META_ID);
LOG.debug(`edit, metaId=${metaId}, forceLoad=${forceLoad}`);
if (forceLoad) {
return vm.viewmodel.client.search(protocol.searchRequest({
limit: 1,
query: metaId
})).then(function (searchReply) {
if (_.isEmpty(searchReply.metas)) {
LOG.warn("forceLoad failed, metaId=" + metaId);
return;
}
vm.edit(searchReply.metas[0]);
});
}
if (Boolean(ko.mapping.isMapped(edited)) === false) {
edited = vm.viewmodel.metaToVm(edited);
}
vm.viewmodel.edited(edited);
};
vm.loadLog = function () {
vm.metaLogs.clear();
vm.navigateToTab(vm.viewmodel.EDITOR_TABS.LOGS);
vm.logQuery(`${model.lucene.META_LOG_FIELD_META_ID}:"${vm.viewmodel.edited().id}"`);
return vm.searchLogs();
};
vm.writeChannel = ko.observable();
vm.isSaving = ko.observable();
vm.isSaveSuccess = ko.observable();
vm.save = function (form) {
if (ui.validateForm(form) === false) {
return;
}
vm.isSaving(true);
const edited = vm.viewmodel.edited();
return vm.viewmodel.client.write(protocol.writeRequest({
action: (
edited.id
? protocol.WRITE_ACTION.UPDATE
: protocol.WRITE_ACTION.CREATE
),
channel: vm.writeChannel(),
meta: vm.viewmodel.vmToMeta(edited)
})).then(function (writeReply) {
vm.errorReply(undefined);
vm.edit(writeReply.meta);
vm.isSaveSuccess(true);
ui.resetForm(form);
}, function (exc) {
vm.errorReply(JSON.stringify(exc, undefined, 4));
}).then(function () {
vm.isSaving(false);
});
};
vm.doDelete = function () {
if (confirm(i18next.t("delete_meta_confirmation")) === false) {
return;
}
const edited = vm.viewmodel.edited();
return vm.deleteMeta(edited).then(function () {
vm.cancel();
});
};
vm.deleteMeta = function (edited) {
if (Boolean(edited) === false) {
return Promise.resolve(undefined);
}
const meta = {};
meta[model.META_TYPE_PROPERTY] = edited[model.META_TYPE_PROPERTY];
meta.id = edited.id;
if (model.META_TYPE_OBJECT === meta[model.META_TYPE_PROPERTY]) {
meta.typeId = edited.typeId();
}
if (model.META_TYPE_TYPE === meta[model.META_TYPE_PROPERTY]) {
meta.schema = {};
}
return vm.viewmodel.client.write(protocol.writeRequest({
action: protocol.WRITE_ACTION.DELETE,
channel: vm.writeChannel(),
meta
})).then(function () {
vm.errorReply(undefined);
edited.deleted(true);
}, (exc) => vm.errorReply(JSON.stringify(exc, undefined, 4)));
};
vm.deleteAll = function () {
if (confirm(i18next.t("delete_all_confirmation")) === false) {
return;
}
return Promise.all(vm.metaObjects.objects().map(vm.deleteMeta)).then(function () {
vm.errorReply(undefined);
vm.cancel();
}, (exc) => vm.errorReply(JSON.stringify(exc, undefined, 4)));
};
vm.isUpdateActive = ko.observable(false);
vm.updateName = ko.observable();
vm.updateValue = ko.observable();
vm.isUpdateValueValid = ko.observable(true);
vm.updateValueString = vm.viewmodel.newComputedJsonField(vm.updateValue, undefined, vm.isUpdateValueValid);
vm.updatePosition = ko.observable();
vm.clearUpdatePosition = ko.observable(false);
vm.pickUpdatePosition = function () {
vm.isUpdateActive(false);
return vm.pickPositionInternal().then(function (position) {
vm.isUpdateActive(true);
vm.updatePosition(position);
});
};
vm.toggleClearUpdatePosition = () => vm.clearUpdatePosition(!vm.clearUpdatePosition());
vm.activateUpdate = function () {
vm.updateName(undefined);
vm.updateValue(undefined);
vm.updateValueString.format();
vm.updatePosition(undefined);
vm.clearUpdatePosition(false);
vm.isUpdateActive(true);
};
vm.update = function (form) {
const edited = vm.viewmodel.edited();
LOG.debug("update, metaId=" + edited.id);
const updateName = vm.updateName();
const updateValue = vm.updateValue();
const updatePosition = vm.updatePosition();
const updateMeta = Object.assign({}, model.metaObject({
id: edited.id,
typeId: edited.typeId()
}));
if (ui.validateForm(form) === false) {
return;
}
if (_.isEmpty(updateName) === false) {
updateMeta.name = updateName;
} else {
delete updateMeta[model.META_NAME];
}
if (_.isObject(updateValue)) {
updateMeta.value = updateValue;
} else {
delete updateMeta[model.OBJECT_VALUE];
}
if (model.isValidPosition(updatePosition)) {
updateMeta.position = updatePosition;
}
if (vm.clearUpdatePosition()) {
updateMeta.position = model.NO_POSITION;
}
return vm.viewmodel.client.writeObjectUpdate(protocol.writeObjectUpdateRequest({
channel: vm.writeChannel(),
meta: updateMeta
})).then(function () {
vm.errorReply(undefined);
vm.isUpdateActive(false);
vm.isSaveSuccess(true);
ui.resetForm(form);
}).catch((exc) => vm.errorReply(JSON.stringify(exc, undefined, 4)));
};
vm.isExecuteActive = ko.observable(false);
vm.executeParam = ko.observable();
vm.isExecuteParamValid = ko.observable(true);
vm.executeParamString = vm.viewmodel.newComputedJsonField(vm.executeParam, undefined, vm.isExecuteParamValid);
vm.isExecuting = ko.observable(false);
vm.executeResult = ko.observable();
vm.activateExecute = function () {
const edited = vm.viewmodel.edited();
const param = setSchemaRequired(edited.paramSchema());
vm.executeParam(param);
vm.executeParamString.format();
vm.executeResult(undefined);
vm.isExecuteActive(true);
};
vm.execute = function (form) {
if (ui.validateForm(form) === false) {
return;
}
vm.isExecuting(true);
const edited = vm.viewmodel.edited();
LOG.debug(`execute, metaId=${edited.id}`);
return vm.viewmodel.client.execute(protocol.executeRequest({
actionId: edited.id,
param: vm.executeParam()
})).then(function (executeReply) {
vm.errorReply(undefined);
vm.executeResult(JSON.stringify(executeReply.result, undefined, 4));
ui.resetForm(form);
}).catch((exc) => vm.errorReply(JSON.stringify(exc, undefined, 4))).then(
() => vm.isExecuting(false)
);
};
vm.cancel = () => vm.edit(undefined);
vm.pickPosition = function () {
return vm.pickPositionInternal().then(function (position) {
vm.viewmodel.edited().position(position);
});
};
vm.clearPosition = () => vm.viewmodel.edited().position(undefined);
vm.insertDate = () => ui.insertText("#objectValue", dates.nowDateString());
vm.insertDateTime = () => ui.insertText("#objectValue", dates.nowDateTimeString());
vm.insertPosition = function () {
const mapApi = vm.viewmodel.mapApiProvider();
if (Boolean(mapApi) === false) {
return Promise.resolve(undefined);
}
return mapApi.pickPosition().then(function (position) {
ui.insertText("#objectValue", JSON.stringify(position));
});
};
vm.visualizePoint = function () {
const mapApi = vm.viewmodel.mapApiProvider();
const selected = getSelectedValue();
const position = JSON.parse(selected);
if (mapApi) {
mapApi.createMarker("visualizePoint", i18next.t("visualized_point"), position, undefined, mapApi.ICONS.PINK).addTo(geoVisualizations);
mapApi.panTo(position);
}
};
vm.visualizeLine = function () {
const mapApi = vm.viewmodel.mapApiProvider();
const selected = getSelectedValue();
const positions = JSON.parse(selected);
if (mapApi) {
mapApi.createPolyline("visualizeLine", i18next.t("visualized_line"), positions).addTo(geoVisualizations);
mapApi.fitBounds(positions);
}
};
vm.visualizeBox = function () {
const mapApi = vm.viewmodel.mapApiProvider();
const selected = getSelectedValue();
const positions = JSON.parse(selected);
if (mapApi) {
mapApi.createRectangle("visualizeBox", i18next.t("visualized_box"), positions).addTo(geoVisualizations);
mapApi.fitBounds(positions);
}
};
vm.visualizePolygon = function () {
const mapApi = vm.viewmodel.mapApiProvider();
const selected = getSelectedValue();
const positions = JSON.parse(selected);
if (mapApi) {
mapApi.createPolygon("visualizePolygon", i18next.t("visualized_polygon"), positions).addTo(geoVisualizations);
mapApi.fitBounds(positions);
}
};
vm.visualizedImage = ko.observable();
vm.visualizeImage = function () {
const dataUrl = getSelectedValue();
vm.visualizedImage(dataUrl);
};
vm.clearVisualizedImage = () => vm.visualizedImage(undefined);
vm.isImportActive = ko.observable(false);
vm.hasImportFileLoaded = ko.observable(false);
vm.isImportProcessing = ko.observable(false);
vm.importTypes = ko.observableArray();
vm.importObjects = ko.observableArray();
vm.importActions = ko.observableArray();
vm.activateImport = function () {
vm.hasImportFileLoaded(false);
vm.isImportActive(true);
};
vm.loadImportFile = function (ignore, event) {
return ext.loadFileContent({
event,
fileEndings: [".json"],
type: ext.FILE_CONTENT_TYPES.TEXT
}).then(function (file) {
const metaImport = JSON.parse(file.content);
if (_.isEmpty(metaImport.types) === false) {
vm.importTypes(metaImport.types);
}
if (_.isEmpty(metaImport.objects) === false) {
vm.importObjects(metaImport.objects);
}
if (_.isEmpty(metaImport.actions) === false) {
vm.importActions(metaImport.actions);
}
vm.hasImportFileLoaded(true);
});
};
vm.doImport = function () {
const writes = [];
const pushWrite = function (meta) {
writes.push(protocol.writeRequest({
action: protocol.WRITE_ACTION.CREATE,
meta
}));
};
vm.isImportProcessing(true);
vm.importTypes().forEach(pushWrite);
vm.importObjects().forEach(pushWrite);
vm.importActions().forEach(pushWrite);
return Promise.all(writes.map(function (write) {
return vm.viewmodel.client.write(write);
})).then(function () {
vm.errorReply(undefined);
}, function (exc) {
vm.errorReply(JSON.stringify(exc, undefined, 4));
}).then(function () {
vm.isImportProcessing(false);
vm.isImportActive(false);
vm.importTypes.removeAll();
vm.importObjects.removeAll();
vm.importActions.removeAll();
});
};
vm.isExportActive = ko.observable(false);
vm.isExporting = ko.observable(false);
vm.exportTypes = ko.observable();
vm.exportObjects = ko.observable();
vm.exportActions = ko.observable();
vm.activateExport = function () {
vm.isExportActive(true);
};
vm.doExport = function () {
const metaExport = {};
LOG.debug("doExport");
vm.isExporting(true);
try {
if (vm.exportTypes()) {
metaExport.types = vm.viewmodel.types().map(vm.viewmodel.vmToMeta);
}
if (vm.exportObjects()) {
metaExport.objects = vm.metaObjects.objects().map(vm.viewmodel.vmToMeta);
}
if (vm.exportActions()) {
metaExport.actions = vm.viewmodel.actions().map(vm.viewmodel.vmToMeta);
}
saveAs(
new Blob([JSON.stringify(metaExport, undefined, 4)], {type: "application/json;charset=utf-8"}),
`meta_export-${dates.now().toMillis()}.json`
);
} catch (exc) {
LOG.warn("doExport failed", exc);
} finally {
vm.isExporting(false);
}
vm.isExportActive(false);
vm.exportTypes(false);
vm.exportObjects(false);
vm.exportActions(false);
};
vm.pickPositionInternal = function () {
const mapApi = vm.viewmodel.mapApiProvider();
LOG.debug("pickPositionInternal");
if (Boolean(mapApi) === false) {
return Promise.resolve(undefined);
}
return mapApi.pickPosition().then(function (position) {
return position;
});
};
vm.navigateToTab = vm.viewmodel.navigateToTab.bind(undefined, vm.viewmodel.COMPONENTS.EDITOR);
vm.onNavUpdate = function (tab) {
const activeTab = (
_.isEmpty(tab)
? vm.viewmodel.EDITOR_TABS.OBJECTS
: tab
);
LOG.debug(`onNavUpdate, tab=${tab}, activeTab=${activeTab}`);
vm.activeTab(activeTab);
};
nav.register({
id: vm.viewmodel.COMPONENTS.EDITOR,
onUpdate: vm.onNavUpdate
});
vm.dispose = function () {
LOG.debug("dispose");
vm.viewmodel.client.unregisterOnEvent(eventHandle);
logFromSub.dispose();
objectDistanceComputed.dispose();
vm.executeParamString.dispose();
};
ko.when(function () {
return _.isObject(vm.viewmodel.mapApiProvider());
}).then(function () {
const mapApi = vm.viewmodel.mapApiProvider();
mapApi.addOverlay(vm.objectDistanceCircle, i18next.t("search_distance"));
mapApi.addOverlay(geoVisualizations, i18next.t("geo_visualizations"));
mapApi.editedObjectMarker.subscribe(function (metaId) {
LOG.debug(`editedObjectMarker=${metaId}`);
if (metaId) {
vm.editInternal(model.metaObject({id: metaId}), true);
mapApi.editedObjectMarker(undefined);
}
});
});
return Object.freeze(vm);
}
}
});