Ensure query compare order matches expectation
A user typically expects that the first selection would be the query that they are comparing _from_ and the second query is being compared _to_. This commit ensures that something like this expectation will always hold. So, when there are two queries selected, the first one selected will always be _from_ and appear on the left side of the compare view. The one selected later will be _to_ and appear on the right. There is a corner case when there are 3 or more selected queries and a user *unselects* a query. We do not track the selection order of the remaining two queries.
This commit is contained in:
@@ -167,7 +167,7 @@ export class QueryHistoryManager {
|
||||
treeDataProvider: HistoryTreeDataProvider;
|
||||
treeView: vscode.TreeView<CompletedQuery>;
|
||||
lastItemClick: { time: Date; item: CompletedQuery } | undefined;
|
||||
|
||||
compareWithItem: CompletedQuery | undefined;
|
||||
|
||||
constructor(
|
||||
ctx: ExtensionContext,
|
||||
@@ -185,6 +185,7 @@ export class QueryHistoryManager {
|
||||
treeDataProvider,
|
||||
canSelectMany: true,
|
||||
});
|
||||
|
||||
// Lazily update the tree view selection due to limitations of TreeView API (see
|
||||
// `updateTreeViewSelectionIfVisible` doc for details)
|
||||
this.treeView.onDidChangeVisibility(async (_ev) =>
|
||||
@@ -195,6 +196,7 @@ export class QueryHistoryManager {
|
||||
if (ev.selection.length == 0) {
|
||||
this.updateTreeViewSelectionIfVisible();
|
||||
}
|
||||
this.updateCompareWith(ev.selection);
|
||||
});
|
||||
logger.log('Registering query history panel commands.');
|
||||
ctx.subscriptions.push(
|
||||
@@ -349,8 +351,8 @@ export class QueryHistoryManager {
|
||||
throw new Error('Please select a successful query.');
|
||||
}
|
||||
|
||||
const from = singleItem;
|
||||
const to = await this.findOtherQueryToCompare(singleItem, multiSelect);
|
||||
const from = this.compareWithItem || singleItem;
|
||||
const to = await this.findOtherQueryToCompare(from, multiSelect);
|
||||
|
||||
if (from && to) {
|
||||
this.doCompareCallback(from, to);
|
||||
@@ -588,4 +590,33 @@ the file in the file explorer and dragging it into the workspace.`
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the compare with source query. This ensures that all compare command invocations
|
||||
* when exactly 2 queries are selected always have the proper _from_ query. Always use
|
||||
* compareWithItem as the _from_ query.
|
||||
*
|
||||
* The heuristic is this:
|
||||
*
|
||||
* 1. If selection is empty or has length > 2 delete compareWithItem.
|
||||
* 2. If selection is length 1, then set that item to compareWithItem.
|
||||
* 3. If selection is length 2, then make sure compareWithItem is one of the selected items
|
||||
* if not, then delete compareWithItem. If it is then, do nothing.
|
||||
*
|
||||
* This ensures that compareWithItem is always the first item selected if there are only
|
||||
* two selected items.
|
||||
*
|
||||
* @param newSelection the new selection after the most recent selection change
|
||||
*/
|
||||
private updateCompareWith(newSelection: CompletedQuery[]) {
|
||||
if (newSelection.length === 1) {
|
||||
this.compareWithItem = newSelection[0];
|
||||
} else if (
|
||||
newSelection.length !== 2 ||
|
||||
!this.compareWithItem ||
|
||||
!newSelection.includes(this.compareWithItem)
|
||||
) {
|
||||
this.compareWithItem = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,6 +169,42 @@ describe('query-history', () => {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateCompareWith', () => {
|
||||
it('should update compareWithItem when there is a single item', () => {
|
||||
const queryHistory = createMockQueryHistory([]);
|
||||
queryHistory.updateCompareWith(['a']);
|
||||
expect(queryHistory.compareWithItem).to.be.eq('a');
|
||||
});
|
||||
|
||||
it('should delete compareWithItem when there are 0 items', () => {
|
||||
const queryHistory = createMockQueryHistory([]);
|
||||
queryHistory.compareWithItem = 'a';
|
||||
queryHistory.updateCompareWith([]);
|
||||
expect(queryHistory.compareWithItem).to.be.undefined;
|
||||
});
|
||||
|
||||
it('should delete compareWithItem when there are more than 2 items', () => {
|
||||
const queryHistory = createMockQueryHistory([]);
|
||||
queryHistory.compareWithItem = 'a';
|
||||
queryHistory.updateCompareWith(['a', 'b', 'c']);
|
||||
expect(queryHistory.compareWithItem).to.be.undefined;
|
||||
});
|
||||
|
||||
it('should delete compareWithItem when there are 2 items and disjoint from compareWithItem', () => {
|
||||
const queryHistory = createMockQueryHistory([]);
|
||||
queryHistory.compareWithItem = 'a';
|
||||
queryHistory.updateCompareWith(['b', 'c']);
|
||||
expect(queryHistory.compareWithItem).to.be.undefined;
|
||||
});
|
||||
|
||||
it('should do nothing when compareWithItem exists and exactly 2 items', () => {
|
||||
const queryHistory = createMockQueryHistory([]);
|
||||
queryHistory.compareWithItem = 'a';
|
||||
queryHistory.updateCompareWith(['a', 'b']);
|
||||
expect(queryHistory.compareWithItem).to.be.eq('a');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function createMockQueryHistory(allHistory: {}[]) {
|
||||
@@ -177,6 +213,8 @@ function createMockQueryHistory(allHistory: {}[]) {
|
||||
findOtherQueryToCompare: (QueryHistoryManager.prototype as any).findOtherQueryToCompare,
|
||||
treeDataProvider: {
|
||||
allHistory
|
||||
}
|
||||
},
|
||||
updateCompareWith: (QueryHistoryManager.prototype as any).updateCompareWith,
|
||||
compareWithItem: undefined as undefined | string,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user