Merge pull request #3115 from github/koesie10/compare-messages

Split compare view messages
This commit is contained in:
Koen Vlaswinkel
2023-12-07 10:54:23 +01:00
committed by GitHub
6 changed files with 112 additions and 62 deletions

View File

@@ -334,13 +334,15 @@ interface ChangeCompareMessage {
newResultSetName: string;
}
export type ToCompareViewMessage = SetComparisonsMessage;
export type ToCompareViewMessage =
| SetComparisonQueryInfoMessage
| SetComparisonsMessage;
/**
* Message to the compare view that specifies the query results to compare.
* Message to the compare view that sets the metadata of the compared queries.
*/
export interface SetComparisonsMessage {
readonly t: "setComparisons";
export interface SetComparisonQueryInfoMessage {
readonly t: "setComparisonQueryInfo";
readonly stats: {
fromQuery?: {
name: string;
@@ -353,11 +355,18 @@ export interface SetComparisonsMessage {
time: string;
};
};
readonly databaseUri: string;
readonly commonResultSetNames: string[];
}
/**
* Message to the compare view that specifies the query results to compare.
*/
export interface SetComparisonsMessage {
readonly t: "setComparisons";
readonly currentResultSetName: string;
readonly result: QueryCompareResult | undefined;
readonly message: string | undefined;
readonly databaseUri: string;
}
type QueryCompareResult = RawQueryCompareResult | InterpretedQueryCompareResult;

View File

@@ -22,13 +22,18 @@ import {
import { telemetryListener } from "../common/vscode/telemetry";
import { redactableError } from "../common/errors";
import { App } from "../common/app";
import { findResultSetNames } from "./result-set-names";
import {
findCommonResultSetNames,
findResultSetNames,
} from "./result-set-names";
interface ComparePair {
from: CompletedLocalQueryInfo;
fromSchemas: BQRSInfo;
to: CompletedLocalQueryInfo;
toSchemas: BQRSInfo;
commonResultSetNames: readonly string[];
}
export class CompareView extends AbstractWebview<
@@ -62,13 +67,44 @@ export class CompareView extends AbstractWebview<
to.completedQuery.query.resultsPaths.resultsPath,
);
const commonResultSetNames = await findCommonResultSetNames(
fromSchemas,
toSchemas,
);
this.comparePair = {
from,
fromSchemas,
to,
toSchemas,
commonResultSetNames,
};
const panel = await this.getPanel();
panel.reveal(undefined, true);
await this.waitForPanelLoaded();
await this.postMessage({
t: "setComparisonQueryInfo",
stats: {
fromQuery: {
// since we split the description into several rows
// only run interpolation if the label is user-defined
// otherwise we will wind up with duplicated rows
name: this.labelProvider.getShortLabel(from),
status: from.completedQuery.statusString,
time: from.startTime,
},
toQuery: {
name: this.labelProvider.getShortLabel(to),
status: to.completedQuery.statusString,
time: to.startTime,
},
},
databaseUri: to.initialInfo.databaseInfo.databaseUri,
commonResultSetNames,
});
await this.showResultsInternal(selectedResultSetName);
}
@@ -77,21 +113,15 @@ export class CompareView extends AbstractWebview<
return;
}
const { from, to } = this.comparePair;
const panel = await this.getPanel();
panel.reveal(undefined, true);
await this.waitForPanelLoaded();
const {
commonResultSetNames,
currentResultSetDisplayName,
fromResultSet,
toResultSet,
} = await this.findResultSetsToCompare(
this.comparePair,
selectedResultSetName,
);
const { currentResultSetDisplayName, fromResultSet, toResultSet } =
await this.findResultSetsToCompare(
this.comparePair,
selectedResultSetName,
);
if (currentResultSetDisplayName) {
let result: RawQueryCompareResult | undefined;
let message: string | undefined;
@@ -103,26 +133,9 @@ export class CompareView extends AbstractWebview<
await this.postMessage({
t: "setComparisons",
stats: {
fromQuery: {
// since we split the description into several rows
// only run interpolation if the label is user-defined
// otherwise we will wind up with duplicated rows
name: this.labelProvider.getShortLabel(from),
status: from.completedQuery.statusString,
time: from.startTime,
},
toQuery: {
name: this.labelProvider.getShortLabel(to),
status: to.completedQuery.statusString,
time: to.startTime,
},
},
result,
commonResultSetNames,
currentResultSetName: currentResultSetDisplayName,
message,
databaseUri: to.initialInfo.databaseInfo.databaseUri,
});
}
}
@@ -190,15 +203,16 @@ export class CompareView extends AbstractWebview<
}
private async findResultSetsToCompare(
{ from, fromSchemas, to, toSchemas }: ComparePair,
{ from, fromSchemas, to, toSchemas, commonResultSetNames }: ComparePair,
selectedResultSetName: string | undefined,
) {
const {
commonResultSetNames,
currentResultSetDisplayName,
fromResultSetName,
toResultSetName,
} = await findResultSetNames(fromSchemas, toSchemas, selectedResultSetName);
const { currentResultSetDisplayName, fromResultSetName, toResultSetName } =
await findResultSetNames(
fromSchemas,
toSchemas,
commonResultSetNames,
selectedResultSetName,
);
const fromResultSet = await this.getResultSet(
fromSchemas,
@@ -211,7 +225,6 @@ export class CompareView extends AbstractWebview<
to.completedQuery.query.resultsPaths.resultsPath,
);
return {
commonResultSetNames,
currentResultSetDisplayName,
fromResultSet,
toResultSet,

View File

@@ -1,18 +1,28 @@
import { BQRSInfo } from "../common/bqrs-cli-types";
import { getDefaultResultSetName } from "../common/interface-types";
export async function findCommonResultSetNames(
fromSchemas: BQRSInfo,
toSchemas: BQRSInfo,
): Promise<string[]> {
const fromSchemaNames = fromSchemas["result-sets"].map(
(schema) => schema.name,
);
const toSchemaNames = toSchemas["result-sets"].map((schema) => schema.name);
return fromSchemaNames.filter((name) => toSchemaNames.includes(name));
}
export async function findResultSetNames(
fromSchemas: BQRSInfo,
toSchemas: BQRSInfo,
commonResultSetNames: readonly string[],
selectedResultSetName: string | undefined,
) {
const fromSchemaNames = fromSchemas["result-sets"].map(
(schema) => schema.name,
);
const toSchemaNames = toSchemas["result-sets"].map((schema) => schema.name);
const commonResultSetNames = fromSchemaNames.filter((name) =>
toSchemaNames.includes(name),
);
// Fall back on the default result set names if there are no common ones.
const defaultFromResultSetName = fromSchemaNames.find((name) =>
@@ -37,7 +47,6 @@ export async function findResultSetNames(
const toResultSetName = currentResultSetName || defaultToResultSetName!;
return {
commonResultSetNames,
currentResultSetDisplayName:
currentResultSetName ||
`${defaultFromResultSetName} <-> ${defaultToResultSetName}`,

View File

@@ -17,8 +17,8 @@ const Template: StoryFn<typeof CompareTableComponent> = (args) => (
export const CompareTable = Template.bind({});
CompareTable.args = {
comparison: {
t: "setComparisons",
queryInfo: {
t: "setComparisonQueryInfo",
stats: {
fromQuery: {
name: "Query built from user-controlled sources",
@@ -31,7 +31,11 @@ CompareTable.args = {
time: "8/16/2023, 3:07:21 PM",
},
},
databaseUri: "file:///java",
commonResultSetNames: ["edges", "nodes", "subpaths", "#select"],
},
comparison: {
t: "setComparisons",
currentResultSetName: "edges",
result: {
kind: "raw",
@@ -66,6 +70,5 @@ CompareTable.args = {
],
},
message: undefined,
databaseUri: "file:///java",
},
};

View File

@@ -5,12 +5,14 @@ import { styled } from "styled-components";
import {
ToCompareViewMessage,
SetComparisonsMessage,
SetComparisonQueryInfoMessage,
} from "../../common/interface-types";
import CompareSelector from "./CompareSelector";
import { vscode } from "../vscode-api";
import CompareTable from "./CompareTable";
import "../results/resultsView.css";
import { assertNever } from "../../common/helpers-pure";
const Header = styled.div`
display: flex;
@@ -25,6 +27,8 @@ const Message = styled.div`
`;
export function Compare(_: Record<string, never>): JSX.Element {
const [queryInfo, setQueryInfo] =
useState<SetComparisonQueryInfoMessage | null>(null);
const [comparison, setComparison] = useState<SetComparisonsMessage | null>(
null,
);
@@ -39,8 +43,14 @@ export function Compare(_: Record<string, never>): JSX.Element {
if (evt.origin === window.origin) {
const msg: ToCompareViewMessage = evt.data;
switch (msg.t) {
case "setComparisonQueryInfo":
setQueryInfo(msg);
break;
case "setComparisons":
setComparison(msg);
break;
default:
assertNever(msg);
}
} else {
// sanitize origin
@@ -55,7 +65,7 @@ export function Compare(_: Record<string, never>): JSX.Element {
};
}, []);
if (!comparison) {
if (!queryInfo || !comparison) {
return <div>Waiting for results to load.</div>;
}
@@ -65,7 +75,7 @@ export function Compare(_: Record<string, never>): JSX.Element {
<Header>
<HeaderTitle>Comparing:</HeaderTitle>
<CompareSelector
availableResultSets={comparison.commonResultSetNames}
availableResultSets={queryInfo.commonResultSetNames}
currentResultSetName={comparison.currentResultSetName}
updateResultSet={(newResultSetName: string) =>
vscode.postMessage({ t: "changeCompare", newResultSetName })
@@ -73,7 +83,10 @@ export function Compare(_: Record<string, never>): JSX.Element {
/>
</Header>
{hasRows ? (
<CompareTable comparison={comparison}></CompareTable>
<CompareTable
queryInfo={queryInfo}
comparison={comparison}
></CompareTable>
) : (
<Message>{message}</Message>
)}

View File

@@ -1,6 +1,9 @@
import * as React from "react";
import { SetComparisonsMessage } from "../../common/interface-types";
import {
SetComparisonQueryInfoMessage,
SetComparisonsMessage,
} from "../../common/interface-types";
import { className } from "../results/result-table-utils";
import { vscode } from "../vscode-api";
import TextButton from "../common/TextButton";
@@ -8,6 +11,7 @@ import { styled } from "styled-components";
import { RawCompareResultTable } from "./RawCompareResultTable";
interface Props {
queryInfo: SetComparisonQueryInfoMessage;
comparison: SetComparisonsMessage;
}
@@ -26,9 +30,8 @@ const Table = styled.table`
}
`;
export default function CompareTable(props: Props) {
const comparison = props.comparison;
const result = props.comparison.result!;
export default function CompareTable({ queryInfo, comparison }: Props) {
const result = comparison.result!;
async function openQuery(kind: "from" | "to") {
vscode.postMessage({
@@ -43,18 +46,18 @@ export default function CompareTable(props: Props) {
<tr>
<td>
<OpenButton onClick={() => openQuery("from")}>
{comparison.stats.fromQuery?.name}
{queryInfo.stats.fromQuery?.name}
</OpenButton>
</td>
<td>
<OpenButton onClick={() => openQuery("to")}>
{comparison.stats.toQuery?.name}
{queryInfo.stats.toQuery?.name}
</OpenButton>
</td>
</tr>
<tr>
<td>{comparison.stats.fromQuery?.time}</td>
<td>{comparison.stats.toQuery?.time}</td>
<td>{queryInfo.stats.fromQuery?.time}</td>
<td>{queryInfo.stats.toQuery?.time}</td>
</tr>
<tr>
<th>{result.from.length} rows removed</th>
@@ -69,7 +72,7 @@ export default function CompareTable(props: Props) {
columns={result.columns}
schemaName={comparison.currentResultSetName}
rows={result.from}
databaseUri={comparison.databaseUri}
databaseUri={queryInfo.databaseUri}
className={className}
/>
)}
@@ -80,7 +83,7 @@ export default function CompareTable(props: Props) {
columns={result.columns}
schemaName={comparison.currentResultSetName}
rows={result.to}
databaseUri={comparison.databaseUri}
databaseUri={queryInfo.databaseUri}
className={className}
/>
)}