diff --git a/platform/commonUI/edit/src/policies/EditActionPolicy.js b/platform/commonUI/edit/src/policies/EditActionPolicy.js index dda1945e1d..2d6dd56b37 100644 --- a/platform/commonUI/edit/src/policies/EditActionPolicy.js +++ b/platform/commonUI/edit/src/policies/EditActionPolicy.js @@ -55,7 +55,7 @@ define( // A view is editable unless explicitly flagged as not (views || []).forEach(function (view) { - if (view.editable === true || + if (isEditable(view) || (view.key === 'plot' && type.getKey() === 'telemetry.panel') || (view.key === 'table' && type.getKey() === 'table') || (view.key === 'rt-table' && type.getKey() === 'rttable') @@ -64,6 +64,14 @@ define( } }); + function isEditable(view) { + if (typeof view.editable === Function) { + return view.editable(domainObject.useCapability('adapter')); + } else { + return view.editable === true; + } + } + return count; }; diff --git a/src/exporters/CSVExporter.js b/src/exporters/CSVExporter.js index 284d38fea3..e1fba993ae 100644 --- a/src/exporters/CSVExporter.js +++ b/src/exporters/CSVExporter.js @@ -20,20 +20,18 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -define([ - 'csv', - 'saveAs' -], function (CSV, saveAs) { - class CSVExporter { - export(rows, options) { - let headers = (options && options.headers) || - (Object.keys((rows[0] || {})).sort()); - let filename = (options && options.filename) || "export.csv"; - let csvText = new CSV(rows, { header: headers }).encode(); - let blob = new Blob([csvText], { type: "text/csv" }); - saveAs(blob, filename); - } - } +import CSV from 'comma-separated-values'; +import {saveAs} from 'file-saver/FileSaver'; - return CSVExporter; -}); \ No newline at end of file +class CSVExporter { + export(rows, options) { + let headers = (options && options.headers) || + (Object.keys((rows[0] || {})).sort()); + let filename = (options && options.filename) || "export.csv"; + let csvText = new CSV(rows, { header: headers }).encode(); + let blob = new Blob([csvText], { type: "text/csv" }); + saveAs(blob, filename); + } +}; + +export default CSVExporter; diff --git a/src/plugins/telemetryTable/TelemetryTableRow.js b/src/plugins/telemetryTable/TelemetryTableRow.js index 804a4ef44d..b90187be93 100644 --- a/src/plugins/telemetryTable/TelemetryTableRow.js +++ b/src/plugins/telemetryTable/TelemetryTableRow.js @@ -30,12 +30,11 @@ define([], function () { this.objectKeyString = objectKeyString; } - getFormattedDatum() { - return Object.values(this.columns) - .reduce((formattedDatum, column) => { - formattedDatum[column.getKey()] = this.getFormattedValue(column.getKey()); - return formattedDatum; - }, {}); + getFormattedDatum(headers) { + return Object.keys(headers).reduce((formattedDatum, columnKey) => { + formattedDatum[columnKey] = this.getFormattedValue(columnKey); + return formattedDatum; + }, {}); } getFormattedValue(key) { diff --git a/src/plugins/telemetryTable/TelemetryTableViewProvider.js b/src/plugins/telemetryTable/TelemetryTableViewProvider.js index 35ef0cd01a..58acc86d7e 100644 --- a/src/plugins/telemetryTable/TelemetryTableViewProvider.js +++ b/src/plugins/telemetryTable/TelemetryTableViewProvider.js @@ -35,12 +35,15 @@ define([ return { key: 'table', name: 'Telemetry Table', - editable: true, + cssClass: 'icon-tabular-realtime', + editable: function(domainObject) { + return domainObject.type === 'table'; + }, canView: function (domainObject) { return domainObject.type === 'table' || domainObject.hasOwnProperty('telemetry'); }, view: function (domainObject) { - let csvExporter = new CSVExporter(); + let csvExporter = new CSVExporter.default(); let table = new TelemetryTable(domainObject, openmct); let component; return { diff --git a/src/plugins/telemetryTable/collections/SortedTableRowCollection.js b/src/plugins/telemetryTable/collections/SortedTableRowCollection.js index 756896f25f..96c369fe8e 100644 --- a/src/plugins/telemetryTable/collections/SortedTableRowCollection.js +++ b/src/plugins/telemetryTable/collections/SortedTableRowCollection.js @@ -82,8 +82,7 @@ define( // Going to check for duplicates. Bound the search problem to // items around the given time. Use sortedIndex because it // employs a binary search which is O(log n). Can use binary search - // based on time stamp because the array is guaranteed ordered due - // to sorted insertion. + // because the array is guaranteed ordered due to sorted insertion. let startIx = this.sortedIndex(this.rows, row); let endIx = undefined; @@ -113,26 +112,49 @@ define( * @private */ sortedIndex(rows, testRow, lodashFunction) { + if (this.rows.length === 0) { + return 0; + } + const sortOptionsKey = this.sortOptions.key; + const testRowValue = testRow.datum[sortOptionsKey]; + const firstValue = this.rows[0].datum[sortOptionsKey]; + const lastValue = this.rows[this.rows.length - 1].datum[sortOptionsKey]; + lodashFunction = lodashFunction || _.sortedIndex; if (this.sortOptions.direction === 'asc') { - return lodashFunction(rows, testRow, (thisRow) => { - return thisRow.datum[sortOptionsKey]; - }); + if (testRowValue > lastValue) { + return this.rows.length; + } else if (testRowValue === lastValue) { + return this.rows.length - 1; + } else if (testRowValue <= firstValue) { + return 0; + } else { + return lodashFunction(rows, testRow, (thisRow) => { + return thisRow.datum[sortOptionsKey]; + }); + } } else { - const testRowValue = testRow.datum[this.sortOptions.key]; - // Use a custom comparison function to support descending sort. - return lodashFunction(rows, testRow, (thisRow) => { - const thisRowValue = thisRow.datum[sortOptionsKey]; - if (testRowValue === thisRowValue) { - return EQUAL; - } else if (testRowValue < thisRowValue) { - return LESS_THAN; - } else { - return GREATER_THAN; - } - }); + if (testRowValue >= firstValue) { + return 0; + } else if (testRowValue < lastValue) { + return this.rows.length; + } else if (testRowValue === lastValue) { + return this.rows.length - 1; + } else { + // Use a custom comparison function to support descending sort. + return lodashFunction(rows, testRow, (thisRow) => { + const thisRowValue = thisRow.datum[sortOptionsKey]; + if (testRowValue === thisRowValue) { + return EQUAL; + } else if (testRowValue < thisRowValue) { + return LESS_THAN; + } else { + return GREATER_THAN; + } + }); + } } } diff --git a/src/plugins/telemetryTable/components/table-row.vue b/src/plugins/telemetryTable/components/table-row.vue index 8d39e95481..d8991ff869 100644 --- a/src/plugins/telemetryTable/components/table-row.vue +++ b/src/plugins/telemetryTable/components/table-row.vue @@ -15,7 +15,7 @@ export default { data: function () { return { rowTop: (this.rowOffset + this.rowIndex) * this.rowHeight + 'px', - formattedRow: this.row.getFormattedDatum(), + formattedRow: this.row.getFormattedDatum(this.headers), rowLimitClass: this.row.getRowLimitClass(), cellLimitClasses: this.row.getCellLimitClasses() } @@ -59,7 +59,7 @@ export default { this.rowTop = (rowOffset + this.rowIndex) * this.rowHeight + 'px'; }, formatRow: function (row) { - this.formattedRow = row.getFormattedDatum(); + this.formattedRow = row.getFormattedDatum(this.headers); this.rowLimitClass = row.getRowLimitClass(); this.cellLimitClasses = row.getCellLimitClasses(); } diff --git a/src/plugins/telemetryTable/components/table.vue b/src/plugins/telemetryTable/components/table.vue index cbd8bcbce7..2d7454d7c0 100644 --- a/src/plugins/telemetryTable/components/table.vue +++ b/src/plugins/telemetryTable/components/table.vue @@ -282,7 +282,6 @@ export default { data() { return { headers: {}, - headersCount: 0, visibleRows: [], columnWidths: [], sizingRows: {}, @@ -346,7 +345,6 @@ export default { let headers = this.table.configuration.getVisibleHeaders(); this.headers = headers; - this.headersCount = Object.values(headers).length; this.$nextTick().then(this.calculateColumnWidths); }, setSizingTableWidth() { @@ -454,12 +452,12 @@ export default { } }, exportAsCSV() { + const headerKeys = Object.keys(this.headers); const justTheData = this.table.filteredRows.getRows() - .map(row => row.getFormattedDatum()); - const headers = Object.keys(this.headers); + .map(row => row.getFormattedDatum(this.headers)); this.csvExporter.export(justTheData, { filename: this.table.domainObject.name + '.csv', - headers: headers + headers: headerKeys }); }, outstandingRequests(loading) {