feat: Annotation API changes to support Geospatial (Map) annotations (#6703)
* feat: `getAnnotations` can take an `abortSignal` * feat: add `MAP` annotationType * fix: handle `MAP` annotations in search results * fix: have `loadAnnotationForTargetObject` take an `abortSignal` * fix(#5646): abort pending annotations requests on nav away from notebooks or plots * fix: handle AbortErrors gracefully * fix: remove redundant `MAP` annotation type * docs: add comment * fix: navigate before selection for geospatial results * feat: comparators for annotation target equality - Adds `addTargetComparator()` to the Annotation API, allowing plugins to define additional comparators for certain annotation types. - Update usage of `_.isEqual()` for targets to use the `areAnnotationTargetsEqual()` method, which uses any additional comparators before falling back to a deep equality check. - Handle aborted `getAnnotations()` calls gracefully in the AnnotationInspectorView * test: add unit tests for target comparators --------- Co-authored-by: Scott Bell <scott@traclabs.com>
This commit is contained in:
@@ -76,6 +76,9 @@ const ANNOTATION_LAST_CREATED = 'annotationLastCreated';
|
||||
* @constructor
|
||||
*/
|
||||
export default class AnnotationAPI extends EventEmitter {
|
||||
/** @type {Map<ANNOTATION_TYPES, Array<(a, b) => boolean >>} */
|
||||
#targetComparatorMap;
|
||||
|
||||
/**
|
||||
* @param {OpenMCT} openmct
|
||||
*/
|
||||
@@ -84,6 +87,7 @@ export default class AnnotationAPI extends EventEmitter {
|
||||
this.openmct = openmct;
|
||||
this.availableTags = {};
|
||||
this.namespaceToSaveAnnotations = '';
|
||||
this.#targetComparatorMap = new Map();
|
||||
|
||||
this.ANNOTATION_TYPES = ANNOTATION_TYPES;
|
||||
this.ANNOTATION_TYPE = ANNOTATION_TYPE;
|
||||
@@ -246,15 +250,16 @@ export default class AnnotationAPI extends EventEmitter {
|
||||
/**
|
||||
* @method getAnnotations
|
||||
* @param {Identifier} domainObjectIdentifier - The domain object identifier to use to search for annotations. For example, a telemetry object identifier.
|
||||
* @param {AbortSignal} abortSignal - An abort signal to cancel the search
|
||||
* @returns {DomainObject[]} Returns an array of annotations that match the search query
|
||||
*/
|
||||
async getAnnotations(domainObjectIdentifier) {
|
||||
async getAnnotations(domainObjectIdentifier, abortSignal = null) {
|
||||
const keyStringQuery = this.openmct.objects.makeKeyString(domainObjectIdentifier);
|
||||
const searchResults = (
|
||||
await Promise.all(
|
||||
this.openmct.objects.search(
|
||||
keyStringQuery,
|
||||
null,
|
||||
abortSignal,
|
||||
this.openmct.objects.SEARCH_TYPES.ANNOTATIONS
|
||||
)
|
||||
)
|
||||
@@ -384,7 +389,8 @@ export default class AnnotationAPI extends EventEmitter {
|
||||
const combinedResults = [];
|
||||
results.forEach((currentAnnotation) => {
|
||||
const existingAnnotation = combinedResults.find((annotationToFind) => {
|
||||
return _.isEqual(currentAnnotation.targets, annotationToFind.targets);
|
||||
const { annotationType, targets } = currentAnnotation;
|
||||
return this.areAnnotationTargetsEqual(annotationType, targets, annotationToFind.targets);
|
||||
});
|
||||
if (!existingAnnotation) {
|
||||
combinedResults.push(currentAnnotation);
|
||||
@@ -460,4 +466,35 @@ export default class AnnotationAPI extends EventEmitter {
|
||||
|
||||
return breakApartSeparateTargets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a comparator function for a given annotation type.
|
||||
* The comparator functions will be used to determine if two annotations
|
||||
* have the same target.
|
||||
* @param {ANNOTATION_TYPES} annotationType
|
||||
* @param {(t1, t2) => boolean} comparator
|
||||
*/
|
||||
addTargetComparator(annotationType, comparator) {
|
||||
const comparatorList = this.#targetComparatorMap.get(annotationType) ?? [];
|
||||
comparatorList.push(comparator);
|
||||
this.#targetComparatorMap.set(annotationType, comparatorList);
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare two sets of targets to see if they are equal. First checks if
|
||||
* any targets comparators evaluate to true, then falls back to a deep
|
||||
* equality check.
|
||||
* @param {ANNOTATION_TYPES} annotationType
|
||||
* @param {*} targets
|
||||
* @param {*} otherTargets
|
||||
* @returns true if the targets are equal, false otherwise
|
||||
*/
|
||||
areAnnotationTargetsEqual(annotationType, targets, otherTargets) {
|
||||
const targetComparatorList = this.#targetComparatorMap.get(annotationType);
|
||||
return (
|
||||
(targetComparatorList?.length &&
|
||||
targetComparatorList.some((targetComparator) => targetComparator(targets, otherTargets))) ||
|
||||
_.isEqual(targets, otherTargets)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user