Compare commits
14 Commits
plan-accep
...
introduce-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ff96ff091 | ||
|
|
ad87dd6fdc | ||
|
|
80c833db88 | ||
|
|
a756891ccd | ||
|
|
2e1b6c5190 | ||
|
|
b042d9098d | ||
|
|
325f2c4860 | ||
|
|
74a516aa9e | ||
|
|
28e26461cc | ||
|
|
cfaaf6b1fe | ||
|
|
bffe79ecbd | ||
|
|
94d9852339 | ||
|
|
905e397d3f | ||
|
|
e70a636073 |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openmct",
|
||||
"version": "1.6.2-SNAPSHOT",
|
||||
"version": "1.6.3-SNAPSHOT",
|
||||
"description": "The Open MCT core platform",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
|
||||
@@ -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)
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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)`
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
});
|
||||
|
||||
|
||||
@@ -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
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -67,6 +67,10 @@
|
||||
&.is-in-month {
|
||||
background: $colorMenuElementHilite;
|
||||
}
|
||||
|
||||
&.selected {
|
||||
background: #1ac6ff; // this should be a variable... CHARLESSSSSS
|
||||
}
|
||||
}
|
||||
|
||||
&__day {
|
||||
|
||||
@@ -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 [];
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user