Compare commits
9 Commits
condition-
...
v2.0.4
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e2863595d7 | ||
|
|
7cad3c01ff | ||
|
|
ae1b7520bf | ||
|
|
2a165a4549 | ||
|
|
6abd395605 | ||
|
|
610f78b6fb | ||
|
|
663f42ad2e | ||
|
|
f80a3c13c1 | ||
|
|
a94ec344ea |
@@ -21,45 +21,163 @@
|
||||
*****************************************************************************/
|
||||
|
||||
/*
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding conditionSets.
|
||||
This test suite is dedicated to tests which verify the basic operations surrounding conditionSets. Note: this
|
||||
suite is sharing state between tests which is considered an anti-pattern. Implimenting in this way to
|
||||
demonstrate some playwright for test developers. This pattern should not be re-used in other CRUD suites.
|
||||
*/
|
||||
|
||||
const { test, expect } = require('@playwright/test');
|
||||
|
||||
test.describe('Condition Set Operations', () => {
|
||||
test('Create new button `condition set` creates new condition object', async ({ page }) => {
|
||||
//Go to baseURL
|
||||
await page.goto('/', { waitUntil: 'networkidle' });
|
||||
let conditionSetUrl;
|
||||
let getConditionSetIdentifierFromUrl;
|
||||
|
||||
//Click the Create button
|
||||
await page.click('button:has-text("Create")');
|
||||
test('Create new Condition Set object and store @localStorage', async ({ page, context }) => {
|
||||
//Go to baseURL
|
||||
await page.goto('/', { waitUntil: 'networkidle' });
|
||||
|
||||
// Click text=Condition Set
|
||||
await page.click('text=Condition Set');
|
||||
//Click the Create button
|
||||
await page.click('button:has-text("Create")');
|
||||
|
||||
// Click text=OK
|
||||
// Click text=Condition Set
|
||||
await page.click('text=Condition Set');
|
||||
|
||||
// Click text=OK
|
||||
await Promise.all([
|
||||
page.waitForNavigation(),
|
||||
page.click('text=OK')
|
||||
]);
|
||||
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||
//Save localStorage for future test execution
|
||||
await context.storageState({ path: './e2e/tests/recycled_storage.json' });
|
||||
|
||||
//Set object identifier from url
|
||||
conditionSetUrl = await page.url();
|
||||
console.log('conditionSetUrl ' + conditionSetUrl);
|
||||
|
||||
getConditionSetIdentifierFromUrl = await conditionSetUrl.split('/').pop().split('?')[0];
|
||||
console.log('getConditionSetIdentifierFromUrl ' + getConditionSetIdentifierFromUrl);
|
||||
|
||||
});
|
||||
|
||||
test.describe.serial('Condition Set CRUD Operations on @localStorage', () => {
|
||||
//Load localStorage for subsequent tests
|
||||
test.use({ storageState: './e2e/tests/recycled_storage.json' });
|
||||
|
||||
//Begin suite of tests again localStorage
|
||||
test('Condition set object properties persist in main view and inspector', async ({ page }) => {
|
||||
//Navigate to baseURL with injected localStorage
|
||||
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
||||
|
||||
//Assertions on loaded Condition Set in main view
|
||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||
|
||||
//Assertions on loaded Condition Set in Inspector
|
||||
await expect.soft(page.locator('_vue=item.name=Unnamed Condition Set')).toBeTruthy;
|
||||
|
||||
//Reload Page
|
||||
await Promise.all([
|
||||
page.waitForNavigation(/*{ url: 'http://localhost:8080/#/browse/mine/dab945d4-5a84-480e-8180-222b4aa730fa?tc.mode=fixed&tc.startBound=1639696164435&tc.endBound=1639697964435&tc.timeSystem=utc&view=conditionSet.view' }*/),
|
||||
page.click('text=OK')
|
||||
page.reload(),
|
||||
page.waitForLoadState('networkidle')
|
||||
]);
|
||||
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||
//Re-verify after reload
|
||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||
//Assertions on loaded Condition Set in Inspector
|
||||
await expect.soft(page.locator('_vue=item.name=Unnamed Condition Set')).toBeTruthy;
|
||||
|
||||
});
|
||||
test.fixme('condition set object properties exist', async ({ page }) => {
|
||||
//Go to object created in step one
|
||||
//Verify the Condition Set properties persist on Save
|
||||
//Verify the Condition Set properties persist on page.reload()
|
||||
});
|
||||
test.fixme('condition set object can be modified', async ({ page }) => {
|
||||
//Go to object created in step one
|
||||
test('condition set object can be modified on @localStorage', async ({ page }) => {
|
||||
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
||||
|
||||
//Assertions on loaded Condition Set in main view
|
||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||
|
||||
//Update the Condition Set properties
|
||||
//Verify the Condition Set properties persist on Save
|
||||
//Verify the Condition Set properties persist on page.reload()
|
||||
// Click Edit Button
|
||||
await page.locator('text=Conditions View Snapshot >> button').nth(3).click();
|
||||
|
||||
//Edit Condition Set Name from main view
|
||||
await page.locator('text=Unnamed Condition Set').first().fill('Renamed Condition Set');
|
||||
await page.locator('text=Renamed Condition Set').first().press('Enter');
|
||||
// Click Save Button
|
||||
await page.locator('text=Snapshot Save and Finish Editing Save and Continue Editing >> button').nth(1).click();
|
||||
// Click Save and Finish Editing Option
|
||||
await page.locator('text=Save and Finish Editing').click();
|
||||
|
||||
//Verify Main section reflects updated Name Property
|
||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Renamed Condition Set');
|
||||
|
||||
// Verify Inspector properties
|
||||
// Verify Inspector has updated Name property
|
||||
await expect.soft(page.locator('text=Renamed Condition Set').nth(1)).toBeTruthy();
|
||||
// Verify Inspector Details has updated Name property
|
||||
await expect.soft(page.locator('text=Renamed Condition Set').nth(2)).toBeTruthy();
|
||||
|
||||
// Verify Tree reflects updated Name proprety
|
||||
// Expand Tree
|
||||
await page.locator('text=Open MCT My Items >> span >> nth=3').click();
|
||||
// Verify Condition Set Object is renamed in Tree
|
||||
await expect(page.locator('a:has-text("Renamed Condition Set")')).toBeTruthy();
|
||||
// Verify Search Tree reflects renamed Name property
|
||||
await page.locator('input[type="search"]').fill('Renamed');
|
||||
await expect(page.locator('a:has-text("Renamed Condition Set")')).toBeTruthy();
|
||||
|
||||
//Reload Page
|
||||
await Promise.all([
|
||||
page.reload(),
|
||||
page.waitForLoadState('networkidle')
|
||||
]);
|
||||
|
||||
//Verify Main section reflects updated Name Property
|
||||
await expect.soft(page.locator('.l-browse-bar__object-name')).toContainText('Renamed Condition Set');
|
||||
|
||||
// Verify Inspector properties
|
||||
// Verify Inspector has updated Name property
|
||||
await expect.soft(page.locator('text=Renamed Condition Set').nth(1)).toBeTruthy();
|
||||
// Verify Inspector Details has updated Name property
|
||||
await expect.soft(page.locator('text=Renamed Condition Set').nth(2)).toBeTruthy();
|
||||
|
||||
// Verify Tree reflects updated Name proprety
|
||||
// Expand Tree
|
||||
await page.locator('text=Open MCT My Items >> span >> nth=3').click();
|
||||
// Verify Condition Set Object is renamed in Tree
|
||||
await expect(page.locator('a:has-text("Renamed Condition Set")')).toBeTruthy();
|
||||
// Verify Search Tree reflects renamed Name property
|
||||
await page.locator('input[type="search"]').fill('Renamed');
|
||||
await expect(page.locator('a:has-text("Renamed Condition Set")')).toBeTruthy();
|
||||
});
|
||||
test.fixme('condition set object can be deleted', async ({ page }) => {
|
||||
//Go to object created in step one
|
||||
//Verify that Condition Set object can be deleted
|
||||
//Verify the Condition Set object does not exist in Tree
|
||||
//Verify the Condition Set object does not exist with direct navigation to object's URL
|
||||
test('condition set object can be deleted by Search Tree Actions menu on @localStorage', async ({ page }) => {
|
||||
//Navigate to baseURL
|
||||
await page.goto('/', { waitUntil: 'networkidle' });
|
||||
|
||||
//Expect Unnamed Condition Set to be visible in Main View
|
||||
await expect(page.locator('a:has-text("Unnamed Condition Set Condition Set")')).toBeVisible();
|
||||
|
||||
// Search for Unnamed Condition Set
|
||||
await page.locator('input[type="search"]').fill('Unnamed Condition Set');
|
||||
// Right Click to Open Actions Menu
|
||||
await page.locator('a:has-text("Unnamed Condition Set")').click({
|
||||
button: 'right'
|
||||
});
|
||||
// Click Remove Action
|
||||
await page.locator('text=Remove').click();
|
||||
|
||||
await page.locator('text=OK').click();
|
||||
|
||||
//Expect Unnamed Condition Set to be removed in Main View
|
||||
await expect(page.locator('a:has-text("Unnamed Condition Set Condition Set")')).not.toBeVisible();
|
||||
|
||||
await page.locator('.c-search__clear-input').click();
|
||||
// Search for Unnamed Condition Set
|
||||
await page.locator('input[type="search"]').fill('Unnamed Condition Set');
|
||||
// Expect Unnamed Condition Set to be removed
|
||||
await expect(page.locator('a:has-text("Unnamed Condition Set")')).not.toBeVisible();
|
||||
|
||||
//Feature?
|
||||
//Domain Object is still available by direct URL after delete
|
||||
await page.goto(conditionSetUrl, { waitUntil: 'networkidle' });
|
||||
await expect(page.locator('.l-browse-bar__object-name')).toContainText('Unnamed Condition Set');
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
22
e2e/tests/recycled_storage.json
Normal file
22
e2e/tests/recycled_storage.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"cookies": [],
|
||||
"origins": [
|
||||
{
|
||||
"origin": "http://localhost:8080",
|
||||
"localStorage": [
|
||||
{
|
||||
"name": "tcHistory",
|
||||
"value": "{\"utc\":[{\"start\":1651513945533,\"end\":1651515745533}]}"
|
||||
},
|
||||
{
|
||||
"name": "mct",
|
||||
"value": "{\"mine\":{\"identifier\":{\"key\":\"mine\",\"namespace\":\"\"},\"name\":\"My Items\",\"type\":\"folder\",\"composition\":[{\"key\":\"c0f99e39-85e7-4ef7-99b1-ef52d4ed69b2\",\"namespace\":\"\"}],\"location\":\"ROOT\",\"persisted\":1651515746374,\"modified\":1651515746374},\"c0f99e39-85e7-4ef7-99b1-ef52d4ed69b2\":{\"name\":\"Unnamed Condition Set\",\"type\":\"conditionSet\",\"identifier\":{\"key\":\"c0f99e39-85e7-4ef7-99b1-ef52d4ed69b2\",\"namespace\":\"\"},\"configuration\":{\"conditionTestData\":[],\"conditionCollection\":[{\"isDefault\":true,\"id\":\"e35a066b-eb0e-4b05-a4c9-cc31dc202572\",\"configuration\":{\"name\":\"Default\",\"output\":\"Default\",\"trigger\":\"all\",\"criteria\":[]},\"summary\":\"Default condition\"}]},\"composition\":[],\"telemetry\":{},\"modified\":1651515746373,\"location\":\"mine\",\"persisted\":1651515746373}}"
|
||||
},
|
||||
{
|
||||
"name": "mct-tree-expanded",
|
||||
"value": "[]"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "openmct",
|
||||
"version": "2.0.3",
|
||||
"version": "2.0.4",
|
||||
"description": "The Open MCT core platform",
|
||||
"devDependencies": {
|
||||
"@babel/eslint-parser": "7.16.3",
|
||||
|
||||
@@ -185,8 +185,8 @@ export class TelemetryCollection extends EventEmitter {
|
||||
|
||||
for (let datum of data) {
|
||||
parsedValue = this.parseTime(datum);
|
||||
beforeStartOfBounds = parsedValue <= this.lastBounds.start;
|
||||
afterEndOfBounds = parsedValue >= this.lastBounds.end;
|
||||
beforeStartOfBounds = parsedValue < this.lastBounds.start;
|
||||
afterEndOfBounds = parsedValue > this.lastBounds.end;
|
||||
|
||||
if (!afterEndOfBounds && !beforeStartOfBounds) {
|
||||
let isDuplicate = false;
|
||||
|
||||
@@ -148,6 +148,8 @@ export default {
|
||||
this.openmct.time.off('timeSystem', this.updateTimeSystem);
|
||||
this.telemetryCollection.off('add', this.setLatestValues);
|
||||
this.telemetryCollection.off('clear', this.resetValues);
|
||||
|
||||
this.telemetryCollection.destroy();
|
||||
},
|
||||
methods: {
|
||||
updateView() {
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
:href="url"
|
||||
>
|
||||
<div class="c-condition-widget__label">
|
||||
{{ internalDomainObject.conditionalLabel || internalDomainObject.label }}
|
||||
{{ label }}
|
||||
</div>
|
||||
</component>
|
||||
</template>
|
||||
@@ -39,28 +39,112 @@ export default {
|
||||
inject: ['openmct', 'domainObject'],
|
||||
data: function () {
|
||||
return {
|
||||
internalDomainObject: this.domainObject
|
||||
conditionalLabel: '',
|
||||
conditionSetIdentifier: null,
|
||||
domainObjectLabel: '',
|
||||
url: null,
|
||||
urlDefined: false,
|
||||
useConditionSetOutputAsLabel: false
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
urlDefined() {
|
||||
return this.internalDomainObject.url && this.internalDomainObject.url.length > 0;
|
||||
},
|
||||
url() {
|
||||
return this.urlDefined ? sanitizeUrl(this.internalDomainObject.url) : null;
|
||||
label() {
|
||||
return this.useConditionSetOutputAsLabel
|
||||
? this.conditionalLabel
|
||||
: this.domainObjectLabel
|
||||
;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
conditionSetIdentifier: {
|
||||
handler(newValue, oldValue) {
|
||||
if (!oldValue || !newValue || !this.openmct.objects.areIdsEqual(newValue, oldValue)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.listenToConditionSetChanges();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.unlisten = this.openmct.objects.observe(this.internalDomainObject, '*', this.updateInternalDomainObject);
|
||||
this.unlisten = this.openmct.objects.observe(this.domainObject, '*', this.updateDomainObject);
|
||||
|
||||
if (this.domainObject) {
|
||||
this.updateDomainObject(this.domainObject);
|
||||
this.listenToConditionSetChanges();
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.conditionSetIdentifier = null;
|
||||
|
||||
if (this.unlisten) {
|
||||
this.unlisten();
|
||||
}
|
||||
|
||||
this.stopListeningToConditionSetChanges();
|
||||
},
|
||||
methods: {
|
||||
updateInternalDomainObject(domainObject) {
|
||||
this.internalDomainObject = domainObject;
|
||||
async listenToConditionSetChanges() {
|
||||
if (!this.conditionSetIdentifier) {
|
||||
return;
|
||||
}
|
||||
|
||||
const conditionSetDomainObject = await this.openmct.objects.get(this.conditionSetIdentifier);
|
||||
this.stopListeningToConditionSetChanges();
|
||||
|
||||
if (!conditionSetDomainObject) {
|
||||
this.openmct.notifications.alert('Unable to find condition set');
|
||||
}
|
||||
|
||||
this.telemetryCollection = this.openmct.telemetry.requestCollection(conditionSetDomainObject, {
|
||||
size: 1,
|
||||
strategy: 'latest'
|
||||
});
|
||||
|
||||
this.telemetryCollection.on('add', this.updateConditionLabel, this);
|
||||
this.telemetryCollection.load();
|
||||
},
|
||||
stopListeningToConditionSetChanges() {
|
||||
if (this.telemetryCollection) {
|
||||
this.telemetryCollection.off('add', this.updateConditionLabel, this);
|
||||
this.telemetryCollection.destroy();
|
||||
this.telemetryCollection = null;
|
||||
}
|
||||
},
|
||||
updateConditionLabel([latestDatum]) {
|
||||
if (!this.conditionSetIdentifier) {
|
||||
this.stopListeningToConditionSetChanges();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.conditionalLabel = latestDatum.output || '';
|
||||
},
|
||||
updateDomainObject(domainObject) {
|
||||
if (this.domainObjectLabel !== domainObject.label) {
|
||||
this.domainObjectLabel = domainObject.label;
|
||||
}
|
||||
|
||||
const urlDefined = domainObject.url && domainObject.url.length > 0;
|
||||
if (this.urlDefined !== urlDefined) {
|
||||
this.urlDefined = urlDefined;
|
||||
}
|
||||
|
||||
const url = this.urlDefined ? sanitizeUrl(domainObject.url) : null;
|
||||
if (this.url !== url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
const conditionSetIdentifier = domainObject.configuration.objectStyles.conditionSetIdentifier;
|
||||
if (this.conditionSetIdentifier !== conditionSetIdentifier) {
|
||||
this.conditionSetIdentifier = conditionSetIdentifier;
|
||||
}
|
||||
|
||||
const useConditionSetOutputAsLabel = this.conditionSetIdentifier && domainObject.configuration.useConditionSetOutputAsLabel;
|
||||
if (this.useConditionSetOutputAsLabel !== useConditionSetOutputAsLabel) {
|
||||
this.useConditionSetOutputAsLabel = useConditionSetOutputAsLabel;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -235,6 +235,8 @@ export default {
|
||||
this.telemetryCollection.off('add', this.setLatestValues);
|
||||
this.telemetryCollection.off('clear', this.refreshData);
|
||||
|
||||
this.telemetryCollection.destroy();
|
||||
|
||||
if (this.mutablePromise) {
|
||||
this.mutablePromise.then(() => {
|
||||
this.openmct.objects.destroyMutable(this.domainObject);
|
||||
|
||||
@@ -60,7 +60,7 @@
|
||||
>
|
||||
<div class="c-image-controls__input icon-brightness">
|
||||
<input
|
||||
v-model="filters.contrast"
|
||||
v-model="filters.brightness"
|
||||
type="range"
|
||||
min="0"
|
||||
max="500"
|
||||
@@ -69,7 +69,7 @@
|
||||
</div>
|
||||
<div class="c-image-controls__input icon-contrast">
|
||||
<input
|
||||
v-model="filters.brightness"
|
||||
v-model="filters.contrast"
|
||||
type="range"
|
||||
min="0"
|
||||
max="500"
|
||||
@@ -174,7 +174,7 @@ export default {
|
||||
this.$emit('filtersUpdated', this.filters);
|
||||
},
|
||||
handleResetFilters() {
|
||||
this.filters = DEFAULT_FILTER_VALUES;
|
||||
this.filters = {...DEFAULT_FILTER_VALUES};
|
||||
this.notifyFiltersChanged();
|
||||
},
|
||||
limitZoomRange(factor) {
|
||||
|
||||
@@ -97,8 +97,7 @@
|
||||
'transform': `scale(${zoomFactor}) translate(${imageTranslateX}px, ${imageTranslateY}px)`,
|
||||
'transition': `${!pan && animateZoom ? 'transform 250ms ease-in' : 'initial'}`,
|
||||
'width': `${sizedImageWidth}px`,
|
||||
'height': `${sizedImageHeight}px`,
|
||||
|
||||
'height': `${sizedImageHeight}px`
|
||||
}"
|
||||
></div>
|
||||
<Compass
|
||||
@@ -382,6 +381,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);
|
||||
@@ -834,8 +836,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() {
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
height: 100%; //fallback value
|
||||
}
|
||||
&__image {
|
||||
height: 100%;
|
||||
|
||||
@@ -46,7 +46,6 @@ export default {
|
||||
|
||||
// kickoff
|
||||
this.subscribe();
|
||||
this.requestHistory();
|
||||
},
|
||||
beforeDestroy() {
|
||||
if (this.unsubscribe) {
|
||||
@@ -71,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) {
|
||||
@@ -133,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
|
||||
@@ -183,27 +172,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 };
|
||||
|
||||
@@ -84,7 +84,6 @@ describe("The Imagery View Layouts", () => {
|
||||
let telemetryPromise;
|
||||
let telemetryPromiseResolve;
|
||||
let cleanupFirst;
|
||||
let isClearDataTriggered;
|
||||
|
||||
let openmct;
|
||||
let parent;
|
||||
@@ -193,20 +192,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;
|
||||
@@ -325,44 +316,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();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -398,7 +438,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(() => {
|
||||
@@ -520,25 +560,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", () => {
|
||||
|
||||
@@ -192,7 +192,6 @@ export default {
|
||||
|
||||
if (this.axisType === 'yAxis' && this.axis.get('logMode')) {
|
||||
return getLogTicks(range.min, range.max, number, 4);
|
||||
// return getLogTicks2(range.min, range.max, number);
|
||||
} else {
|
||||
return ticks(range.min, range.max, number);
|
||||
}
|
||||
@@ -204,7 +203,6 @@ export default {
|
||||
|
||||
updateTicks(forceRegeneration = false) {
|
||||
const range = this.axis.get('displayRange');
|
||||
const logMode = this.axis.get('logMode');
|
||||
|
||||
if (!range) {
|
||||
delete this.min;
|
||||
@@ -233,7 +231,7 @@ export default {
|
||||
step: newTicks[1] - newTicks[0]
|
||||
};
|
||||
|
||||
newTicks = getFormattedTicks(newTicks, format, logMode);
|
||||
newTicks = getFormattedTicks(newTicks, format);
|
||||
|
||||
this.ticks = newTicks;
|
||||
this.shouldCheckWidth = true;
|
||||
|
||||
@@ -132,12 +132,6 @@ export default {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.object && this.object.type === 'conditionWidget' && keys.includes('output')) {
|
||||
this.openmct.objects.mutate(this.object, 'conditionalLabel', styleObj.output);
|
||||
} else {
|
||||
this.openmct.objects.mutate(this.object, 'conditionalLabel', '');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,11 +78,6 @@ export function getLogTicks(start, stop, mainTickCount = 8, secondaryTickCount =
|
||||
return result;
|
||||
}
|
||||
|
||||
export function getLogTicks2(start, stop, count = 8) {
|
||||
return ticks(antisymlog(start, 10), antisymlog(stop, 10), count)
|
||||
.map(n => symlog(n, 10));
|
||||
}
|
||||
|
||||
/**
|
||||
* Linear tick generation from d3-array.
|
||||
*/
|
||||
@@ -131,17 +126,12 @@ export function commonSuffix(a, b) {
|
||||
return a.slice(a.length - breakpoint);
|
||||
}
|
||||
|
||||
export function getFormattedTicks(newTicks, format, formatFloat) {
|
||||
export function getFormattedTicks(newTicks, format) {
|
||||
newTicks = newTicks
|
||||
.map(function (tickValue) {
|
||||
let formattedValue = format(tickValue);
|
||||
if (formatFloat === true && typeof formattedValue === 'number' && !Number.isInteger(formattedValue)) {
|
||||
formattedValue = parseFloat(formattedValue).toFixed(2);
|
||||
}
|
||||
|
||||
return {
|
||||
value: tickValue,
|
||||
text: formattedValue
|
||||
text: format(tickValue)
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
@@ -213,12 +213,6 @@ export default {
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (this.domainObject && this.domainObject.type === 'conditionWidget' && keys.includes('output')) {
|
||||
this.openmct.objects.mutate(this.domainObject, 'conditionalLabel', styleObj.output);
|
||||
} else {
|
||||
this.openmct.objects.mutate(this.domainObject, 'conditionalLabel', '');
|
||||
}
|
||||
},
|
||||
updateView(immediatelySelect) {
|
||||
this.clear();
|
||||
@@ -450,4 +444,3 @@ export default {
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -16,5 +16,5 @@ module.exports = merge(common, {
|
||||
__OPENMCT_ROOT_RELATIVE__: '""'
|
||||
})
|
||||
],
|
||||
devtool: 'source-map'
|
||||
devtool: 'eval-source-map'
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user