mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 19:12:02 +00:00
Compare commits
3 Commits
telemetry-
...
tables-per
Author | SHA1 | Date | |
---|---|---|---|
f1d7c7843c | |||
d35c656ce3 | |||
627b59e91d |
@ -78,7 +78,7 @@
|
|||||||
<!-- Content table -->
|
<!-- Content table -->
|
||||||
<div class="c-table__body-w c-telemetry-table__body-w js-telemetry-table__body-w" @scroll="scroll" :style="{ 'max-width': widthWithScroll}">
|
<div class="c-table__body-w c-telemetry-table__body-w js-telemetry-table__body-w" @scroll="scroll" :style="{ 'max-width': widthWithScroll}">
|
||||||
<div class="c-telemetry-table__scroll-forcer" :style="{ width: totalWidth + 'px' }"></div>
|
<div class="c-telemetry-table__scroll-forcer" :style="{ width: totalWidth + 'px' }"></div>
|
||||||
<table class="c-table__body c-telemetry-table__body"
|
<table class="c-table__body c-telemetry-table__body js-telemetry-table__content"
|
||||||
:style="{ height: totalHeight + 'px'}">
|
:style="{ height: totalHeight + 'px'}">
|
||||||
<tbody>
|
<tbody>
|
||||||
<telemetry-table-row v-for="(row, rowIndex) in visibleRows"
|
<telemetry-table-row v-for="(row, rowIndex) in visibleRows"
|
||||||
@ -284,7 +284,7 @@ import _ from 'lodash';
|
|||||||
const VISIBLE_ROW_COUNT = 100;
|
const VISIBLE_ROW_COUNT = 100;
|
||||||
const ROW_HEIGHT = 17;
|
const ROW_HEIGHT = 17;
|
||||||
const RESIZE_POLL_INTERVAL = 200;
|
const RESIZE_POLL_INTERVAL = 200;
|
||||||
const AUTO_SCROLL_TRIGGER_HEIGHT = 20;
|
const AUTO_SCROLL_TRIGGER_HEIGHT = 100;
|
||||||
const RESIZE_HOT_ZONE = 10;
|
const RESIZE_HOT_ZONE = 10;
|
||||||
const MOVE_TRIGGER_WAIT = 500;
|
const MOVE_TRIGGER_WAIT = 500;
|
||||||
const VERTICAL_SCROLL_WIDTH = 30;
|
const VERTICAL_SCROLL_WIDTH = 30;
|
||||||
@ -364,42 +364,48 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
updateVisibleRows() {
|
updateVisibleRows() {
|
||||||
|
if (!this.updatingView) {
|
||||||
|
this.updatingView = true;
|
||||||
|
requestAnimationFrame(()=> {
|
||||||
|
|
||||||
let start = 0;
|
let start = 0;
|
||||||
let end = VISIBLE_ROW_COUNT;
|
let end = VISIBLE_ROW_COUNT;
|
||||||
let filteredRows = this.table.filteredRows.getRows();
|
let filteredRows = this.table.filteredRows.getRows();
|
||||||
let filteredRowsLength = filteredRows.length;
|
let filteredRowsLength = filteredRows.length;
|
||||||
|
|
||||||
this.totalHeight = this.rowHeight * filteredRowsLength - 1;
|
if (filteredRowsLength < VISIBLE_ROW_COUNT) {
|
||||||
|
end = filteredRowsLength;
|
||||||
|
} else {
|
||||||
|
let firstVisible = this.calculateFirstVisibleRow();
|
||||||
|
let lastVisible = this.calculateLastVisibleRow();
|
||||||
|
let totalVisible = lastVisible - firstVisible;
|
||||||
|
|
||||||
if (filteredRowsLength < VISIBLE_ROW_COUNT) {
|
let numberOffscreen = VISIBLE_ROW_COUNT - totalVisible;
|
||||||
end = filteredRowsLength;
|
start = firstVisible - Math.floor(numberOffscreen / 2);
|
||||||
} else {
|
end = lastVisible + Math.ceil(numberOffscreen / 2);
|
||||||
let firstVisible = this.calculateFirstVisibleRow();
|
|
||||||
let lastVisible = this.calculateLastVisibleRow();
|
|
||||||
let totalVisible = lastVisible - firstVisible;
|
|
||||||
|
|
||||||
let numberOffscreen = VISIBLE_ROW_COUNT - totalVisible;
|
if (start < 0) {
|
||||||
start = firstVisible - Math.floor(numberOffscreen / 2);
|
start = 0;
|
||||||
end = lastVisible + Math.ceil(numberOffscreen / 2);
|
end = Math.min(VISIBLE_ROW_COUNT, filteredRowsLength);
|
||||||
|
} else if (end >= filteredRowsLength) {
|
||||||
|
end = filteredRowsLength;
|
||||||
|
start = end - VISIBLE_ROW_COUNT + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.rowOffset = start;
|
||||||
|
this.visibleRows = filteredRows.slice(start, end);
|
||||||
|
|
||||||
if (start < 0) {
|
this.updatingView = false;
|
||||||
start = 0;
|
});
|
||||||
end = Math.min(VISIBLE_ROW_COUNT, filteredRowsLength);
|
|
||||||
} else if (end >= filteredRowsLength) {
|
|
||||||
end = filteredRowsLength;
|
|
||||||
start = end - VISIBLE_ROW_COUNT + 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.rowOffset = start;
|
|
||||||
this.visibleRows = filteredRows.slice(start, end);
|
|
||||||
},
|
},
|
||||||
calculateFirstVisibleRow() {
|
calculateFirstVisibleRow() {
|
||||||
return Math.floor(this.scrollable.scrollTop / this.rowHeight);
|
let scrollTop = this.scrollable.scrollTop;
|
||||||
|
return Math.floor(scrollTop / this.rowHeight);
|
||||||
},
|
},
|
||||||
calculateLastVisibleRow() {
|
calculateLastVisibleRow() {
|
||||||
let bottomScroll = this.scrollable.scrollTop + this.scrollable.offsetHeight;
|
let scrollBottom = this.scrollable.scrollTop + this.scrollable.offsetHeight;
|
||||||
return Math.floor(bottomScroll / this.rowHeight);
|
return Math.ceil(scrollBottom / this.rowHeight);
|
||||||
},
|
},
|
||||||
updateHeaders() {
|
updateHeaders() {
|
||||||
this.headers = this.table.configuration.getVisibleHeaders();
|
this.headers = this.table.configuration.getVisibleHeaders();
|
||||||
@ -443,29 +449,23 @@ export default {
|
|||||||
}
|
}
|
||||||
this.table.sortBy(this.sortOptions);
|
this.table.sortBy(this.sortOptions);
|
||||||
},
|
},
|
||||||
scroll() {
|
scroll () {
|
||||||
if (!this.processingScroll) {
|
this.updateVisibleRows();
|
||||||
this.processingScroll = true;
|
this.synchronizeScrollX();
|
||||||
requestAnimationFrame(()=> {
|
|
||||||
this.updateVisibleRows();
|
|
||||||
this.synchronizeScrollX();
|
|
||||||
|
|
||||||
if (this.shouldSnapToBottom()) {
|
if (this.shouldSnapToBottom()) {
|
||||||
this.autoScroll = true;
|
this.autoScroll = true;
|
||||||
} else {
|
} else {
|
||||||
// If user scrolls away from bottom, disable auto-scroll.
|
// If user scrolls away from bottom, disable auto-scroll.
|
||||||
// Auto-scroll will be re-enabled if user scrolls to bottom again.
|
// Auto-scroll will be re-enabled if user scrolls to bottom again.
|
||||||
this.autoScroll = false;
|
this.autoScroll = false;
|
||||||
}
|
|
||||||
this.processingScroll = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
shouldSnapToBottom() {
|
shouldSnapToBottom() {
|
||||||
return this.scrollable.scrollTop >= (this.scrollable.scrollHeight - this.scrollable.offsetHeight - AUTO_SCROLL_TRIGGER_HEIGHT);
|
return this.scrollable.scrollTop >= (this.scrollable.scrollHeight - this.scrollable.offsetHeight - AUTO_SCROLL_TRIGGER_HEIGHT);
|
||||||
},
|
},
|
||||||
scrollToBottom() {
|
scrollToBottom() {
|
||||||
this.scrollable.scrollTop = this.scrollable.scrollHeight;
|
this.scrollable.scrollTop = Number.MAX_SAFE_INTEGER;
|
||||||
},
|
},
|
||||||
synchronizeScrollX() {
|
synchronizeScrollX() {
|
||||||
this.headersHolderEl.scrollLeft = this.scrollable.scrollLeft;
|
this.headersHolderEl.scrollLeft = this.scrollable.scrollLeft;
|
||||||
@ -477,37 +477,40 @@ export default {
|
|||||||
this.filters[columnKey] = '';
|
this.filters[columnKey] = '';
|
||||||
this.table.filteredRows.setColumnFilter(columnKey, '');
|
this.table.filteredRows.setColumnFilter(columnKey, '');
|
||||||
},
|
},
|
||||||
rowsAdded(rows) {
|
rowsAdded (rows) {
|
||||||
|
this.setHeight();
|
||||||
|
|
||||||
let sizingRow;
|
let sizingRow;
|
||||||
if (Array.isArray(rows)) {
|
if (Array.isArray(rows)) {
|
||||||
sizingRow = rows[0];
|
sizingRow = rows[0];
|
||||||
} else {
|
} else {
|
||||||
sizingRow = rows;
|
sizingRow = rows;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.sizingRows[sizingRow.objectKeyString]) {
|
if (!this.sizingRows[sizingRow.objectKeyString]) {
|
||||||
this.sizingRows[sizingRow.objectKeyString] = sizingRow;
|
this.sizingRows[sizingRow.objectKeyString] = sizingRow;
|
||||||
this.$nextTick().then(this.calculateColumnWidths);
|
this.$nextTick().then(this.calculateColumnWidths);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.updatingView) {
|
if (this.autoScroll) {
|
||||||
this.updatingView = true;
|
this.scrollToBottom();
|
||||||
requestAnimationFrame(()=> {
|
|
||||||
this.updateVisibleRows();
|
|
||||||
if (this.autoScroll) {
|
|
||||||
this.$nextTick().then(this.scrollToBottom);
|
|
||||||
}
|
|
||||||
this.updatingView = false;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.updateVisibleRows();
|
||||||
},
|
},
|
||||||
rowsRemoved(rows) {
|
rowsRemoved (rows) {
|
||||||
if (!this.updatingView) {
|
this.setHeight();
|
||||||
this.updatingView = true;
|
this.updateVisibleRows();
|
||||||
requestAnimationFrame(()=> {
|
},
|
||||||
this.updateVisibleRows();
|
/**
|
||||||
this.updatingView = false;
|
* Calculates height based on total number of rows, and sets table height.
|
||||||
});
|
*/
|
||||||
}
|
setHeight() {
|
||||||
|
let filteredRowsLength = this.table.filteredRows.getRows().length;
|
||||||
|
this.totalHeight = this.rowHeight * filteredRowsLength - 1;
|
||||||
|
// Set element height directly to avoid having to wait for Vue to update DOM
|
||||||
|
// which causes subsequent scroll to use an out of date height.
|
||||||
|
this.contentTable.style.height = this.totalHeight + 'px';
|
||||||
},
|
},
|
||||||
exportAsCSV() {
|
exportAsCSV() {
|
||||||
const headerKeys = Object.keys(this.headers);
|
const headerKeys = Object.keys(this.headers);
|
||||||
@ -595,7 +598,11 @@ export default {
|
|||||||
this.calculateTableSize();
|
this.calculateTableSize();
|
||||||
// On some resize events scrollTop is reset to 0. Possibly due to a transition we're using?
|
// On some resize events scrollTop is reset to 0. Possibly due to a transition we're using?
|
||||||
// Need to preserve scroll position in this case.
|
// Need to preserve scroll position in this case.
|
||||||
this.scrollable.scrollTop = scrollTop;
|
if (this.autoScroll) {
|
||||||
|
this.scrollToBottom();
|
||||||
|
} else {
|
||||||
|
this.scrollable.scrollTop = scrollTop;
|
||||||
|
}
|
||||||
width = el.clientWidth;
|
width = el.clientWidth;
|
||||||
height = el.clientHeight;
|
height = el.clientHeight;
|
||||||
}
|
}
|
||||||
@ -608,6 +615,9 @@ export default {
|
|||||||
this.filterChanged = _.debounce(this.filterChanged, 500);
|
this.filterChanged = _.debounce(this.filterChanged, 500);
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.rowsAdded = _.throttle(this.rowsAdded, 200);
|
||||||
|
this.rowsRemoved = _.throttle(this.rowsRemoved, 200);
|
||||||
|
this.scroll = _.throttle(this.scroll, 100);
|
||||||
|
|
||||||
this.table.on('object-added', this.addObject);
|
this.table.on('object-added', this.addObject);
|
||||||
this.table.on('object-removed', this.removeObject);
|
this.table.on('object-removed', this.removeObject);
|
||||||
@ -621,6 +631,7 @@ export default {
|
|||||||
//Default sort
|
//Default sort
|
||||||
this.sortOptions = this.table.filteredRows.sortBy();
|
this.sortOptions = this.table.filteredRows.sortBy();
|
||||||
this.scrollable = this.$el.querySelector('.js-telemetry-table__body-w');
|
this.scrollable = this.$el.querySelector('.js-telemetry-table__body-w');
|
||||||
|
this.contentTable = this.$el.querySelector('.js-telemetry-table__content');
|
||||||
this.sizingTable = this.$el.querySelector('.js-telemetry-table__sizing');
|
this.sizingTable = this.$el.querySelector('.js-telemetry-table__sizing');
|
||||||
this.headersHolderEl = this.$el.querySelector('.js-table__headers-w');
|
this.headersHolderEl = this.$el.querySelector('.js-table__headers-w');
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user