UNPKG

tsiclient

Version:

--- [//]: <> (This content is similar to https://github.com/MicrosoftDocs/azure-docs/edit/main/includes/tsi-retirement.md)

554 lines (548 loc) 28.1 kB
import { a as __extends } from './tslib.es6-f952ba6f.js'; import { U as Utils, v as valueTypes } from './Utils-38a0872e.js'; import { select } from 'd3'; import { C as ChartComponent } from './ChartComponent-ed6f3c6d.js'; var TimeSeriesEventCell = /** @class */ (function () { function TimeSeriesEventCell(name, value, type) { if (type === void 0) { type = null; } this.key = name + "_" + type; this.name = name; this.type = type; this.value = value; } return TimeSeriesEventCell; }()); var TimeSeriesEvent = /** @class */ (function () { function TimeSeriesEvent(rawEvent, offset, offsetName, locale) { if (offset === void 0) { offset = null; } if (offsetName === void 0) { offsetName = null; } if (locale === void 0) { locale = 'en'; } this.cells = {}; if (offset !== null) { var type = 'DateTime'; var utcOffsetDate_1 = Utils.offsetUTC(new Date(Date.parse(rawEvent['timestamp ($ts)'].split("Z").join("")))); rawEvent[offsetName + "_" + type] = { name: offsetName, value: function () { return Utils.timeFormat(true, true, offset, true, null, null, locale)(utcOffsetDate_1); }, type: type }; } this.cells = Object.keys(rawEvent).reduce(function (cellObj, propId) { var cell; if (propId == "timestamp ($ts)") cell = new TimeSeriesEventCell('timestamp ($ts)', rawEvent[propId], 'DateTime'); else { cell = new TimeSeriesEventCell(rawEvent[propId]['name'], rawEvent[propId]['value'], rawEvent[propId]['type']); } cellObj[cell.key] = cell; return cellObj; }, {}); } return TimeSeriesEvent; }()); var EventsTableData = /** @class */ (function () { function EventsTableData() { this.columns = {}; this.rows = []; this.events = []; this.timestampColumnKey = "timestamp ($ts)_DateTime"; this.offsetName = null; this.maxVisibleToStart = 10; this.offsetNameCache = {}; this.timeSeriesIdProperties = []; } EventsTableData.prototype.createOffsetName = function (offset) { if (offset in this.offsetNameCache) { return this.offsetNameCache[offset]; } var offsetSubstring = ""; if ((typeof offset) === 'string') { offsetSubstring = Utils.convertTimezoneToLabel(offset); } else { offsetSubstring = Utils.formatOffsetMinutes(offset); } var offsetName = "timestamp " + offsetSubstring; this.offsetNameCache[offset] = offsetName; return offsetName; }; EventsTableData.prototype.sortColumnKeys = function () { var _this = this; var columnKeys = Object.keys(this.columns); var existingTsidColumnKeys = Object.values(this.columns).filter(function (c) { return c['isTsid']; }).map(function (c) { return c['key']; }); // detect existing time series id properties in column keys columnKeys = existingTsidColumnKeys.concat(columnKeys.filter(function (c) { return !existingTsidColumnKeys.includes(c); })); // put these time series id properties to the beginning of the column key list var offsetKey = this.offsetName + "_DateTime"; var lessTimestamps = columnKeys.filter(function (columnKey) { return (columnKey !== _this.timestampColumnKey && columnKey !== offsetKey); }); var timestamps = []; if (columnKeys.indexOf(this.timestampColumnKey) !== -1) timestamps.push(this.timestampColumnKey); if (columnKeys.indexOf(offsetKey) !== -1) timestamps.push(offsetKey); return timestamps.concat(lessTimestamps); }; EventsTableData.prototype.setEvents = function (rawEvents, fromTsx, timeSeriesIdProperties, offset) { var _this = this; if (offset === void 0) { offset = null; } this.timeSeriesIdProperties = timeSeriesIdProperties; this.events = []; rawEvents.forEach(function (rawEvent) { if (!fromTsx) { rawEvent = Object.keys(rawEvent).reduce(function (newEventMap, currColName) { newEventMap[currColName] = { name: currColName, value: rawEvent[currColName] }; return newEventMap; }, {}); } if (offset !== null) { _this.offsetName = _this.createOffsetName(offset); } var event = new TimeSeriesEvent(rawEvent, offset, (offset !== null ? _this.offsetName : null)); _this.events.push(event); }); this.constructColumns(); }; EventsTableData.prototype.sortEvents = function (columnKey, isAscending) { var sortType = this.columns[columnKey].type; var aTop = 1; var bTop = -1; if (!isAscending) { aTop = -1; bTop = 1; } this.events.sort(function (a, b) { if ((a.cells && a.cells[columnKey]) || (b.cells && b.cells[columnKey])) { var aConverted = (a.cells && a.cells[columnKey]) ? a.cells[columnKey].value : null; var bConverted = (b.cells && b.cells[columnKey]) ? b.cells[columnKey].value : null; //one value is null if (aConverted == null) return bTop; if (bConverted == null) return aTop; //convert to appropriate type if (sortType == "Double") { aConverted = Number(aConverted); bConverted = Number(bConverted); } else if (sortType == "DateTime") { aConverted = (new Date(aConverted)).valueOf(); bConverted = (new Date(bConverted)).valueOf(); } //compare if (aConverted > bConverted) return aTop; if (aConverted < bConverted) return bTop; return 0; } return 0; }); }; EventsTableData.prototype.constructColumns = function () { var _this = this; var timeSeriesIdPropertyKeys = this.timeSeriesIdProperties.map(function (p) { return p.name + "_" + p.type; }); var newColumns = {}; this.events.forEach(function (event) { Object.keys(event.cells).forEach(function (cellKey) { var cell = event.cells[cellKey]; if (_this.columns[cell.key] == null) { newColumns[cell.key] = { key: cell.key, name: cell.name, visible: true, type: cell.type, isTsid: timeSeriesIdPropertyKeys.includes(cell.key) }; } else { newColumns[cell.key] = _this.columns[cell.key]; } }); }); var visibleColumnCounter = Object.values(newColumns).filter(function (c) { return c['isTsid']; }).length; Object.keys(newColumns).forEach(function (columnKey) { if (newColumns[columnKey].isTsid) { newColumns[columnKey].visible = true; } else { newColumns[columnKey].visible = visibleColumnCounter < _this.maxVisibleToStart; visibleColumnCounter++; } }); this.columns = newColumns; }; EventsTableData.prototype.generateCSVString = function (includeAllColumns, offset) { //replace comma at end of line with end line character var endLine = function (s) { return s.slice(0, s.length - 1) + "\n"; }; var columnKeys = this.sortColumnKeys(); var csvString = endLine(columnKeys.reduce(function (headerString, columnKey) { return headerString + Utils.sanitizeString(columnKey, valueTypes.String) + ","; }, "")); this.events.forEach(function (event) { csvString += endLine(columnKeys.reduce(function (lineString, columnKey) { var value = (event.cells[columnKey] ? (typeof (event.cells[columnKey].value) === 'function' ? event.cells[columnKey].value() : event.cells[columnKey].value) : null); return lineString + ((event.cells[columnKey] != null && Utils.sanitizeString(value, event.cells[columnKey].type) !== null) ? Utils.sanitizeString(value, event.cells[columnKey].type) : "") + ","; }, "")); }); return csvString; }; return EventsTableData; }()); var EventsTable = /** @class */ (function (_super) { __extends(EventsTable, _super); function EventsTable(renderTarget) { var _this = _super.call(this, renderTarget) || this; _this.maxVisibleIndex = 100; _this.isAscending = true; _this.timestampColumnName = 'timestamp ($ts)'; _this.sortColumn = 'timestamp ($ts)'; _this.allSelectedState = "all"; // all | some | none _this.eventsTableData = new EventsTableData(); _this.margins = { left: 10, right: 10 }; return _this; } EventsTable.prototype.EventsTable = function () { }; EventsTable.prototype.renderFromEventsTsx = function (eventsFromTsx, chartOptions) { this.render(eventsFromTsx, chartOptions, true); }; EventsTable.prototype.render = function (events, chartOptions, fromTsx) { if (fromTsx === void 0) { fromTsx = false; } this.chartOptions.setOptions(chartOptions); this.maxVisibleIndex = 100; this.eventsTableData.setEvents(events, fromTsx, this.chartOptions.timeSeriesIdProperties, chartOptions.offset); var componentContainer = select(this.renderTarget) .classed("tsi-tableComponent", true); _super.prototype.themify.call(this, componentContainer, this.chartOptions.theme); var tableLeftPanel; if (this.eventsTable == null) { tableLeftPanel = componentContainer.append("div") .classed("tsi-tableLeftPanel", true); this.eventsLegend = tableLeftPanel.append("div") .classed("tsi-tableLegend", true); this.eventsLegend.append("ul"); this.eventsTable = componentContainer.append("div") .classed("tsi-eventsTable", true); this.eventsTable.append("div").classed("tsi-columnHeaders", true); var table = this.eventsTable.append("div").classed("tsi-eventRowsContainer", true) .append("table").classed("tsi-eventRows", true); table.append("tr"); } else { tableLeftPanel = componentContainer.select("tsi-tableLeftPanel"); } this.renderLegend(); this.buildTable(); tableLeftPanel.selectAll(".tsi-eventsDownload").remove(); var downloadButton = tableLeftPanel.append("button") .attr("class", "tsi-eventsDownload tsi-primaryButton") .attr("aria-label", this.getString("Download as CSV")) .on("click", function () { var _this = this; this.classList.add('tsi-downloading'); setTimeout(function () { Utils.downloadCSV(self.eventsTableData.generateCSVString(true, 0), "Events"); _this.classList.remove('tsi-downloading'); }, 100); }); downloadButton.append("div").attr("class", "tsi-downloadEventsIcon"); downloadButton.append("div").attr("class", "tsi-downloadEventsText").text(this.getString("Download as CSV")); //listen for table scroll and adjust the headers accordingly var self = this; this.eventsTable.select('.tsi-eventRowsContainer').node().scrollLeft = 0; this.eventsTable.select('.tsi-eventRowsContainer').node().scrollTop = 0; this.eventsTable.select('.tsi-eventRowsContainer').node().addEventListener('scroll', function (evt) { self.eventsTable.select('.tsi-columnHeaders').node().scrollLeft = this.scrollLeft; //check to see if need to infiniteScroll if ((this.scrollTop + this.clientHeight) > (this.scrollHeight - 100)) { var oldVisibleIndex = self.maxVisibleIndex; self.maxVisibleIndex += (Math.min(100, self.eventsTableData.events.length - self.maxVisibleIndex)); if (self.maxVisibleIndex != oldVisibleIndex) self.buildTable(); } }, false); }; EventsTable.prototype.renderLegend = function () { var _this = this; this.eventsLegend.html(""); this.eventsLegend.append("ul"); var columns = this.eventsTableData.sortColumnKeys() .map(function (cIdx) { return _this.eventsTableData.columns[cIdx]; }); this.setSelectAllState(); if (columns.length > 2) { // tristate - all selected var selectAllColumns = this.eventsLegend.select("ul") .append("li").attr("class", "tsi-selectAllColumns"); selectAllColumns.append("button").attr("class", "tsi-columnToggleButton") .attr("aria-label", function () { var selectAllState = _this.getSelectAllState(); return selectAllState !== "all" ? _this.getString("Toggle all columns") : _this.getString("Toggle all columns"); }) .on("click", function () { var setAllVisible = false; var selectAllState = _this.getSelectAllState(); if (selectAllState != "all") { setAllVisible = true; } Object.keys(_this.eventsTableData.columns).forEach(function (columnKey) { if (setAllVisible) { _this.eventsTableData.columns[columnKey].visible = true; } else { if (columnKey != _this.timestampColumnName) _this.eventsTableData.columns[columnKey].visible = false; } }); _this.setLegendColumnStates(); _this.buildTable(); }); selectAllColumns.append("span").attr("class", "tsi-columnToggleCheckbox"); selectAllColumns.append("span").attr("class", "tsi-selectAllSomeState"); selectAllColumns.append("span").attr("class", "tsi-columnToggleName") .text(this.getString("All Columns")); } var toggleableColumnLis = this.eventsLegend.select("ul").selectAll(".tsi-columnToggle") .data(columns); var toggleableColumnLisEntered = toggleableColumnLis.enter() .append("li") .classed("tsi-columnToggle", true) .merge(toggleableColumnLis); var self = this; toggleableColumnLisEntered.each(function (d) { select(this).append("button").attr("class", "tsi-columnToggleButton") .attr("aria-label", function (d) { return "toggle column " + d.key; }) .on("click", function (event, d) { d.visible = !d.visible; self.setLegendColumnStates(); self.buildTable(); }); select(this).append("div").attr("class", "tsi-columnToggleCheckbox"); if (d.isTsid) { var typeIconCOntainer = select(this).append("div").attr("class", "tsi-columnTypeIcons"); typeIconCOntainer.append("span").attr("class", "tsi-columnTypeIcon") .classed("tsid", true).attr("title", self.getString("Time Series ID")); typeIconCOntainer.append("span").attr("class", "tsi-columnTypeIcon") .classed(d.type, true); } else { select(this).append("div").attr("class", "tsi-columnTypeIcon") .classed(d.type, true); } select(this).select("button").append("div").attr("class", "tsi-onlyLabel").text(self.getString("only")) .attr('tabindex', "0") .attr('role', 'button') .on("click", function (event, d) { event.stopPropagation(); columns.forEach(function (column) { if (column.key == d.key) column.visible = true; else column.visible = false; }); self.setLegendColumnStates(); self.buildTable(); }); select(this).append("div").attr("class", "tsi-columnToggleName").classed('tsidPropertyName', function (d) { return d.isTsid; }).text(function (d) { return columns.filter(function (c) { return c.name === d.name; }).length > 1 ? d.name + " (" + d.type + ")" : d.name; }); }); this.setLegendColumnStates(); toggleableColumnLis.exit().remove(); }; EventsTable.prototype.setLegendColumnStates = function () { if (this.eventsLegend.select("ul")) { this.eventsLegend.select("ul").selectAll(".tsi-columnToggle").each(function () { select(this).select(".tsi-columnToggleCheckbox").classed("tsi-notSelected", function (d) { return !(d.visible); }); }); } this.setSelectAllState(); }; EventsTable.prototype.getSelectAllState = function () { var _this = this; var selectAllState = Object.keys(this.eventsTableData.columns).reduce(function (prev, curr) { if (curr == _this.timestampColumnName) // skip timestamp, will always be visible return prev; if (prev == null) return (_this.eventsTableData.columns[curr].visible) ? "all" : "none"; if (prev == "some") return "some"; return (prev == (_this.eventsTableData.columns[curr].visible ? "all" : "none")) ? prev : "some"; }, null); if (selectAllState == null) selectAllState = "none"; return selectAllState; }; EventsTable.prototype.setSelectAllState = function () { var selectAllState = this.getSelectAllState(); var selectAllColumns = this.eventsLegend.select("ul").select(".tsi-selectAllColumns"); selectAllColumns.select(".tsi-columnToggleCheckbox") .classed("tsi-notSelected", function () { return selectAllState !== "all"; }); selectAllColumns.select(".tsi-columnToggleButton") .attr("aria-label", (selectAllState !== "all" ? this.getString("Toggle all columns on") : this.getString("Toggle all columns off"))); this.eventsLegend.select("ul").select(".tsi-selectAllColumns").select(".tsi-selectAllSomeState") .style("visibility", function () { return (selectAllState == "some") ? "visible" : "hidden"; }); }; EventsTable.prototype.getFilteredColumnKeys = function () { var _this = this; return this.eventsTableData.sortColumnKeys().filter(function (columnKey) { return _this.eventsTableData.columns[columnKey].visible; }); }; //creates columnHeaders, returns a dictionary of widths so that buildTable can know the min width of each column EventsTable.prototype.buildHeaders = function (filteredColumnKeys, focusedHeader) { var _this = this; if (focusedHeader === void 0) { focusedHeader = null; } var longAndDoubleExist = function (propertyKey) { var propertyName = _this.eventsTableData.columns[propertyKey].name; return _this.eventsTableData.columns.hasOwnProperty(propertyName + "_Long") && _this.eventsTableData.columns.hasOwnProperty(propertyName + "_Double"); }; this.eventsTable.select(".tsi-columnHeaders").html(""); var self = this; var columnHeaders = this.eventsTable.select(".tsi-columnHeaders").selectAll(".tsi-columnHeader") .data(filteredColumnKeys); var isOffsetDateTimeColumn = function (d) { return d.includes('timestamp') && (d.includes('') || d.includes('-')) && !d.includes('$ts') ? true : null; }; var columnHeadersEntered = columnHeaders.enter() .append("div") .classed("tsi-columnHeader", true) .classed("tsi-columnHeaderDisabled", isOffsetDateTimeColumn) .each(function (d) { select(this).append("span") .classed("tsi-columnHeaderName", true) .classed("moreMarginRight", function (d) { return self.eventsTableData.columns[d].isTsid; }) .text(longAndDoubleExist(d) ? self.eventsTableData.columns[d].name + " (" + self.eventsTableData.columns[d].type + ")" : self.eventsTableData.columns[d].name); select(this).append("span").attr("class", "tsi-columnSortIcon").classed("moreRight", self.eventsTableData.columns[d].isTsid) .classed("up", (self.sortColumn == d && self.isAscending)) .classed("down", (self.sortColumn == d && !self.isAscending)); if (self.eventsTableData.columns[d].isTsid) { var typeIconContainer = select(this).append("div").attr("class", "tsi-columnTypeIcons"); typeIconContainer.append("span").attr("class", "tsi-columnTypeIcon") .classed("tsid", true).attr("title", self.getString("Time Series ID")); typeIconContainer.append("span").attr("class", "tsi-columnTypeIcon") .classed(self.eventsTableData.columns[d].type, true); } else { select(this).append("span").attr("class", "tsi-columnTypeIcon") .classed(self.eventsTableData.columns[d].type, true); } var id = JSON.parse(JSON.stringify(d)); select(this).append("button").attr("class", "tsi-sortColumnButton") .attr("aria-label", function (title) { return "Sort by column " + title; }) .on("click", function (event, f) { //set sort column and direction if (self.sortColumn == d) { self.isAscending = !self.isAscending; } else { self.isAscending = false; } self.sortColumn = d; self.eventsTableData.sortEvents(d, self.isAscending); self.buildTable(f); self.eventsTable.select('.tsi-columnHeaders').node().scrollLeft = self.eventsTable.select('.tsi-eventRowsContainer').node().scrollLeft; }) .attr("disabled", isOffsetDateTimeColumn); }); var widthDictionary = {}; columnHeadersEntered.each(function (d) { widthDictionary[d] = select(this).node().getBoundingClientRect().width; }); columnHeaders.exit().remove(); if (focusedHeader !== null) { var columnHeader = select(columnHeadersEntered.filter(function (d) { return d === focusedHeader; }).nodes()[0]); if (columnHeader) { columnHeader.select("button").node().focus(); } } return widthDictionary; }; EventsTable.prototype.adjustHeaderWidth = function (widthDictionary) { //set the width to fit inside the container less the scroll bar var tableSelection = this.eventsTable.select('.tsi-eventRowsContainer').node(); var scrollBarWidthDiff = tableSelection.getBoundingClientRect().width - tableSelection.clientWidth; this.eventsTable.select(".tsi-columnHeaders").style("width", "calc(100% - " + scrollBarWidthDiff + "px)"); this.eventsTable.select(".tsi-columnHeaders").selectAll(".tsi-columnHeader") .style("width", function (d) { if (widthDictionary[d]) return (widthDictionary[d] - 17) + "px"; //17 pixel difference in element due to padding/border else { return select(this).style("width"); } }); }; EventsTable.prototype.buildTable = function (currentSortedCol) { var _this = this; if (currentSortedCol === void 0) { currentSortedCol = null; } var filteredColumnKeys = this.getFilteredColumnKeys(); var widthDictionary = this.buildHeaders(filteredColumnKeys, currentSortedCol); this.eventsTable.select("table").html(""); var self = this; var rowsData = this.eventsTableData.events.slice(0, this.maxVisibleIndex); var firstRow = this.eventsTable.select("table").append("tr") .classed("tsi-eventRow", true); var firstRowCells = firstRow.selectAll("td").data(filteredColumnKeys); firstRowCells.enter() .append("td") .classed("tsi-eventCell", true) .text(function (d) { return _this.eventsTableData.columns[d].name; }); var rows = this.eventsTable.select("table").selectAll("tsi-eventRow").data(rowsData); var rowsEntered = rows.enter() .append("tr") .classed("tsi-eventRow", true) .merge(rows) .each(function (event) { var visibleCells = filteredColumnKeys.map(function (columnKey) { if (event.cells[columnKey]) return event.cells[columnKey]; return { key: columnKey, value: null }; }); var valueCells = select(this).selectAll("td").data(visibleCells); var valueCellsEntered = valueCells.enter() .append("td") .classed("tsi-eventCell", true) .style("min-width", function (d) { if (widthDictionary[d.key] != null) return Math.ceil(widthDictionary[d.key]) + "px"; else return "none"; }) .text(function (d) { return self.formatValue(d.value, d.type); }); valueCells.exit().remove(); }); if (rowsEntered.size() > 0) { var firstRow = rowsEntered.filter(function (d, i) { return i === 0; }); firstRow.selectAll("td").each(function (d) { var cellWidth = select(this).node().getBoundingClientRect().width; widthDictionary[d.key] = (cellWidth > widthDictionary[d.key]) ? cellWidth : widthDictionary[d.key]; }); } rows.exit().remove(); this.adjustHeaderWidth(widthDictionary); }; EventsTable.prototype.formatValue = function (value, type) { if (type === 'Dynamic') { return JSON.stringify(value); } if (type !== 'DateTime' || value === null || value === undefined) { return value; } if (typeof (value) === 'function') { return value(); } var timeFormatFunction = Utils.timeFormat(true, true, 0, this.chartOptions.is24HourTime, null, null, this.chartOptions.dateLocale); var dateValue = new Date(value.split("Z").join("")); return timeFormatFunction(Utils.offsetUTC(dateValue)); }; return EventsTable; }(ChartComponent)); export { EventsTable as E };