Compare commits

...

14 Commits

Author SHA1 Message Date
Andrew Henry
4ff96ff091 Don't delete cache entry 2021-03-13 17:26:02 -08:00
Andrew Henry
ad87dd6fdc Only batch if > 1 2021-03-13 17:20:23 -08:00
Andrew Henry
80c833db88 Batch requests 2021-03-13 13:32:02 -08:00
Andrew Henry
a756891ccd Promises, not await 2021-03-13 11:57:12 -08:00
Andrew Henry
2e1b6c5190 Implemented search in couch provider 2021-03-13 10:30:55 -08:00
Jamie V
b042d9098d doing correct comparison to find page to delete (#3754) 2021-03-12 15:49:58 -08:00
Shefali Joshi
325f2c4860 Pinch to zoom and wheel zoom work the same way (#3752) 2021-03-12 12:22:22 -08:00
Jamie V
74a516aa9e [Date Picker] Highlight Selected Date (#3678)
* WIP: added color, was not sure correct sass variable, charles... take it from here!

* adding charles name to the comment for posterity

Co-authored-by: Deep Tailor <deep.j.tailor@nasa.gov>
2021-03-11 10:25:30 -08:00
Shefali Joshi
28e26461cc Change master to 1.6.3 SNAPSHOT (#3749) 2021-03-10 10:40:30 -08:00
David Tsay
cfaaf6b1fe [Imagery] Update to be compatible with VIPER (#3744)
* heading, sun heading, and camera pan  are all absolute directions
* removing roll and pitch keys as they will not be necessary
* proofing against empty historical or realtime ids from config
* adding checks in imagerylayout for missing properties

Co-authored-by: Jamie Vigliotta <jamie.j.vigliotta@nasa.gov>
2021-03-08 15:27:35 -08:00
Shefali Joshi
bffe79ecbd Pass object path when getting views during object creation (#3736) 2021-03-04 10:17:14 -08:00
Shefali Joshi
94d9852339 Force Vue to look for the reactive property and recompute views (#3733)
Co-authored-by: Deep Tailor <deep.j.tailor@nasa.gov>
2021-03-03 15:42:55 -08:00
Jamie V
905e397d3f making sure ALL telemetry for a given indicator is fresh (#3734) 2021-03-03 15:37:49 -08:00
Shefali Joshi
e70a636073 Accept plans from a file OR from JSON object (couchDB) (#3729)
Co-authored-by: Deep Tailor <deep.j.tailor@nasa.gov>
2021-03-03 14:50:48 -08:00
17 changed files with 180 additions and 89 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "openmct",
"version": "1.6.2-SNAPSHOT",
"version": "1.6.3-SNAPSHOT",
"description": "The Open MCT core platform",
"dependencies": {},
"devDependencies": {

View File

@@ -37,7 +37,7 @@ define([
context.domainObject.getModel(),
objectUtils.parseKeyString(context.domainObject.getId())
);
const providers = mct.propertyEditors.get(domainObject);
const providers = mct.propertyEditors.get(domainObject, mct.router.path);
if (providers.length > 0) {
action.dialogService = Object.create(action.dialogService);

View File

@@ -180,7 +180,7 @@ ObjectAPI.prototype.get = function (identifier, abortSignal) {
this.cache[keystring] = objectPromise;
return objectPromise.then(result => {
delete this.cache[keystring];
//delete this.cache[keystring];
result = this.applyGetInterceptors(identifier, result);
return result;

View File

@@ -27,7 +27,6 @@
>
<CompassHUD
v-if="hasCameraFieldOfView"
:heading="heading"
:sun-heading="sunHeading"
:camera-angle-of-view="cameraAngleOfView"
:camera-pan="cameraPan"
@@ -79,26 +78,20 @@ export default {
},
computed: {
hasCameraFieldOfView() {
return this.heading !== undefined && this.cameraPan !== undefined;
return this.cameraPan !== undefined && this.cameraAngleOfView > 0;
},
// compass direction from north in degrees
// horizontal rotation from north in degrees
heading() {
return this.image.heading;
},
pitch() {
return this.image.pitch;
},
// compass direction from north in degrees
// horizontal rotation from north in degrees
sunHeading() {
return this.image.sunOrientation;
},
// relative direction from heading in degrees
// horizontal rotation from north in degrees
cameraPan() {
return this.image.cameraPan;
},
cameraTilt() {
return this.image.cameraTilt;
},
cameraAngleOfView() {
return CAMERA_ANGLE_OF_VIEW;
},

View File

@@ -94,10 +94,6 @@ const COMPASS_POINTS = [
export default {
props: {
heading: {
type: Number,
required: true
},
sunHeading: {
type: Number,
default: undefined
@@ -136,8 +132,8 @@ export default {
},
visibleRange() {
return [
rotate(this.heading, this.cameraPan, -this.cameraAngleOfView / 2),
rotate(this.heading, this.cameraPan, this.cameraAngleOfView / 2)
rotate(this.cameraPan, -this.cameraAngleOfView / 2),
rotate(this.cameraPan, this.cameraAngleOfView / 2)
];
}
}

View File

@@ -27,7 +27,7 @@
>
<div
class="c-nsew"
:style="rotateFrameStyle"
:style="compassRoseStyle"
>
<svg
class="c-nsew__minor-ticks"
@@ -118,21 +118,21 @@
</div>
<div
v-if="hasHeading"
class="c-spacecraft-body"
:style="headingStyle"
>
</div>
<div
v-if="showSunHeading"
v-if="hasSunHeading"
class="c-sun"
:style="sunHeadingStyle"
></div>
<div
v-if="showCameraFOV"
class="c-cam-field"
:style="cameraHeadingStyle"
:style="cameraPanStyle"
>
<div class="cam-field-half cam-field-half-l">
<div
@@ -177,16 +177,10 @@ export default {
}
},
computed: {
cameraHeading() {
return rotate(this.heading, this.cameraPan);
},
compassHeading() {
return this.lockCompass ? this.cameraHeading : 0;
},
north() {
return rotate(this.compassHeading, -this.cameraHeading);
return this.lockCompass ? rotate(-this.cameraPan) : 0;
},
rotateFrameStyle() {
compassRoseStyle() {
return { transform: `rotate(${ this.north }deg)` };
},
northTextTransform() {
@@ -216,6 +210,9 @@ export default {
west: `translate(50,87) ${ rotation }`
};
},
hasHeading() {
return this.heading !== undefined;
},
headingStyle() {
const rotation = rotate(this.north, this.heading);
@@ -223,14 +220,7 @@ export default {
transform: `translateX(-50%) rotate(${ rotation }deg)`
};
},
cameraHeadingStyle() {
const rotation = rotate(this.north, this.cameraHeading);
return {
transform: `rotate(${ rotation }deg)`
};
},
showSunHeading() {
hasSunHeading() {
return this.sunHeading !== undefined;
},
sunHeadingStyle() {
@@ -240,18 +230,22 @@ export default {
transform: `rotate(${ rotation }deg)`
};
},
showCameraFOV() {
return this.cameraPan !== undefined && this.cameraAngleOfView > 0;
cameraPanStyle() {
const rotation = rotate(this.north, this.cameraPan);
return {
transform: `rotate(${ rotation }deg)`
};
},
// left half of camera field of view
// rotated counter-clockwise from camera field of view heading
// rotated counter-clockwise from camera pan angle
cameraFOVStyleLeftHalf() {
return {
transform: `translateX(50%) rotate(${ -this.cameraAngleOfView / 2 }deg)`
};
},
// right half of camera field of view
// rotated clockwise from camera field of view heading
// rotated clockwise from camera pan angle
cameraFOVStyleRightHalf() {
return {
transform: `translateX(-50%) rotate(${ this.cameraAngleOfView / 2 }deg)`

View File

@@ -1,23 +1,28 @@
export function rotate(direction, ...rotations) {
/**
*
* sums an arbitrary number of absolute rotations
* (meaning rotations relative to one common direction 0)
* normalizes the rotation to the range [0, 360)
*
* @param {...number} rotations in degrees
* @returns {number} normalized sum of all rotations - [0, 360) degrees
*/
export function rotate(...rotations) {
const rotation = rotations.reduce((a, b) => a + b, 0);
return normalizeCompassDirection(direction + rotation);
}
export function normalizeCompassDirection(degrees) {
const base = degrees % 360;
return base >= 0 ? base : 360 + base;
return normalizeCompassDirection(rotation);
}
export function inRange(degrees, [min, max]) {
const point = rotate(degrees);
return min > max
? (degrees >= min && degrees < 360) || (degrees <= max && degrees >= 0)
: degrees >= min && degrees <= max;
? (point >= min && point < 360) || (point <= max && point >= 0)
: point >= min && point <= max;
}
export function percentOfRange(degrees, [min, max]) {
let distance = degrees;
let distance = rotate(degrees);
let minRange = min;
let maxRange = max;
@@ -31,3 +36,9 @@ export function percentOfRange(degrees, [min, max]) {
return (distance - minRange) / (maxRange - minRange);
}
function normalizeCompassDirection(degrees) {
const base = degrees % 360;
return base >= 0 ? base : 360 + base;
}

View File

@@ -273,7 +273,7 @@ export default {
isFresh = true;
for (let key of this.spacecraftPositionKeys) {
if (this.relatedTelemetry[key] && latest[key] && focused[key]) {
isFresh = Boolean(this.relatedTelemetry[key].comparisonFunction(latest[key], focused[key]));
isFresh = isFresh && Boolean(this.relatedTelemetry[key].comparisonFunction(latest[key], focused[key]));
} else {
isFresh = false;
}
@@ -291,7 +291,7 @@ export default {
isFresh = true;
for (let key of this.spacecraftOrientationKeys) {
if (this.relatedTelemetry[key] && latest[key] && focused[key]) {
isFresh = Boolean(this.relatedTelemetry[key].comparisonFunction(latest[key], focused[key]));
isFresh = isFresh && Boolean(this.relatedTelemetry[key].comparisonFunction(latest[key], focused[key]));
} else {
isFresh = false;
}
@@ -312,7 +312,7 @@ export default {
if (this.isSpacecraftPositionFresh && this.isSpacecraftOrientationFresh) {
for (let key of this.cameraKeys) {
if (this.relatedTelemetry[key] && latest[key] && focused[key]) {
isFresh = Boolean(this.relatedTelemetry[key].comparisonFunction(latest[key], focused[key]));
isFresh = isFresh && Boolean(this.relatedTelemetry[key].comparisonFunction(latest[key], focused[key]));
} else {
isFresh = false;
}
@@ -348,7 +348,7 @@ export default {
// related telemetry keys
this.spacecraftPositionKeys = ['positionX', 'positionY', 'positionZ'];
this.spacecraftOrientationKeys = ['heading', 'roll', 'pitch'];
this.spacecraftOrientationKeys = ['heading'];
this.cameraKeys = ['cameraPan', 'cameraTilt'];
this.sunKeys = ['sunOrientation'];
@@ -468,7 +468,12 @@ export default {
// set data ON image telemetry as well as in focusedImageRelatedTelemetry
for (let key of this.relatedTelemetry.keys) {
if (this.relatedTelemetry[key] && this.relatedTelemetry[key].historical) {
if (
this.relatedTelemetry[key]
&& this.relatedTelemetry[key].historical
&& this.relatedTelemetry[key].requestLatestFor
) {
let valuesOnTelemetry = this.relatedTelemetry[key].hasTelemetryOnDatum;
let value = await this.getMostRecentRelatedTelemetry(key, this.focusedImage);

View File

@@ -73,7 +73,7 @@ export default class RelatedTelemetry {
await this._initializeHistorical(key);
}
if (this[key].realtime && this[key].realtime.telemetryObjectId) {
if (this[key].realtime && this[key].realtime.telemetryObjectId && this[key].realtime.telemetryObjectId !== '') {
await this._intializeRealtime(key);
}
}
@@ -82,7 +82,9 @@ export default class RelatedTelemetry {
}
async _initializeHistorical(key) {
if (this[key].historical.telemetryObjectId) {
if (!this[key].historical.telemetryObjectId) {
this[key].historical.hasTelemetryOnDatum = true;
} else if (this[key].historical.telemetryObjectId !== '') {
this[key].historicalDomainObject = await this._openmct.objects.get(this[key].historical.telemetryObjectId);
this[key].requestLatestFor = async (datum) => {
@@ -96,8 +98,6 @@ export default class RelatedTelemetry {
return results[results.length - 1];
};
} else {
this[key].historical.hasTelemetryOnDatum = true;
}
}

View File

@@ -69,7 +69,7 @@ export default {
methods: {
deletePage(id) {
const selectedSection = this.sections.find(s => s.isSelected);
const page = this.pages.find(p => p.id !== id);
const page = this.pages.find(p => p.id === id);
deleteNotebookEntries(this.openmct, this.domainObject, selectedSection, page);
const selectedPage = this.pages.find(p => p.isSelected);

View File

@@ -26,6 +26,7 @@ import CouchObjectQueue from "./CouchObjectQueue";
const REV = "_rev";
const ID = "_id";
const HEARTBEAT = 50000;
const ALL_DOCS = "_all_docs?include_docs=true";
export default class CouchObjectProvider {
// options {
@@ -67,6 +68,9 @@ export default class CouchObjectProvider {
// stringify body if needed
if (fetchOptions.body) {
fetchOptions.body = JSON.stringify(fetchOptions.body);
fetchOptions.headers = {
"Content-Type": "application/json"
};
}
return fetch(this.url + '/' + subPath, fetchOptions)
@@ -131,10 +135,70 @@ export default class CouchObjectProvider {
}
get(identifier, abortSignal) {
return this.request(identifier.key, "GET", undefined, abortSignal).then(this.getModel.bind(this));
return new Promise((resolve, reject) => {
this.batchIds = this.batchIds || [];
this.batchIds.push(identifier.key);
if (this.bulkPromise === undefined) {
this.bulkPromise = new Promise((bulkResolve, bulkReject) => {
setTimeout(() => {
let batchIds = this.batchIds;
delete this.batchIds;
delete this.bulkPromise;
if (batchIds.length === 1) {
this.request(identifier.key, "GET", undefined, abortSignal)
.then((result) => resolve(this.getModel(result)));
} else {
this.bulkGet(batchIds, abortSignal)
.then(bulkResolve)
.catch(bulkReject);
}
});
});
}
this.bulkPromise
.then((domainObjectMap) => {
resolve(domainObjectMap[identifier.key]);
})
.catch(error => reject(error));
});
}
async getObjectsByFilter(filter) {
bulkGet(ids, signal) {
//Remove dupes
ids = Array.from(new Set(ids));
const query = {
'keys': ids
};
return this.request(ALL_DOCS, 'POST', query, signal).then((response) => {
return response.rows.reduce((map, row) => {
if (row.doc !== undefined) {
map[row.key] = this.getModel(row.doc);
}
return map;
}, {});
});
}
search(query, abortSignal) {
const filter = {
"selector": {
"model": {
"name": {
"$regex": `(?i)${query}`
}
}
}
};
return this.getObjectsByFilter(filter, abortSignal);
}
async getObjectsByFilter(filter, abortSignal) {
let objects = [];
let url = `${this.url}/_find`;
@@ -149,6 +213,7 @@ export default class CouchObjectProvider {
headers: {
"Content-Type": "application/json"
},
signal: abortSignal,
body
});

View File

@@ -143,5 +143,9 @@ describe('the plugin', () => {
expect(couchProvider.updateQueued).toHaveBeenCalledTimes(2);
});
describe('batches object requests', () => {
//NEED TO MAKE SURE THERE ARE NO RACE CONDITIONS WHERE REQUESTS FOR OBJECTS ARE DROPPED
});
});
});

View File

@@ -1,10 +1,14 @@
export function getValidatedPlan(domainObject) {
let jsonString = domainObject.selectFile.body;
let body = domainObject.selectFile.body;
let json = {};
try {
json = JSON.parse(jsonString);
} catch (e) {
return json;
if (typeof body === 'string') {
try {
json = JSON.parse(body);
} catch (e) {
return json;
}
} else {
json = body;
}
return json;

View File

@@ -413,6 +413,21 @@ define([
return;
}
const isPinchToZoom = event.ctrlKey === true;
let isZoomIn = event.wheelDelta < 0;
let isZoomOut = event.wheelDelta >= 0;
//Flip the zoom direction if this is pinch to zoom
if (isPinchToZoom) {
if (isZoomIn === true) {
isZoomOut = true;
isZoomIn = false;
} else if (isZoomOut === true) {
isZoomIn = true;
isZoomOut = false;
}
}
let xDisplayRange = this.$scope.xAxis.get('displayRange');
let yDisplayRange = this.$scope.yAxis.get('displayRange');
@@ -445,7 +460,7 @@ define([
};
}
if (event.wheelDelta < 0) {
if (isZoomIn) {
this.$scope.xAxis.set('displayRange', {
min: xDisplayRange.min + ((xAxisDist * ZOOM_AMT) * xAxisMinDist),
@@ -456,7 +471,7 @@ define([
min: yDisplayRange.min + ((yAxisDist * ZOOM_AMT) * yAxisMinDist),
max: yDisplayRange.max - ((yAxisDist * ZOOM_AMT) * yAxisMaxDist)
});
} else if (event.wheelDelta >= 0) {
} else if (isZoomOut) {
this.$scope.xAxis.set('displayRange', {
min: xDisplayRange.min - ((xAxisDist * ZOOM_AMT) * xAxisMinDist),

View File

@@ -67,6 +67,10 @@
&.is-in-month {
background: $colorMenuElementHilite;
}
&.selected {
background: #1ac6ff; // this should be a variable... CHARLESSSSSS
}
}
&__day {

View File

@@ -159,7 +159,7 @@ export default {
return this.views.filter(v => v.key === this.viewKey)[0] || {};
},
views() {
if (this.openmct.router.started !== true) {
if (this.domainObject && (this.openmct.router.started !== true)) {
return [];
}

View File

@@ -710,25 +710,25 @@ export default {
}
});
},
async aggregateSearchResults(results, abortSignal) {
aggregateSearchResults(results, abortSignal) {
for (const result of results) {
if (!abortSignal.aborted) {
const objectPath = await this.openmct.objects.getOriginalPath(result.identifier);
this.openmct.objects.getOriginalPath(result.identifier).then((objectPath) => {
// removing the item itself, as the path we pass to buildTreeItem is a parent path
objectPath.shift();
// removing the item itself, as the path we pass to buildTreeItem is a parent path
objectPath.shift();
// if root, remove, we're not using in object path for tree
let lastObject = objectPath.length ? objectPath[objectPath.length - 1] : false;
if (lastObject && lastObject.type === 'root') {
objectPath.pop();
}
// if root, remove, we're not using in object path for tree
let lastObject = objectPath.length ? objectPath[objectPath.length - 1] : false;
if (lastObject && lastObject.type === 'root') {
objectPath.pop();
}
// we reverse the objectPath in the tree, so have to do it here first,
// since this one is already in the correct direction
let resultObject = this.buildTreeItem(result, objectPath.reverse());
// we reverse the objectPath in the tree, so have to do it here first,
// since this one is already in the correct direction
let resultObject = this.buildTreeItem(result, objectPath.reverse());
this.searchResultItems.push(resultObject);
this.searchResultItems.push(resultObject);
});
}
}
},