diff --git a/log-viewer/modules/components/analysis-view/AnalysisView.ts b/log-viewer/modules/components/analysis-view/AnalysisView.ts index a942feea..1b02a1ac 100644 --- a/log-viewer/modules/components/analysis-view/AnalysisView.ts +++ b/log-viewer/modules/components/analysis-view/AnalysisView.ts @@ -219,8 +219,7 @@ export class AnalysisView extends LitElement { newFindArgs.options.matchCase !== this.findArgs.options?.matchCase; this.findArgs = newFindArgs; - const clearHighlights = - e.type === 'lv-find-close' || (!isTableVisible && newFindArgs.count === 0); + const clearHighlights = e.type === 'lv-find-close'; if (clearHighlights) { newFindArgs.text = ''; } @@ -423,7 +422,7 @@ export class AnalysisView extends LitElement { _clearSearchHighlights() { this._find( - new CustomEvent('lv-find', { + new CustomEvent('lv-find-close', { detail: { text: '', count: 0, options: { matchCase: false } }, }), ); diff --git a/log-viewer/modules/components/calltree-view/CalltreeView.ts b/log-viewer/modules/components/calltree-view/CalltreeView.ts index 619bd7cc..e552e062 100644 --- a/log-viewer/modules/components/calltree-view/CalltreeView.ts +++ b/log-viewer/modules/components/calltree-view/CalltreeView.ts @@ -358,9 +358,7 @@ export class CalltreeView extends LitElement { newFindArgs.options.matchCase !== this.findArgs.options?.matchCase; this.findArgs = newFindArgs; - const clearHighlights = - e.type === 'lv-find-close' || - (this.canClearSearchHighlights && !isTableVisible && newFindArgs.count === 0); + const clearHighlights = e.type === 'lv-find-close'; if (clearHighlights) { newFindArgs.text = ''; } @@ -805,7 +803,7 @@ export class CalltreeView extends LitElement { private _clearSearchHighlights() { this._find( - new CustomEvent('lv-find', { + new CustomEvent('lv-find-close', { detail: { text: '', count: 0, options: { matchCase: false } }, }), ); diff --git a/log-viewer/modules/components/database-view/DMLView.ts b/log-viewer/modules/components/database-view/DMLView.ts index e6b9f8e3..7ea6d345 100644 --- a/log-viewer/modules/components/database-view/DMLView.ts +++ b/log-viewer/modules/components/database-view/DMLView.ts @@ -62,6 +62,7 @@ export class DMLView extends LitElement { }; findMap: { [key: number]: RowComponent } = {}; totalMatches = 0; + canClearHighlights = false; constructor() { super(); @@ -219,6 +220,8 @@ export class DMLView extends LitElement { return; } + this.canClearHighlights = true; + const newFindArgs = JSON.parse(JSON.stringify(e.detail)); if (!isTableVisible) { newFindArgs.text = ''; @@ -229,8 +232,7 @@ export class DMLView extends LitElement { newFindArgs.options.matchCase !== this.findArgs.options?.matchCase; this.findArgs = newFindArgs; - const clearHighlights = - e.type === 'lv-find-close' || (!isTableVisible && newFindArgs.count === 0); + const clearHighlights = e.type === 'lv-find-close'; if (clearHighlights) { newFindArgs.text = ''; } @@ -248,6 +250,7 @@ export class DMLView extends LitElement { ); } } + this.canClearHighlights = false; } _renderDMLTable(dmlTableContainer: HTMLElement, dmlLines: DMLBeginLine[]) { @@ -298,6 +301,7 @@ export class DMLView extends LitElement { selectableRows: 'highlight', dataTree: true, dataTreeBranchElement: false, + dataTreeStartExpanded: true, columnDefaults: { title: 'default', resizable: true, @@ -377,8 +381,10 @@ export class DMLView extends LitElement { }); this.dmlTable.on('dataFiltering', () => { - this._resetFindWidget(); - this._clearSearchHighlights(); + if (this.canClearHighlights) { + this._resetFindWidget(); + this._clearSearchHighlights(); + } }); this.dmlTable.on('groupClick', (e: UIEvent, group: GroupComponent) => { @@ -389,13 +395,6 @@ export class DMLView extends LitElement { this.dmlTable?.blockRedraw(); group.toggle(); - if (!group.isVisible()) { - this.dmlTable?.getRows().forEach((row) => { - if (!row.isTreeExpanded()) { - row.treeExpand(); - } - }); - } this.dmlTable?.restoreRedraw(); }); @@ -438,7 +437,7 @@ export class DMLView extends LitElement { private _clearSearchHighlights() { this._find( - new CustomEvent('lv-find', { + new CustomEvent('lv-find-close', { detail: { text: '', count: 0, options: { matchCase: false } }, }), ); diff --git a/log-viewer/modules/components/database-view/SOQLView.ts b/log-viewer/modules/components/database-view/SOQLView.ts index db59b0bb..2915fe9b 100644 --- a/log-viewer/modules/components/database-view/SOQLView.ts +++ b/log-viewer/modules/components/database-view/SOQLView.ts @@ -73,6 +73,7 @@ export class SOQLView extends LitElement { }; findMap: { [key: number]: RowComponent } = {}; totalMatches = 0; + canClearHighlights = false; get _soqlTableWrapper(): HTMLDivElement | null { return this.renderRoot?.querySelector('#db-soql-table') ?? null; @@ -253,14 +254,15 @@ export class SOQLView extends LitElement { return; } + this.canClearHighlights = true; + const newFindArgs = JSON.parse(JSON.stringify(e.detail)); const newSearch = newFindArgs.text !== this.findArgs.text || newFindArgs.options.matchCase !== this.findArgs.options?.matchCase; this.findArgs = newFindArgs; - const clearHighlights = - e.type === 'lv-find-close' || (!isTableVisible && newFindArgs.count === 0); + const clearHighlights = e.type === 'lv-find-close'; if (clearHighlights) { newFindArgs.text = ''; } @@ -278,6 +280,8 @@ export class SOQLView extends LitElement { ); } } + + this.canClearHighlights = false; } _renderSOQLTable(soqlTableContainer: HTMLElement, soqlLines: SOQLExecuteBeginLine[]) { @@ -340,6 +344,7 @@ export class SOQLView extends LitElement { }, dataTree: true, dataTreeBranchElement: false, + dataTreeStartExpanded: true, columnDefaults: { title: 'default', resizable: true, @@ -513,13 +518,6 @@ export class SOQLView extends LitElement { this.soqlTable?.blockRedraw(); group.toggle(); - if (!group.isVisible()) { - this.soqlTable?.getRows().forEach((row) => { - if (!row.isTreeExpanded()) { - row.treeExpand(); - } - }); - } this.soqlTable?.restoreRedraw(); }); @@ -540,8 +538,10 @@ export class SOQLView extends LitElement { }); this.soqlTable.on('dataFiltering', () => { - this._resetFindWidget(); - this._clearSearchHighlights(); + if (this.canClearHighlights) { + this._resetFindWidget(); + this._clearSearchHighlights(); + } }); this.soqlTable.on('renderStarted', () => { @@ -567,7 +567,7 @@ export class SOQLView extends LitElement { _clearSearchHighlights() { this._find( - new CustomEvent('lv-find', { + new CustomEvent('lv-find-close', { detail: { text: '', count: 0, options: { matchCase: false } }, }), ); diff --git a/log-viewer/modules/datagrid/groups/GroupCalcs.ts b/log-viewer/modules/datagrid/groups/GroupCalcs.ts index e0a91aa9..c1d8f179 100644 --- a/log-viewer/modules/datagrid/groups/GroupCalcs.ts +++ b/log-viewer/modules/datagrid/groups/GroupCalcs.ts @@ -27,10 +27,10 @@ export class GroupCalcs extends Module { const arrowClone = rawGroup.arrowElement.cloneNode(true); rawGroup.arrowElement = document.createElement('span'); - const rowFrag = document.createDocumentFragment(); const firstCell = row.cells[0].getElement(); firstCell.insertBefore(arrowClone, firstCell.firstChild); + const rowFrag = document.createDocumentFragment(); row.cells.forEach((cell: { getElement(): HTMLElement }) => { rowFrag.appendChild(cell.getElement()); }); diff --git a/log-viewer/modules/datagrid/groups/GroupSort.ts b/log-viewer/modules/datagrid/groups/GroupSort.ts index a026065e..3307a122 100644 --- a/log-viewer/modules/datagrid/groups/GroupSort.ts +++ b/log-viewer/modules/datagrid/groups/GroupSort.ts @@ -12,11 +12,7 @@ export class GroupSort extends Module { initialize() { // @ts-expect-error groupSort is a custom propoerty see registerTableOption above if (this.table.options.groupSort) { - this.table.on('dataSorting', () => { - this.table.blockRedraw(); - this._sortGroups(); - this.table.restoreRedraw(); - }); + this.subscribe('sort-changed', this._sortGroups.bind(this)); } } @@ -34,89 +30,111 @@ export class GroupSort extends Module { } } - _areGroupsEqual(oldGroups: unknown[], newGroups: unknown[]) { - return ( - oldGroups && - newGroups.length === oldGroups.length && - newGroups.every((value, index) => value === oldGroups[index]) - ); - } - _sortGroups() { const grpArray = Array.isArray(this.table.options.groupBy) ? this.table.options.groupBy : [this.table.options.groupBy]; const { options } = this.table; - options.groupValues = []; const validGrps = grpArray.filter(Boolean).length > 0; - if (this.table && this.table.options.sortMode !== 'remote' && validGrps) { - const { modules } = this.table; + if (this.table && options.sortMode !== 'remote' && validGrps) { + let groupFunc = grpArray[0]; + const grpField = groupFunc as string; + if (typeof groupFunc === 'string') { + groupFunc = function (data) { + return data[grpField]; + }; + } - const groupRows = modules.groupRows; - const rows = this.table.rowManager.rows; - groupRows.configureGroupSetup(); - groupRows.generateGroups(rows); + const groupsByKey: { [key: string]: unknown[] } = {}; + if (groupFunc) { + const rows = this.table.rowManager.rows; + rows.forEach((row: InternalColumnTotal) => { + const grpVal = groupFunc(row.data); + let groupRows = groupsByKey[grpVal]; + if (!groupRows) { + groupRows = []; + groupsByKey[grpVal] = groupRows; + } + groupRows.push(row); + }); + } - const groupTotalsRows: InternalColumnTotal[] = []; - const columnCalcs = modules.columnCalcs; + let groupTotalsRows: InternalColumnTotal[] = []; + const columnCalcs = this.table.modules.columnCalcs; const field = columnCalcs.botCalcs[0].field; - groupRows.groupList.forEach((group: { key: string; rows: { data: unknown }[] }) => { - const row = columnCalcs.generateBottomRow(group.rows); - row.data[field] = group.key; - row.key = group.key; - row.rows = group.rows; + for (const [key, rows] of Object.entries(groupsByKey)) { + const row = columnCalcs.generateBottomRow(rows); + row.data[field] = key; + row.key = key; + row.rows = rows; row.generateCells(); groupTotalsRows.push(row); - }); - - const sortListActual: unknown[] = []; - //build list of valid sorters and trigger column specific callbacks before sort begins - const sorter = modules.sort; - const sortList: InternalSortItem[] = options.sortOrderReverse - ? sorter.sortList.slice().reverse() - : sorter.sortList; - sortList.forEach((item) => { - let sortObj; - - if (item.column) { - sortObj = item.column.modules.sort; - - if (sortObj) { - //if no sorter has been defined, take a guess - if (!sortObj.sorter) { - sortObj.sorter = sorter.findSorter(item.column); - } - - item.params = - typeof sortObj.params === 'function' - ? sortObj.params(item.column.getComponent(), item.dir) - : sortObj.params; - - sortListActual.push(item); - } - } - }); - - //sort data - if (sortListActual.length) { - sorter._sortItems(groupTotalsRows, sortListActual); - } else { - groupTotalsRows.sort((a, b) => { - const index = b.rows.length - a.rows.length; - if (index === 0) { - return a.key.localeCompare(b.key); - } - return index; - }); } + + groupTotalsRows = this._sortGroupTotals(groupTotalsRows); const groupValues: string[] = []; groupTotalsRows.forEach((colTotals) => { groupValues.push(colTotals.data[field] as string); }); - this.table?.setGroupValues([groupValues]); + const originalGroupVals = (options.groupValues ?? [[]])[0] ?? []; + if (!this._areGroupsEqual(groupValues, originalGroupVals)) { + this.table?.setGroupValues([groupValues]); + } + } else { + this.table?.setGroupValues([]); + } + } + + _areGroupsEqual(oldGroups: unknown[], newGroups: unknown[]) { + return ( + oldGroups && + newGroups.length === oldGroups.length && + newGroups.every((value, index) => value === oldGroups[index]) + ); + } + + _sortGroupTotals(groupTotalsRows: InternalColumnTotal[]) { + const sortListActual: unknown[] = []; + const { modules, options } = this.table; + + const sorter = modules.sort; + const sortList: InternalSortItem[] = options.sortOrderReverse + ? sorter.sortList.slice().reverse() + : sorter.sortList; + sortList.forEach((item) => { + if (item.column) { + const sortObj = item.column.modules.sort; + if (sortObj) { + //if no sorter has been defined, take a guess + if (!sortObj.sorter) { + sortObj.sorter = sorter.findSorter(item.column); + } + + item.params = + typeof sortObj.params === 'function' + ? sortObj.params(item.column.getComponent(), item.dir) + : sortObj.params; + + sortListActual.push(item); + } + } + }); + + //sort data + if (sortListActual.length) { + sorter._sortItems(groupTotalsRows, sortListActual); + } else { + groupTotalsRows.sort((a, b) => { + const index = b.rows.length - a.rows.length; + if (index === 0) { + return a.key.localeCompare(b.key); + } + return index; + }); } + return groupTotalsRows; } }