mirror of
https://github.com/nasa/openmct.git
synced 2025-03-25 13:28:38 +00:00
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
This commit is contained in:
parent
11295a8042
commit
9a0923801b
@ -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;
|
||||
@ -385,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);
|
||||
@ -461,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)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -41,7 +41,6 @@
|
||||
|
||||
<script>
|
||||
import TagEditor from './tags/TagEditor.vue';
|
||||
import _ from 'lodash';
|
||||
|
||||
export default {
|
||||
components: {
|
||||
@ -191,7 +190,6 @@ export default {
|
||||
}
|
||||
},
|
||||
async loadAnnotationForTargetObject(target) {
|
||||
const targetID = this.openmct.objects.makeKeyString(target.identifier);
|
||||
// If the user changes targets while annotations are loading,
|
||||
// abort the previous request.
|
||||
if (this.abortController !== null) {
|
||||
@ -199,20 +197,27 @@ export default {
|
||||
}
|
||||
|
||||
this.abortController = new AbortController();
|
||||
const allAnnotationsForTarget = await this.openmct.annotation.getAnnotations(
|
||||
target.identifier,
|
||||
this.abortController.signal
|
||||
);
|
||||
const filteredAnnotationsForSelection = allAnnotationsForTarget.filter((annotation) => {
|
||||
const matchingTargetID = Object.keys(annotation.targets).filter((loadedTargetID) => {
|
||||
return targetID === loadedTargetID;
|
||||
});
|
||||
const fetchedTargetDetails = annotation.targets[matchingTargetID];
|
||||
const selectedTargetDetails = this.targetDetails[matchingTargetID];
|
||||
|
||||
return _.isEqual(fetchedTargetDetails, selectedTargetDetails);
|
||||
});
|
||||
this.loadNewAnnotations(filteredAnnotationsForSelection);
|
||||
try {
|
||||
const allAnnotationsForTarget = await this.openmct.annotation.getAnnotations(
|
||||
target.identifier,
|
||||
this.abortController.signal
|
||||
);
|
||||
const filteredAnnotationsForSelection = allAnnotationsForTarget.filter((annotation) =>
|
||||
this.openmct.annotation.areAnnotationTargetsEqual(
|
||||
this.annotationType,
|
||||
this.targetDetails,
|
||||
annotation.targets
|
||||
)
|
||||
);
|
||||
this.loadNewAnnotations(filteredAnnotationsForSelection);
|
||||
} catch (err) {
|
||||
if (err.name !== 'AbortError') {
|
||||
throw err;
|
||||
}
|
||||
} finally {
|
||||
this.abortController = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
Loading…
x
Reference in New Issue
Block a user