Differentiate aggregate telenmetry in LAD tables (#6406)

* allow lad tables rows to be selected

* rows now clickable and previewable

* trying to add type column

* aggregate and telemetry

* if aggregate, use blank for value and timestamps

* remove extraneous path lookup

* cleanup css

* add tests

* allow hiding of type column

* adjust tests to include type column
This commit is contained in:
Scott Bell 2023-03-15 05:31:15 +04:00 committed by GitHub
parent 600890c4a6
commit 1f30706d27
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 120 additions and 15 deletions

View File

@ -53,16 +53,20 @@ test.describe('Testing LAD table configuration', () => {
// make sure headers are visible initially // make sure headers are visible initially
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Type' })).toBeVisible();
// hide timestamp column // hide timestamp column
await page.getByLabel('Timestamp').uncheck(); await page.getByLabel('Timestamp').uncheck();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Type' })).toBeVisible();
// hide units column // hide units & type column
await page.getByLabel('Units').uncheck(); await page.getByLabel('Units').uncheck();
await page.getByLabel('Type').uncheck();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Type' })).toBeHidden();
// save and reload and verify they columns are still hidden // save and reload and verify they columns are still hidden
await page.locator('button[title="Save"]').click(); await page.locator('button[title="Save"]').click();
@ -70,6 +74,7 @@ test.describe('Testing LAD table configuration', () => {
await page.reload(); await page.reload();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Type' })).toBeHidden();
// Edit LAD table // Edit LAD table
await page.locator('[title="Edit"]').click(); await page.locator('[title="Edit"]').click();
@ -78,6 +83,7 @@ test.describe('Testing LAD table configuration', () => {
// show timestamp column // show timestamp column
await page.getByLabel('Timestamp').check(); await page.getByLabel('Timestamp').check();
await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Type' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible();
// save and reload and make sure only timestamp is still visible // save and reload and make sure only timestamp is still visible
@ -85,23 +91,27 @@ test.describe('Testing LAD table configuration', () => {
await page.locator('text=Save and Finish Editing').click(); await page.locator('text=Save and Finish Editing').click();
await page.reload(); await page.reload();
await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden(); await expect(page.getByRole('cell', { name: 'Units' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Type' })).toBeHidden();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible();
// Edit LAD table // Edit LAD table
await page.locator('[title="Edit"]').click(); await page.locator('[title="Edit"]').click();
await page.getByRole('tab', { name: 'LAD Table Configuration' }).getByText('LAD Table Configuration').click(); await page.getByRole('tab', { name: 'LAD Table Configuration' }).getByText('LAD Table Configuration').click();
// show units column // show units and type columns
await page.getByLabel('Units').check(); await page.getByLabel('Units').check();
await page.getByLabel('Type').check();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Type' })).toBeVisible();
// save and reload and make sure both columns are still visible // save and reload and make sure all columns are still visible
await page.locator('button[title="Save"]').click(); await page.locator('button[title="Save"]').click();
await page.locator('text=Save and Finish Editing').click(); await page.locator('text=Save and Finish Editing').click();
await page.reload(); await page.reload();
await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Timestamp' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible(); await expect(page.getByRole('cell', { name: 'Units' })).toBeVisible();
await expect(page.getByRole('cell', { name: 'Type' })).toBeVisible();
}); });
}); });

View File

@ -22,7 +22,8 @@
<template> <template>
<tr <tr
class="js-lad-table__body__row" class="js-lad-table__body__row c-table__selectable-row"
@click="clickedRow"
@contextmenu.prevent="showContextMenu" @contextmenu.prevent="showContextMenu"
> >
<td class="js-first-data">{{ domainObject.name }}</td> <td class="js-first-data">{{ domainObject.name }}</td>
@ -40,6 +41,10 @@
> >
{{ unit }} {{ unit }}
</td> </td>
<td
v-if="showType"
class="js-type-data"
>{{ typeLabel }}</td>
</tr> </tr>
</template> </template>
@ -52,6 +57,9 @@ const CONTEXT_MENU_ACTIONS = [
]; ];
const BLANK_VALUE = '---'; const BLANK_VALUE = '---';
import identifierToString from '/src/tools/url';
import PreviewAction from "@/ui/preview/PreviewAction.js";
export default { export default {
inject: ['openmct', 'currentView'], inject: ['openmct', 'currentView'],
props: { props: {
@ -83,17 +91,28 @@ export default {
datum: undefined, datum: undefined,
timestamp: undefined, timestamp: undefined,
timestampKey: undefined, timestampKey: undefined,
composition: [],
unit: '' unit: ''
}; };
}, },
computed: { computed: {
value() { value() {
if (!this.datum) { if (!this.datum || this.isAggregate) {
return BLANK_VALUE; return BLANK_VALUE;
} }
return this.formats[this.valueKey].format(this.datum); return this.formats[this.valueKey].format(this.datum);
}, },
typeLabel() {
if (this.isAggregate) {
return 'Aggregate';
}
return "Telemetry";
},
isAggregate() {
return this.composition && this.composition.length > 0;
},
valueClasses() { valueClasses() {
let classes = []; let classes = [];
@ -113,7 +132,7 @@ export default {
}, },
formattedTimestamp() { formattedTimestamp() {
if (!this.timestamp) { if (!this.timestamp || this.isAggregate) {
return BLANK_VALUE; return BLANK_VALUE;
} }
@ -131,12 +150,19 @@ export default {
}, },
showTimestamp() { showTimestamp() {
return !this.configuration?.hiddenColumns?.timestamp; return !this.configuration?.hiddenColumns?.timestamp;
},
showType() {
return !this.configuration?.hiddenColumns?.type;
} }
}, },
mounted() { async mounted() {
this.metadata = this.openmct.telemetry.getMetadata(this.domainObject); this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
this.formats = this.openmct.telemetry.getFormatMap(this.metadata); this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier); this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
const compositionCollection = this.openmct.composition.get(this.domainObject);
if (compositionCollection) {
this.composition = await compositionCollection.load();
}
this.timeContext = this.openmct.time.getContextForView(this.objectPath); this.timeContext = this.openmct.time.getContextForView(this.objectPath);
@ -170,11 +196,15 @@ export default {
if (this.hasUnits) { if (this.hasUnits) {
this.setUnit(); this.setUnit();
} }
this.previewAction = new PreviewAction(this.openmct);
this.previewAction.on('isVisible', this.togglePreviewState);
}, },
destroyed() { destroyed() {
this.openmct.time.off('timeSystem', this.updateTimeSystem); this.openmct.time.off('timeSystem', this.updateTimeSystem);
this.telemetryCollection.off('add', this.setLatestValues); this.telemetryCollection.off('add', this.setLatestValues);
this.telemetryCollection.off('clear', this.resetValues); this.telemetryCollection.off('clear', this.resetValues);
this.previewAction.off('isVisible', this.togglePreviewState);
this.telemetryCollection.destroy(); this.telemetryCollection.destroy();
}, },
@ -189,6 +219,20 @@ export default {
}); });
} }
}, },
clickedRow(event) {
if (this.openmct.editor.isEditing()) {
event.preventDefault();
this.preview(this.objectPath);
} else {
const resultUrl = identifierToString(this.openmct, this.objectPath);
this.openmct.router.navigate(resultUrl);
}
},
preview(objectPath) {
if (this.previewAction.appliesTo(objectPath)) {
this.previewAction.invoke(objectPath);
}
},
setLatestValues(data) { setLatestValues(data) {
this.latestDatum = data[data.length - 1]; this.latestDatum = data[data.length - 1];
this.updateView(); this.updateView();

View File

@ -32,6 +32,7 @@
<th v-if="showTimestamp">Timestamp</th> <th v-if="showTimestamp">Timestamp</th>
<th>Value</th> <th>Value</th>
<th v-if="hasUnits">Units</th> <th v-if="hasUnits">Units</th>
<th v-if="showType">Type</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
@ -93,6 +94,9 @@ export default {
showTimestamp() { showTimestamp() {
return !this.configuration?.hiddenColumns?.timestamp; return !this.configuration?.hiddenColumns?.timestamp;
}, },
showType() {
return !this.configuration?.hiddenColumns?.type;
},
staleClass() { staleClass() {
if (this.staleObjects.length !== 0) { if (this.staleObjects.length !== 0) {
return 'is-stale'; return 'is-stale';

View File

@ -74,7 +74,8 @@ export default {
return { return {
headers: { headers: {
timestamp: 'Timestamp', timestamp: 'Timestamp',
units: 'Units' units: 'Units',
type: 'Type'
}, },
ladTableConfiguration, ladTableConfiguration,
isEditing: this.openmct.editor.isEditing(), isEditing: this.openmct.editor.isEditing(),

View File

@ -31,6 +31,7 @@
<th>Name</th> <th>Name</th>
<th v-if="showTimestamp">Timestamp</th> <th v-if="showTimestamp">Timestamp</th>
<th>Value</th> <th>Value</th>
<th v-if="showType">Type</th>
<th v-if="hasUnits">Units</th> <th v-if="hasUnits">Units</th>
</tr> </tr>
</thead> </thead>
@ -112,6 +113,9 @@ export default {
showTimestamp() { showTimestamp() {
return !this.configuration?.hiddenColumns?.timestamp; return !this.configuration?.hiddenColumns?.timestamp;
}, },
showType() {
return !this.configuration?.hiddenColumns?.type;
},
staleClass() { staleClass() {
if (this.staleObjects.length !== 0) { if (this.staleObjects.length !== 0) {
return 'is-stale'; return 'is-stale';

View File

@ -152,23 +152,42 @@ describe("The LAD Table", () => {
} }
}).telemetry; }).telemetry;
// add another telemetry object as composition in lad table to test multi rows const aggregateTelemetryObj = getMockObjects({
mockObj.ladTable.composition.push(anotherTelemetryObj.identifier); objectKeyStrings: ['telemetry'],
overwrite: {
telemetry: {
name: "Aggregate Telemetry Object",
identifier: {
namespace: "",
key: "aggregate-telemetry-object"
}
}
}
}).telemetry;
// add another aggregate telemetry object as composition in lad table to test multi rows
aggregateTelemetryObj.composition = [anotherTelemetryObj.identifier];
mockObj.ladTable.composition.push(aggregateTelemetryObj.identifier);
beforeEach(async () => { beforeEach(async () => {
let telemetryRequestResolve; let telemetryRequestResolve;
let telemetryObjectResolve; let telemetryObjectResolve;
let anotherTelemetryObjectResolve; let anotherTelemetryObjectResolve;
let telemetryRequestPromise = new Promise((resolve) => { let aggregateTelemetryObjectResolve;
const telemetryRequestPromise = new Promise((resolve) => {
telemetryRequestResolve = resolve; telemetryRequestResolve = resolve;
}); });
let telemetryObjectPromise = new Promise((resolve) => { const telemetryObjectPromise = new Promise((resolve) => {
telemetryObjectResolve = resolve; telemetryObjectResolve = resolve;
}); });
let anotherTelemetryObjectPromise = new Promise((resolve) => { const anotherTelemetryObjectPromise = new Promise((resolve) => {
anotherTelemetryObjectResolve = resolve; anotherTelemetryObjectResolve = resolve;
}); });
const aggregateTelemetryObjectPromise = new Promise((resolve) => {
aggregateTelemetryObjectResolve = resolve;
});
spyOnBuiltins(['requestAnimationFrame']); spyOnBuiltins(['requestAnimationFrame']);
window.requestAnimationFrame.and.callFake((callBack) => { window.requestAnimationFrame.and.callFake((callBack) => {
callBack(); callBack();
@ -185,10 +204,14 @@ describe("The LAD Table", () => {
telemetryObjectResolve(mockObj.telemetry); telemetryObjectResolve(mockObj.telemetry);
return telemetryObjectPromise; return telemetryObjectPromise;
} else { } else if (obj.key === 'another-telemetry-object') {
anotherTelemetryObjectResolve(anotherTelemetryObj); anotherTelemetryObjectResolve(anotherTelemetryObj);
return anotherTelemetryObjectPromise; return anotherTelemetryObjectPromise;
} else {
aggregateTelemetryObjectResolve(aggregateTelemetryObj);
return aggregateTelemetryObjectPromise;
} }
}); });
@ -202,7 +225,7 @@ describe("The LAD Table", () => {
ladTableView = ladTableViewProvider.view(mockObj.ladTable, [mockObj.ladTable]); ladTableView = ladTableViewProvider.view(mockObj.ladTable, [mockObj.ladTable]);
ladTableView.show(child, true); ladTableView.show(child, true);
await Promise.all([telemetryRequestPromise, telemetryObjectPromise, anotherTelemetryObjectPromise]); await Promise.all([telemetryRequestPromise, telemetryObjectPromise, anotherTelemetryObjectPromise, aggregateTelemetryObjectResolve]);
await Vue.nextTick(); await Vue.nextTick();
}); });
@ -217,6 +240,16 @@ describe("The LAD Table", () => {
await Vue.nextTick(); await Vue.nextTick();
const latestDate = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText; const latestDate = parent.querySelector(TABLE_BODY_FIRST_ROW_SECOND_DATA).innerText;
expect(latestDate).toBe(expectedDate); expect(latestDate).toBe(expectedDate);
const dataType = parent.querySelector(TABLE_BODY_ROWS).querySelector('.js-type-data').innerText;
expect(dataType).toBe('Telemetry');
});
it("should show aggregate telemetry type with blank data", async () => {
await Vue.nextTick();
const lastestData = parent.querySelectorAll(TABLE_BODY_ROWS)[1].querySelectorAll('td')[2].innerText;
expect(lastestData).toBe('---');
const dataType = parent.querySelectorAll(TABLE_BODY_ROWS)[1].querySelector('.js-type-data').innerText;
expect(dataType).toBe('Aggregate');
}); });
it("should show the name provided for the the telemetry producing object", () => { it("should show the name provided for the the telemetry producing object", () => {

View File

@ -150,6 +150,15 @@ div.c-table {
tr:not(.c-table__group-header) + tr:not(.c-table__group-header) { tr:not(.c-table__group-header) + tr:not(.c-table__group-header) {
border-top: 1px solid $colorTabBorder; border-top: 1px solid $colorTabBorder;
} }
transition: $transOut;
}
&__selectable-row {cursor: pointer;
&:hover {
background: $colorListItemBgHov;
filter: $filterHov;
transition: $transIn;
}
} }
&__group-header { &__group-header {