chore: add prettier (2/3): apply formatting, re-enable lint ci step (#6682)
* style: apply prettier formatting * fix: re-enable lint ci check
This commit is contained in:
@@ -34,11 +34,11 @@ import _ from 'lodash';
|
||||
* @property {String} PLOT_SPATIAL The plot-spatial annotation type
|
||||
*/
|
||||
const ANNOTATION_TYPES = Object.freeze({
|
||||
NOTEBOOK: 'NOTEBOOK',
|
||||
GEOSPATIAL: 'GEOSPATIAL',
|
||||
PIXEL_SPATIAL: 'PIXEL_SPATIAL',
|
||||
TEMPORAL: 'TEMPORAL',
|
||||
PLOT_SPATIAL: 'PLOT_SPATIAL'
|
||||
NOTEBOOK: 'NOTEBOOK',
|
||||
GEOSPATIAL: 'GEOSPATIAL',
|
||||
PIXEL_SPATIAL: 'PIXEL_SPATIAL',
|
||||
TEMPORAL: 'TEMPORAL',
|
||||
PLOT_SPATIAL: 'PLOT_SPATIAL'
|
||||
});
|
||||
|
||||
const ANNOTATION_TYPE = 'annotation';
|
||||
@@ -76,357 +76,388 @@ const ANNOTATION_LAST_CREATED = 'annotationLastCreated';
|
||||
* @constructor
|
||||
*/
|
||||
export default class AnnotationAPI extends EventEmitter {
|
||||
/**
|
||||
* @param {OpenMCT} openmct
|
||||
*/
|
||||
constructor(openmct) {
|
||||
super();
|
||||
this.openmct = openmct;
|
||||
this.availableTags = {};
|
||||
this.namespaceToSaveAnnotations = '';
|
||||
|
||||
/**
|
||||
* @param {OpenMCT} openmct
|
||||
*/
|
||||
constructor(openmct) {
|
||||
super();
|
||||
this.openmct = openmct;
|
||||
this.availableTags = {};
|
||||
this.namespaceToSaveAnnotations = '';
|
||||
this.ANNOTATION_TYPES = ANNOTATION_TYPES;
|
||||
this.ANNOTATION_TYPE = ANNOTATION_TYPE;
|
||||
this.ANNOTATION_LAST_CREATED = ANNOTATION_LAST_CREATED;
|
||||
|
||||
this.ANNOTATION_TYPES = ANNOTATION_TYPES;
|
||||
this.ANNOTATION_TYPE = ANNOTATION_TYPE;
|
||||
this.ANNOTATION_LAST_CREATED = ANNOTATION_LAST_CREATED;
|
||||
|
||||
this.openmct.types.addType(ANNOTATION_TYPE, {
|
||||
name: 'Annotation',
|
||||
description: 'A user created note or comment about time ranges, pixel space, and geospatial features.',
|
||||
creatable: false,
|
||||
cssClass: 'icon-notebook',
|
||||
initialize: function (domainObject) {
|
||||
domainObject.targets = domainObject.targets || {};
|
||||
domainObject._deleted = domainObject._deleted || false;
|
||||
domainObject.originalContextPath = domainObject.originalContextPath || '';
|
||||
domainObject.tags = domainObject.tags || [];
|
||||
domainObject.contentText = domainObject.contentText || '';
|
||||
domainObject.annotationType = domainObject.annotationType || 'plotspatial';
|
||||
}
|
||||
});
|
||||
this.openmct.types.addType(ANNOTATION_TYPE, {
|
||||
name: 'Annotation',
|
||||
description:
|
||||
'A user created note or comment about time ranges, pixel space, and geospatial features.',
|
||||
creatable: false,
|
||||
cssClass: 'icon-notebook',
|
||||
initialize: function (domainObject) {
|
||||
domainObject.targets = domainObject.targets || {};
|
||||
domainObject._deleted = domainObject._deleted || false;
|
||||
domainObject.originalContextPath = domainObject.originalContextPath || '';
|
||||
domainObject.tags = domainObject.tags || [];
|
||||
domainObject.contentText = domainObject.contentText || '';
|
||||
domainObject.annotationType = domainObject.annotationType || 'plotspatial';
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Creates an annotation on a given domain object (e.g., a plot) and a set of targets (e.g., telemetry objects)
|
||||
* @typedef {Object} CreateAnnotationOptions
|
||||
* @property {String} name a name for the new annotation (e.g., "Plot annnotation")
|
||||
* @property {DomainObject} domainObject the domain object this annotation was created with
|
||||
* @property {ANNOTATION_TYPES} annotationType the type of annotation to create (e.g., PLOT_SPATIAL)
|
||||
* @property {Tag[]} tags tags to add to the annotation, e.g., SCIENCE for science related annotations
|
||||
* @property {String} contentText Some text to add to the annotation, e.g. ("This annotation is about science")
|
||||
* @property {Object<string, Object>} targets The targets ID keystrings and their specific properties.
|
||||
* For plots, this will be a bounding box, e.g.: {maxY: 100, minY: 0, maxX: 100, minX: 0}
|
||||
* For notebooks, this will be an entry ID, e.g.: {entryId: "entry-ecb158f5-d23c-45e1-a704-649b382622ba"}
|
||||
* @property {DomainObject>} targetDomainObjects the targets ID keystrings and the domain objects this annotation points to (e.g., telemetry objects for a plot)
|
||||
*/
|
||||
/**
|
||||
* @method create
|
||||
* @param {CreateAnnotationOptions} options
|
||||
* @returns {Promise<DomainObject>} a promise which will resolve when the domain object
|
||||
* has been created, or be rejected if it cannot be saved
|
||||
*/
|
||||
async create({
|
||||
name,
|
||||
domainObject,
|
||||
annotationType,
|
||||
tags,
|
||||
contentText,
|
||||
targets,
|
||||
targetDomainObjects
|
||||
}) {
|
||||
if (!Object.keys(this.ANNOTATION_TYPES).includes(annotationType)) {
|
||||
throw new Error(`Unknown annotation type: ${annotationType}`);
|
||||
}
|
||||
/**
|
||||
* Creates an annotation on a given domain object (e.g., a plot) and a set of targets (e.g., telemetry objects)
|
||||
* @typedef {Object} CreateAnnotationOptions
|
||||
* @property {String} name a name for the new annotation (e.g., "Plot annnotation")
|
||||
* @property {DomainObject} domainObject the domain object this annotation was created with
|
||||
* @property {ANNOTATION_TYPES} annotationType the type of annotation to create (e.g., PLOT_SPATIAL)
|
||||
* @property {Tag[]} tags tags to add to the annotation, e.g., SCIENCE for science related annotations
|
||||
* @property {String} contentText Some text to add to the annotation, e.g. ("This annotation is about science")
|
||||
* @property {Object<string, Object>} targets The targets ID keystrings and their specific properties.
|
||||
* For plots, this will be a bounding box, e.g.: {maxY: 100, minY: 0, maxX: 100, minX: 0}
|
||||
* For notebooks, this will be an entry ID, e.g.: {entryId: "entry-ecb158f5-d23c-45e1-a704-649b382622ba"}
|
||||
* @property {DomainObject>} targetDomainObjects the targets ID keystrings and the domain objects this annotation points to (e.g., telemetry objects for a plot)
|
||||
*/
|
||||
/**
|
||||
* @method create
|
||||
* @param {CreateAnnotationOptions} options
|
||||
* @returns {Promise<DomainObject>} a promise which will resolve when the domain object
|
||||
* has been created, or be rejected if it cannot be saved
|
||||
*/
|
||||
async create({name, domainObject, annotationType, tags, contentText, targets, targetDomainObjects}) {
|
||||
if (!Object.keys(this.ANNOTATION_TYPES).includes(annotationType)) {
|
||||
throw new Error(`Unknown annotation type: ${annotationType}`);
|
||||
}
|
||||
|
||||
if (!Object.keys(targets).length) {
|
||||
throw new Error(`At least one target is required to create an annotation`);
|
||||
}
|
||||
if (!Object.keys(targets).length) {
|
||||
throw new Error(`At least one target is required to create an annotation`);
|
||||
}
|
||||
|
||||
if (!Object.keys(targetDomainObjects).length) {
|
||||
throw new Error(`At least one targetDomainObject is required to create an annotation`);
|
||||
}
|
||||
if (!Object.keys(targetDomainObjects).length) {
|
||||
throw new Error(`At least one targetDomainObject is required to create an annotation`);
|
||||
}
|
||||
|
||||
const domainObjectKeyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
const originalPathObjects = await this.openmct.objects.getOriginalPath(domainObjectKeyString);
|
||||
const originalContextPath = this.openmct.objects.getRelativePath(originalPathObjects);
|
||||
const namespace = this.namespaceToSaveAnnotations;
|
||||
const type = 'annotation';
|
||||
const typeDefinition = this.openmct.types.get(type);
|
||||
const definition = typeDefinition.definition;
|
||||
const domainObjectKeyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
const originalPathObjects = await this.openmct.objects.getOriginalPath(domainObjectKeyString);
|
||||
const originalContextPath = this.openmct.objects.getRelativePath(originalPathObjects);
|
||||
const namespace = this.namespaceToSaveAnnotations;
|
||||
const type = 'annotation';
|
||||
const typeDefinition = this.openmct.types.get(type);
|
||||
const definition = typeDefinition.definition;
|
||||
|
||||
const createdObject = {
|
||||
name,
|
||||
type,
|
||||
identifier: {
|
||||
key: uuid(),
|
||||
namespace
|
||||
},
|
||||
tags,
|
||||
_deleted: false,
|
||||
annotationType,
|
||||
contentText,
|
||||
originalContextPath
|
||||
const createdObject = {
|
||||
name,
|
||||
type,
|
||||
identifier: {
|
||||
key: uuid(),
|
||||
namespace
|
||||
},
|
||||
tags,
|
||||
_deleted: false,
|
||||
annotationType,
|
||||
contentText,
|
||||
originalContextPath
|
||||
};
|
||||
|
||||
if (definition.initialize) {
|
||||
definition.initialize(createdObject);
|
||||
}
|
||||
|
||||
createdObject.targets = targets;
|
||||
createdObject.originalContextPath = originalContextPath;
|
||||
|
||||
const success = await this.openmct.objects.save(createdObject);
|
||||
if (success) {
|
||||
this.emit('annotationCreated', createdObject);
|
||||
Object.values(targetDomainObjects).forEach((targetDomainObject) => {
|
||||
this.#updateAnnotationModified(targetDomainObject);
|
||||
});
|
||||
|
||||
return createdObject;
|
||||
} else {
|
||||
throw new Error('Failed to create object');
|
||||
}
|
||||
}
|
||||
|
||||
#updateAnnotationModified(targetDomainObject) {
|
||||
// As certain telemetry objects are immutable, we'll need to check here first
|
||||
// to see if we can add the annotation last created property.
|
||||
// TODO: This should be removed once we have a better way to handle immutable telemetry objects
|
||||
if (targetDomainObject.isMutable) {
|
||||
this.openmct.objects.mutate(targetDomainObject, this.ANNOTATION_LAST_CREATED, Date.now());
|
||||
} else {
|
||||
this.emit('targetDomainObjectAnnotated', targetDomainObject);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @method defineTag
|
||||
* @param {String} key a unique identifier for the tag
|
||||
* @param {Tag} tagsDefinition the definition of the tag to add
|
||||
*/
|
||||
defineTag(tagKey, tagsDefinition) {
|
||||
this.availableTags[tagKey] = tagsDefinition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method setNamespaceToSaveAnnotations
|
||||
* @param {String} namespace the namespace to save new annotations to
|
||||
*/
|
||||
setNamespaceToSaveAnnotations(namespace) {
|
||||
this.namespaceToSaveAnnotations = namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method isAnnotation
|
||||
* @param {DomainObject} domainObject the domainObject in question
|
||||
* @returns {Boolean} Returns true if the domain object is an annotation
|
||||
*/
|
||||
isAnnotation(domainObject) {
|
||||
return domainObject && domainObject.type === ANNOTATION_TYPE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getAvailableTags
|
||||
* @returns {Tag[]} Returns an array of the available tags that have been loaded
|
||||
*/
|
||||
getAvailableTags() {
|
||||
if (this.availableTags) {
|
||||
const rearrangedToArray = Object.keys(this.availableTags).map((tagKey) => {
|
||||
return {
|
||||
id: tagKey,
|
||||
...this.availableTags[tagKey]
|
||||
};
|
||||
});
|
||||
|
||||
if (definition.initialize) {
|
||||
definition.initialize(createdObject);
|
||||
}
|
||||
return rearrangedToArray;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
createdObject.targets = targets;
|
||||
createdObject.originalContextPath = originalContextPath;
|
||||
/**
|
||||
* @method getAnnotations
|
||||
* @param {Identifier} domainObjectIdentifier - The domain object identifier to use to search for annotations. For example, a telemetry object identifier.
|
||||
* @returns {DomainObject[]} Returns an array of annotations that match the search query
|
||||
*/
|
||||
async getAnnotations(domainObjectIdentifier) {
|
||||
const keyStringQuery = this.openmct.objects.makeKeyString(domainObjectIdentifier);
|
||||
const searchResults = (
|
||||
await Promise.all(
|
||||
this.openmct.objects.search(
|
||||
keyStringQuery,
|
||||
null,
|
||||
this.openmct.objects.SEARCH_TYPES.ANNOTATIONS
|
||||
)
|
||||
)
|
||||
).flat();
|
||||
|
||||
const success = await this.openmct.objects.save(createdObject);
|
||||
if (success) {
|
||||
this.emit('annotationCreated', createdObject);
|
||||
Object.values(targetDomainObjects).forEach(targetDomainObject => {
|
||||
this.#updateAnnotationModified(targetDomainObject);
|
||||
});
|
||||
return searchResults;
|
||||
}
|
||||
|
||||
return createdObject;
|
||||
} else {
|
||||
throw new Error('Failed to create object');
|
||||
}
|
||||
/**
|
||||
* @method deleteAnnotations
|
||||
* @param {DomainObject[]} existingAnnotation - An array of annotations to delete (set _deleted to true)
|
||||
*/
|
||||
deleteAnnotations(annotations) {
|
||||
if (!annotations) {
|
||||
throw new Error('Asked to delete null annotations! 🙅♂️');
|
||||
}
|
||||
|
||||
#updateAnnotationModified(targetDomainObject) {
|
||||
// As certain telemetry objects are immutable, we'll need to check here first
|
||||
// to see if we can add the annotation last created property.
|
||||
// TODO: This should be removed once we have a better way to handle immutable telemetry objects
|
||||
if (targetDomainObject.isMutable) {
|
||||
this.openmct.objects.mutate(targetDomainObject, this.ANNOTATION_LAST_CREATED, Date.now());
|
||||
} else {
|
||||
this.emit('targetDomainObjectAnnotated', targetDomainObject);
|
||||
}
|
||||
annotations.forEach((annotation) => {
|
||||
if (!annotation._deleted) {
|
||||
this.openmct.objects.mutate(annotation, '_deleted', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @method deleteAnnotations
|
||||
* @param {DomainObject} annotation - An annotation to undelete (set _deleted to false)
|
||||
*/
|
||||
unDeleteAnnotation(annotation) {
|
||||
if (!annotation) {
|
||||
throw new Error('Asked to undelete null annotation! 🙅♂️');
|
||||
}
|
||||
|
||||
/**
|
||||
* @method defineTag
|
||||
* @param {String} key a unique identifier for the tag
|
||||
* @param {Tag} tagsDefinition the definition of the tag to add
|
||||
*/
|
||||
defineTag(tagKey, tagsDefinition) {
|
||||
this.availableTags[tagKey] = tagsDefinition;
|
||||
this.openmct.objects.mutate(annotation, '_deleted', false);
|
||||
}
|
||||
|
||||
getTagsFromAnnotations(annotations, filterDuplicates = true) {
|
||||
if (!annotations) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @method setNamespaceToSaveAnnotations
|
||||
* @param {String} namespace the namespace to save new annotations to
|
||||
*/
|
||||
setNamespaceToSaveAnnotations(namespace) {
|
||||
this.namespaceToSaveAnnotations = namespace;
|
||||
let tagsFromAnnotations = annotations.flatMap((annotation) => {
|
||||
if (annotation._deleted) {
|
||||
return [];
|
||||
} else {
|
||||
return annotation.tags;
|
||||
}
|
||||
});
|
||||
|
||||
if (filterDuplicates) {
|
||||
tagsFromAnnotations = tagsFromAnnotations.filter((tag, index, tagArray) => {
|
||||
return tagArray.indexOf(tag) === index;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @method isAnnotation
|
||||
* @param {DomainObject} domainObject the domainObject in question
|
||||
* @returns {Boolean} Returns true if the domain object is an annotation
|
||||
*/
|
||||
isAnnotation(domainObject) {
|
||||
return domainObject && (domainObject.type === ANNOTATION_TYPE);
|
||||
const fullTagModels = this.#addTagMetaInformationToTags(tagsFromAnnotations);
|
||||
|
||||
return fullTagModels;
|
||||
}
|
||||
|
||||
#addTagMetaInformationToTags(tags) {
|
||||
return tags.map((tagKey) => {
|
||||
const tagModel = this.availableTags[tagKey];
|
||||
tagModel.tagID = tagKey;
|
||||
|
||||
return tagModel;
|
||||
});
|
||||
}
|
||||
|
||||
#getMatchingTags(query) {
|
||||
if (!query) {
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @method getAvailableTags
|
||||
* @returns {Tag[]} Returns an array of the available tags that have been loaded
|
||||
*/
|
||||
getAvailableTags() {
|
||||
if (this.availableTags) {
|
||||
const rearrangedToArray = Object.keys(this.availableTags).map(tagKey => {
|
||||
return {
|
||||
id: tagKey,
|
||||
...this.availableTags[tagKey]
|
||||
};
|
||||
});
|
||||
const matchingTags = Object.keys(this.availableTags).filter((tagKey) => {
|
||||
if (this.availableTags[tagKey] && this.availableTags[tagKey].label) {
|
||||
return this.availableTags[tagKey].label.toLowerCase().includes(query.toLowerCase());
|
||||
}
|
||||
|
||||
return rearrangedToArray;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* @method getAnnotations
|
||||
* @param {Identifier} domainObjectIdentifier - The domain object identifier to use to search for annotations. For example, a telemetry object identifier.
|
||||
* @returns {DomainObject[]} Returns an array of annotations that match the search query
|
||||
*/
|
||||
async getAnnotations(domainObjectIdentifier) {
|
||||
const keyStringQuery = this.openmct.objects.makeKeyString(domainObjectIdentifier);
|
||||
const searchResults = (await Promise.all(this.openmct.objects.search(keyStringQuery, null, this.openmct.objects.SEARCH_TYPES.ANNOTATIONS))).flat();
|
||||
return matchingTags;
|
||||
}
|
||||
|
||||
return searchResults;
|
||||
}
|
||||
#addTagMetaInformationToResults(results, matchingTagKeys) {
|
||||
const tagsAddedToResults = results.map((result) => {
|
||||
const fullTagModels = this.#addTagMetaInformationToTags(result.tags);
|
||||
|
||||
/**
|
||||
* @method deleteAnnotations
|
||||
* @param {DomainObject[]} existingAnnotation - An array of annotations to delete (set _deleted to true)
|
||||
*/
|
||||
deleteAnnotations(annotations) {
|
||||
if (!annotations) {
|
||||
throw new Error('Asked to delete null annotations! 🙅♂️');
|
||||
}
|
||||
return {
|
||||
fullTagModels,
|
||||
matchingTagKeys,
|
||||
...result
|
||||
};
|
||||
});
|
||||
|
||||
annotations.forEach(annotation => {
|
||||
if (!annotation._deleted) {
|
||||
this.openmct.objects.mutate(annotation, '_deleted', true);
|
||||
}
|
||||
});
|
||||
}
|
||||
return tagsAddedToResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method deleteAnnotations
|
||||
* @param {DomainObject} annotation - An annotation to undelete (set _deleted to false)
|
||||
*/
|
||||
unDeleteAnnotation(annotation) {
|
||||
if (!annotation) {
|
||||
throw new Error('Asked to undelete null annotation! 🙅♂️');
|
||||
}
|
||||
|
||||
this.openmct.objects.mutate(annotation, '_deleted', false);
|
||||
}
|
||||
|
||||
getTagsFromAnnotations(annotations, filterDuplicates = true) {
|
||||
if (!annotations) {
|
||||
return [];
|
||||
}
|
||||
|
||||
let tagsFromAnnotations = annotations.flatMap((annotation) => {
|
||||
if (annotation._deleted) {
|
||||
return [];
|
||||
} else {
|
||||
return annotation.tags;
|
||||
}
|
||||
});
|
||||
|
||||
if (filterDuplicates) {
|
||||
tagsFromAnnotations = tagsFromAnnotations.filter((tag, index, tagArray) => {
|
||||
return tagArray.indexOf(tag) === index;
|
||||
});
|
||||
}
|
||||
|
||||
const fullTagModels = this.#addTagMetaInformationToTags(tagsFromAnnotations);
|
||||
|
||||
return fullTagModels;
|
||||
}
|
||||
|
||||
#addTagMetaInformationToTags(tags) {
|
||||
return tags.map(tagKey => {
|
||||
const tagModel = this.availableTags[tagKey];
|
||||
tagModel.tagID = tagKey;
|
||||
|
||||
return tagModel;
|
||||
});
|
||||
}
|
||||
|
||||
#getMatchingTags(query) {
|
||||
if (!query) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const matchingTags = Object.keys(this.availableTags).filter(tagKey => {
|
||||
if (this.availableTags[tagKey] && this.availableTags[tagKey].label) {
|
||||
return this.availableTags[tagKey].label.toLowerCase().includes(query.toLowerCase());
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
return matchingTags;
|
||||
}
|
||||
|
||||
#addTagMetaInformationToResults(results, matchingTagKeys) {
|
||||
const tagsAddedToResults = results.map(result => {
|
||||
const fullTagModels = this.#addTagMetaInformationToTags(result.tags);
|
||||
async #addTargetModelsToResults(results) {
|
||||
const modelAddedToResults = await Promise.all(
|
||||
results.map(async (result) => {
|
||||
const targetModels = await Promise.all(
|
||||
Object.keys(result.targets).map(async (targetID) => {
|
||||
const targetModel = await this.openmct.objects.get(targetID);
|
||||
const targetKeyString = this.openmct.objects.makeKeyString(targetModel.identifier);
|
||||
const originalPathObjects = await this.openmct.objects.getOriginalPath(targetKeyString);
|
||||
|
||||
return {
|
||||
fullTagModels,
|
||||
matchingTagKeys,
|
||||
...result
|
||||
originalPath: originalPathObjects,
|
||||
...targetModel
|
||||
};
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
return tagsAddedToResults;
|
||||
return {
|
||||
targetModels,
|
||||
...result
|
||||
};
|
||||
})
|
||||
);
|
||||
|
||||
return modelAddedToResults;
|
||||
}
|
||||
|
||||
#combineSameTargets(results) {
|
||||
const combinedResults = [];
|
||||
results.forEach((currentAnnotation) => {
|
||||
const existingAnnotation = combinedResults.find((annotationToFind) => {
|
||||
return _.isEqual(currentAnnotation.targets, annotationToFind.targets);
|
||||
});
|
||||
if (!existingAnnotation) {
|
||||
combinedResults.push(currentAnnotation);
|
||||
} else {
|
||||
existingAnnotation.tags.push(...currentAnnotation.tags);
|
||||
}
|
||||
});
|
||||
|
||||
return combinedResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method #breakApartSeparateTargets
|
||||
* @param {Array} results A set of search results that could have the multiple targets for the same result
|
||||
* @returns {Array} The same set of results, but with each target separated out into its own result
|
||||
*/
|
||||
#breakApartSeparateTargets(results) {
|
||||
const separateResults = [];
|
||||
results.forEach((result) => {
|
||||
Object.keys(result.targets).forEach((targetID) => {
|
||||
const separatedResult = {
|
||||
...result
|
||||
};
|
||||
separatedResult.targets = {
|
||||
[targetID]: result.targets[targetID]
|
||||
};
|
||||
separatedResult.targetModels = result.targetModels.filter((targetModel) => {
|
||||
const targetKeyString = this.openmct.objects.makeKeyString(targetModel.identifier);
|
||||
|
||||
return targetKeyString === targetID;
|
||||
});
|
||||
separateResults.push(separatedResult);
|
||||
});
|
||||
});
|
||||
|
||||
return separateResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method searchForTags
|
||||
* @param {String} query A query to match against tags. E.g., "dr" will match the tags "drilling" and "driving"
|
||||
* @param {Object} [abortController] An optional abort method to stop the query
|
||||
* @returns {Promise} returns a model of matching tags with their target domain objects attached
|
||||
*/
|
||||
async searchForTags(query, abortController) {
|
||||
const matchingTagKeys = this.#getMatchingTags(query);
|
||||
if (!matchingTagKeys.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
async #addTargetModelsToResults(results) {
|
||||
const modelAddedToResults = await Promise.all(results.map(async result => {
|
||||
const targetModels = await Promise.all(Object.keys(result.targets).map(async (targetID) => {
|
||||
const targetModel = await this.openmct.objects.get(targetID);
|
||||
const targetKeyString = this.openmct.objects.makeKeyString(targetModel.identifier);
|
||||
const originalPathObjects = await this.openmct.objects.getOriginalPath(targetKeyString);
|
||||
const searchResults = (
|
||||
await Promise.all(
|
||||
this.openmct.objects.search(
|
||||
matchingTagKeys,
|
||||
abortController,
|
||||
this.openmct.objects.SEARCH_TYPES.TAGS
|
||||
)
|
||||
)
|
||||
).flat();
|
||||
const filteredDeletedResults = searchResults.filter((result) => {
|
||||
return !result._deleted;
|
||||
});
|
||||
const combinedSameTargets = this.#combineSameTargets(filteredDeletedResults);
|
||||
const appliedTagSearchResults = this.#addTagMetaInformationToResults(
|
||||
combinedSameTargets,
|
||||
matchingTagKeys
|
||||
);
|
||||
const appliedTargetsModels = await this.#addTargetModelsToResults(appliedTagSearchResults);
|
||||
const resultsWithValidPath = appliedTargetsModels.filter((result) => {
|
||||
return this.openmct.objects.isReachable(result.targetModels?.[0]?.originalPath);
|
||||
});
|
||||
const breakApartSeparateTargets = this.#breakApartSeparateTargets(resultsWithValidPath);
|
||||
|
||||
return {
|
||||
originalPath: originalPathObjects,
|
||||
...targetModel
|
||||
};
|
||||
}));
|
||||
|
||||
return {
|
||||
targetModels,
|
||||
...result
|
||||
};
|
||||
}));
|
||||
|
||||
return modelAddedToResults;
|
||||
}
|
||||
|
||||
#combineSameTargets(results) {
|
||||
const combinedResults = [];
|
||||
results.forEach(currentAnnotation => {
|
||||
const existingAnnotation = combinedResults.find((annotationToFind) => {
|
||||
return _.isEqual(currentAnnotation.targets, annotationToFind.targets);
|
||||
});
|
||||
if (!existingAnnotation) {
|
||||
combinedResults.push(currentAnnotation);
|
||||
} else {
|
||||
existingAnnotation.tags.push(...currentAnnotation.tags);
|
||||
}
|
||||
});
|
||||
|
||||
return combinedResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method #breakApartSeparateTargets
|
||||
* @param {Array} results A set of search results that could have the multiple targets for the same result
|
||||
* @returns {Array} The same set of results, but with each target separated out into its own result
|
||||
*/
|
||||
#breakApartSeparateTargets(results) {
|
||||
const separateResults = [];
|
||||
results.forEach(result => {
|
||||
Object.keys(result.targets).forEach(targetID => {
|
||||
const separatedResult = {
|
||||
...result
|
||||
};
|
||||
separatedResult.targets = {
|
||||
[targetID]: result.targets[targetID]
|
||||
};
|
||||
separatedResult.targetModels = result.targetModels.filter(targetModel => {
|
||||
const targetKeyString = this.openmct.objects.makeKeyString(targetModel.identifier);
|
||||
|
||||
return targetKeyString === targetID;
|
||||
});
|
||||
separateResults.push(separatedResult);
|
||||
});
|
||||
});
|
||||
|
||||
return separateResults;
|
||||
}
|
||||
|
||||
/**
|
||||
* @method searchForTags
|
||||
* @param {String} query A query to match against tags. E.g., "dr" will match the tags "drilling" and "driving"
|
||||
* @param {Object} [abortController] An optional abort method to stop the query
|
||||
* @returns {Promise} returns a model of matching tags with their target domain objects attached
|
||||
*/
|
||||
async searchForTags(query, abortController) {
|
||||
const matchingTagKeys = this.#getMatchingTags(query);
|
||||
if (!matchingTagKeys.length) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const searchResults = (await Promise.all(this.openmct.objects.search(matchingTagKeys, abortController, this.openmct.objects.SEARCH_TYPES.TAGS))).flat();
|
||||
const filteredDeletedResults = searchResults.filter((result) => {
|
||||
return !(result._deleted);
|
||||
});
|
||||
const combinedSameTargets = this.#combineSameTargets(filteredDeletedResults);
|
||||
const appliedTagSearchResults = this.#addTagMetaInformationToResults(combinedSameTargets, matchingTagKeys);
|
||||
const appliedTargetsModels = await this.#addTargetModelsToResults(appliedTagSearchResults);
|
||||
const resultsWithValidPath = appliedTargetsModels.filter(result => {
|
||||
return this.openmct.objects.isReachable(result.targetModels?.[0]?.originalPath);
|
||||
});
|
||||
const breakApartSeparateTargets = this.#breakApartSeparateTargets(resultsWithValidPath);
|
||||
|
||||
return breakApartSeparateTargets;
|
||||
}
|
||||
return breakApartSeparateTargets;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user