2.0.4 merge into master (#5297)

* Release 2.0.3

* Fix tick values for plots ticks in log mode and null check (#5119)

* [2297] When there is no display range or range, skip setting the range value when auto scale is turned off.

* If the formatted value is a number and a float, set precision to 2 decimal points.

* Fix value assignment

* Use whole numbers in log mode

* Revert whole numbers fix - need floats for values between 0 and 1.

* Handle scrolling to focused image on resize/new data (#5121)

* Scroll to focused image when view resizes - this will force scrolling to focused image when going to/from view large mode

* Scroll to the right if there is no paused focused image

* [LAD Tables] Use Telemetry Collections (#5127)

* Use telemetry collections to handle bounds checks

* added telemetry collection to alphanumeric telemetry view (#5131)

* Added animation styling for POS and CAM; adjusted cutoff for isNewImage (#5116)

* Added animation styling for POS and CAM; adjusted cutoff for isNewImage

* Remove animation from POS and CAM

* Fix transactions overwriting latest objects with stale objects on save (#5132)

* use object (map) instead of set to track dirty objects
* fix tests due to internals change

Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>

* Gauge edit enabled 2.0.3 (#5133)

* Gauge plugin #4896, add edit mode

* Dynamic dial-type Gauge sizing by height and width (#5129)

* Improve sizing strategy for gauges.
* Do not install gauge by default for now

Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
Co-authored-by: Jamie Vigliotta <jamie.j.vigliotta@nasa.gov>
Co-authored-by: Andrew Henry <akhenry@gmail.com>

* [Telemetry Collections] Include data with start and end bounds (#5145)

* Reverts forced precision for log plots axis labels (#5147)

* Condition Widgets trigger hundreds of persistence calls (#5146)

Co-authored-by: unlikelyzero <jchill2@gmail.com>

* Update version for 2.0.4 (#5255)

* Eliminate NaN conditions and clear stale duration (#5248)

* Temp source map fix 2.0.4 (#5267)

* use dev mode for production

* mode -> production

* added extra devtool options

* wip

* Imagery Fixes for release/2.0.4 (#5282)

* Fallback for height

* Remove duplicated requestHistory call since setDataTimeContext already invokes it on mount

* Inverted datumIsNotValid and refactored requestHistory

* Remove old datumIsNotValid func

* Return false if datum is falsy

* Corrected brightness/contrast input

* Clone default values to avoid mutation

* Changed index of imageTelemetry to an item within bounds

* Implement clearData test for imagery differently

* x-out clearData tests

Co-authored-by: Joshi <simplyrender@gmail.com>

* Imagery test fixes (#5293)

* Fallback for height

* Remove duplicated requestHistory call since setDataTimeContext already invokes it on mount

* Inverted datumIsNotValid and refactored requestHistory

* Remove old datumIsNotValid func

* Return false if datum is falsy

* Corrected brightness/contrast input

* Clone default values to avoid mutation

* Changed index of imageTelemetry to an item within bounds

* Implement clearData test for imagery differently

* x-out clearData tests

* Set bounds on each test rather than the wrapper

Co-authored-by: Michael Rogers <contact@mhrogers.com>

* Imagery validation fix (#5295)

* Remove check for duplicate images
* Remove commented out code and add TODO

* lint fix

* Add missing tests

* Use the master version and ignore release/2.0.4 changes

Co-authored-by: Jamie V <jamie.j.vigliotta@nasa.gov>
Co-authored-by: Michael Rogers <contact@mhrogers.com>
Co-authored-by: David Tsay <3614296+davetsay@users.noreply.github.com>
Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com>
Co-authored-by: Andrew Henry <akhenry@gmail.com>
Co-authored-by: unlikelyzero <jchill2@gmail.com>
This commit is contained in:
Shefali Joshi 2022-06-08 18:06:31 -07:00 committed by GitHub
parent 370e6a0c37
commit 0f0c6a7b17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 104 additions and 84 deletions

View File

@ -173,7 +173,7 @@ export default {
this.$emit('filtersUpdated', this.filters);
},
handleResetFilters() {
this.filters = DEFAULT_FILTER_VALUES;
this.filters = {...DEFAULT_FILTER_VALUES};
this.notifyFiltersChanged();
},
limitZoomRange(factor) {

View File

@ -403,6 +403,9 @@ export default {
formattedDuration() {
let result = 'N/A';
let negativeAge = -1;
if (!Number.isInteger(this.numericDuration)) {
return result;
}
if (this.numericDuration > TWENTYFOUR_HOURS) {
negativeAge *= (this.numericDuration / TWENTYFOUR_HOURS);
@ -905,8 +908,10 @@ export default {
let currentTime = this.timeContext.clock() && this.timeContext.clock().currentValue();
if (currentTime === undefined) {
this.numericDuration = currentTime;
} else {
} else if (Number.isInteger(this.parsedSelectedTime)) {
this.numericDuration = currentTime - this.parsedSelectedTime;
} else {
this.numericDuration = undefined;
}
},
resetAgeCSS() {

View File

@ -72,6 +72,7 @@
background-position: center;
background-repeat: no-repeat;
background-size: contain;
height: 100%; //fallback value
}
&__image {
// Present to allow Save As... image

View File

@ -70,22 +70,18 @@ export default {
this.timeContext.off('timeSystem', this.timeSystemChange);
}
},
datumIsNotValid(datum) {
if (this.imageHistory.length === 0) {
isDatumValid(datum) {
//TODO: Add a check to see if there are duplicate images (identical image timestamp and url subsequently)
if (!datum) {
return false;
}
const datumURL = this.formatImageUrl(datum);
const lastHistoryURL = this.formatImageUrl(this.imageHistory.slice(-1)[0]);
// datum is not valid if it matches the last datum in history,
// or it is before the last datum in the history
const datumTimeCheck = this.parseTime(datum);
const historyTimeCheck = this.parseTime(this.imageHistory.slice(-1)[0]);
const matchesLast = (datumTimeCheck === historyTimeCheck) && (datumURL === lastHistoryURL);
const isStale = datumTimeCheck < historyTimeCheck;
const bounds = this.timeContext.bounds();
return matchesLast || isStale;
const isOutOfBounds = datumTimeCheck < bounds.start || datumTimeCheck > bounds.end;
return !isOutOfBounds;
},
formatImageUrl(datum) {
if (!datum) {
@ -132,25 +128,19 @@ export default {
return this.requestHistory();
},
async requestHistory() {
let bounds = this.timeContext.bounds();
this.requestCount++;
const requestId = this.requestCount;
this.imageHistory = [];
const bounds = this.timeContext.bounds();
let data = await this.openmct.telemetry
const data = await this.openmct.telemetry
.request(this.domainObject, bounds) || [];
if (this.requestCount === requestId) {
let imagery = [];
data.forEach((datum) => {
let image = this.normalizeDatum(datum);
if (image) {
imagery.push(image);
}
});
//this is to optimize anything that reacts to imageHistory length
this.imageHistory = imagery;
// wait until new request resolves to do comparison
if (this.requestCount !== requestId) {
return this.imageHistory = [];
}
const imagery = data.filter(this.isDatumValid).map(this.normalizeDatum);
this.imageHistory = imagery;
},
clearData(domainObjectToClear) {
// global clearData button is accepted therefore no truthy check on inputted param
@ -180,27 +170,29 @@ export default {
.subscribe(this.domainObject, (datum) => {
let parsedTimestamp = this.parseTime(datum);
let bounds = this.timeContext.bounds();
if (!(parsedTimestamp >= bounds.start && parsedTimestamp <= bounds.end)) {
return;
}
if (parsedTimestamp >= bounds.start && parsedTimestamp <= bounds.end) {
let image = this.normalizeDatum(datum);
if (image) {
this.imageHistory.push(image);
}
if (this.isDatumValid(datum)) {
this.imageHistory.push(this.normalizeDatum(datum));
}
});
},
normalizeDatum(datum) {
if (this.datumIsNotValid(datum)) {
return;
}
let image = { ...datum };
image.formattedTime = this.formatTime(datum);
image.url = this.formatImageUrl(datum);
image.time = this.parseTime(image.formattedTime);
image.imageDownloadName = this.getImageDownloadName(datum);
const formattedTime = this.formatTime(datum);
const url = this.formatImageUrl(datum);
const time = this.parseTime(formattedTime);
const imageDownloadName = this.getImageDownloadName(datum);
return image;
return {
...datum,
formattedTime,
url,
time,
imageDownloadName
};
},
getFormatter(key) {
let metadataValue = this.metadata.value(key) || { format: key };

View File

@ -84,7 +84,6 @@ describe("The Imagery View Layouts", () => {
let telemetryPromise;
let telemetryPromiseResolve;
let cleanupFirst;
let isClearDataTriggered;
let openmct;
let parent;
@ -205,20 +204,12 @@ describe("The Imagery View Layouts", () => {
cleanupFirst = [];
openmct = createOpenMct();
openmct.time.timeSystem('utc', {
start: START - (5 * ONE_MINUTE),
end: START + (5 * ONE_MINUTE)
});
telemetryPromise = new Promise((resolve) => {
telemetryPromiseResolve = resolve;
});
spyOn(openmct.telemetry, 'request').and.callFake(() => {
if (isClearDataTriggered) {
return [];
}
telemetryPromiseResolve(imageTelemetry);
return telemetryPromise;
@ -337,44 +328,93 @@ describe("The Imagery View Layouts", () => {
expect(imageryView).toBeDefined();
});
describe("imagery view", () => {
describe("Clear data action for imagery", () => {
let applicableViews;
let imageryViewProvider;
let imageryView;
let componentView;
let clearDataPlugin;
let clearDataAction;
beforeEach(() => {
openmct.time.timeSystem('utc', {
start: START - (5 * ONE_MINUTE),
end: START + (5 * ONE_MINUTE)
});
applicableViews = openmct.objectViews.get(imageryObject, [imageryObject]);
imageryViewProvider = applicableViews.find(viewProvider => viewProvider.key === imageryKey);
imageryView = imageryViewProvider.view(imageryObject, [imageryObject]);
imageryView.show(child);
componentView = imageryView._getInstance().$children[0];
clearDataPlugin = new ClearDataPlugin(
['example.imagery'],
{indicator: true}
);
openmct.install(clearDataPlugin);
clearDataAction = openmct.actions.getAction('clear-data-action');
return Vue.nextTick();
});
it('clear data action is installed', () => {
expect(clearDataAction).toBeDefined();
});
it('on clearData action should clear data for object is selected', (done) => {
// force show the thumbnails
componentView.forceShowThumbnails = true;
Vue.nextTick(() => {
let clearDataResolve;
let telemetryRequestPromise = new Promise((resolve) => {
clearDataResolve = resolve;
});
expect(parent.querySelectorAll('.c-imagery__thumb').length).not.toBe(0);
openmct.objectViews.on('clearData', (_domainObject) => {
return Vue.nextTick(() => {
expect(parent.querySelectorAll('.c-imagery__thumb').length).toBe(0);
clearDataResolve();
});
});
clearDataAction.invoke(imageryObject);
telemetryRequestPromise.then(() => {
done();
});
});
});
});
describe("imagery view", () => {
let applicableViews;
let imageryViewProvider;
let imageryView;
beforeEach(() => {
openmct.time.timeSystem('utc', {
start: START - (5 * ONE_MINUTE),
end: START + (5 * ONE_MINUTE)
});
applicableViews = openmct.objectViews.get(imageryObject, [imageryObject]);
imageryViewProvider = applicableViews.find(viewProvider => viewProvider.key === imageryKey);
imageryView = imageryViewProvider.view(imageryObject, [imageryObject]);
imageryView.show(child);
imageryView._getInstance().$children[0].forceShowThumbnails = true;
return Vue.nextTick();
});
afterEach(() => {
isClearDataTriggered = false;
// openmct.time.stopClock();
// openmct.router.removeListener('change:hash', resolveFunction);
// imageryView.destroy();
});
it("on mount should show the the most recent image", (done) => {
it("on mount should show the the most recent image", () => {
//Looks like we need Vue.nextTick here so that computed properties settle down
Vue.nextTick(() => {
return Vue.nextTick(() => {
const imageInfo = getImageInfo(parent);
expect(imageInfo.url.indexOf(imageTelemetry[COUNT - 1].timeId)).not.toEqual(-1);
done();
});
});
@ -422,7 +462,7 @@ describe("The Imagery View Layouts", () => {
it("should show that an image is not new", (done) => {
Vue.nextTick(() => {
const target = imageTelemetry[2].url;
const target = imageTelemetry[4].url;
parent.querySelectorAll(`img[src='${target}']`)[0].click();
Vue.nextTick(() => {
@ -544,25 +584,6 @@ describe("The Imagery View Layouts", () => {
expect(imageSizeAfter.width).toBeLessThan(imageSizeBefore.width);
done();
});
it('clear data action is installed', () => {
expect(clearDataAction).toBeDefined();
});
it('on clearData action should clear data for object is selected', async (done) => {
// force show the thumbnails
imageryView._getInstance().$children[0].forceShowThumbnails = true;
await Vue.nextTick();
expect(parent.querySelectorAll('.c-imagery__thumb').length).not.toBe(0);
openmct.objectViews.on('clearData', async (_domainObject) => {
await Vue.nextTick();
expect(parent.querySelectorAll('.c-imagery__thumb').length).toBe(0);
done();
});
// stubbed telemetry data will return empty array when true
isClearDataTriggered = true;
clearDataAction.invoke(imageryObject);
});
});
describe("imagery time strip view", () => {

View File

@ -26,9 +26,10 @@ const config = {
maelstromTheme: './src/plugins/themes/maelstrom-theme.scss'
},
output: {
globalObject: "this",
globalObject: 'this',
filename: '[name].js',
library: '[name]',
path: path.resolve(__dirname, 'dist'),
library: 'openmct',
libraryTarget: 'umd',
publicPath: '',
hashFunction: 'xxhash64',

View File

@ -16,5 +16,5 @@ module.exports = merge(common, {
__OPENMCT_ROOT_RELATIVE__: '""'
})
],
devtool: 'source-map'
devtool: 'eval-source-map'
});