Remove custom progress bar and use normal VS Code notification for progress

This commit is contained in:
Robert
2023-07-25 15:33:39 +01:00
parent b87fe94a92
commit 55b21c2add
3 changed files with 231 additions and 315 deletions

View File

@@ -500,13 +500,6 @@ interface SetExternalApiUsagesMessage {
externalApiUsages: ExternalApiUsage[];
}
export interface ShowProgressMessage {
t: "showProgress";
step: number;
maxStep: number;
message: string;
}
interface LoadModeledMethodsMessage {
t: "loadModeledMethods";
modeledMethods: Record<string, ModeledMethod>;
@@ -558,7 +551,6 @@ interface ModelDependencyMessage {
export type ToDataExtensionsEditorMessage =
| SetExtensionPackStateMessage
| SetExternalApiUsagesMessage
| ShowProgressMessage
| LoadModeledMethodsMessage
| AddModeledMethodsMessage;

View File

@@ -14,11 +14,7 @@ import {
FromDataExtensionsEditorMessage,
ToDataExtensionsEditorMessage,
} from "../common/interface-types";
import {
ProgressCallback,
ProgressUpdate,
withProgress,
} from "../common/vscode/progress";
import { ProgressCallback, withProgress } from "../common/vscode/progress";
import { QueryRunner } from "../query-server";
import {
showAndLogExceptionWithTelemetry,
@@ -225,9 +221,10 @@ export class DataExtensionsEditorView extends AbstractWebview<
}
protected async loadExternalApiUsages(): Promise<void> {
const cancellationTokenSource = new CancellationTokenSource();
await withProgress(
async (progress) => {
try {
const cancellationTokenSource = new CancellationTokenSource();
const queryResult = await runQuery(
this.mode === Mode.Framework
? "frameworkModeQuery"
@@ -237,18 +234,15 @@ export class DataExtensionsEditorView extends AbstractWebview<
queryRunner: this.queryRunner,
databaseItem: this.databaseItem,
queryStorageDir: this.queryStorageDir,
progress: (progressUpdate: ProgressUpdate) => {
void this.showProgress(progressUpdate, 1500);
},
progress: (update) => progress({ ...update, maxStep: 1500 }),
token: cancellationTokenSource.token,
},
);
if (!queryResult) {
await this.clearProgress();
return;
}
await this.showProgress({
progress({
message: "Decoding results",
step: 1100,
maxStep: 1500,
@@ -259,11 +253,10 @@ export class DataExtensionsEditorView extends AbstractWebview<
bqrsPath: queryResult.outputDir.bqrsPath,
});
if (!bqrsChunk) {
await this.clearProgress();
return;
}
await this.showProgress({
progress({
message: "Finalizing results",
step: 1450,
maxStep: 1500,
@@ -275,8 +268,6 @@ export class DataExtensionsEditorView extends AbstractWebview<
t: "setExternalApiUsages",
externalApiUsages,
});
await this.clearProgress();
} catch (err) {
void showAndLogExceptionWithTelemetry(
this.app.logger,
@@ -286,9 +277,14 @@ export class DataExtensionsEditorView extends AbstractWebview<
)`Failed to load external API usages: ${getErrorMessage(err)}`,
);
}
},
{ cancellable: false },
);
}
protected async generateModeledMethods(): Promise<void> {
await withProgress(
async (progress) => {
const tokenSource = new CancellationTokenSource();
let addedDatabase: DatabaseItem | undefined;
@@ -296,15 +292,13 @@ export class DataExtensionsEditorView extends AbstractWebview<
// In application mode, we need the database of a specific library to generate
// the modeled methods. In framework mode, we'll use the current database.
if (this.mode === Mode.Application) {
addedDatabase = await this.promptImportDatabase((update) =>
this.showProgress(update),
);
addedDatabase = await this.promptImportDatabase(progress);
if (!addedDatabase) {
return;
}
}
await this.showProgress({
progress({
step: 0,
maxStep: 4000,
message: "Generating modeled methods for library",
@@ -328,7 +322,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
modeledMethods: modeledMethodsByName,
});
},
progress: (update) => this.showProgress(update),
progress,
token: tokenSource.token,
});
} catch (e: unknown) {
@@ -344,24 +338,27 @@ export class DataExtensionsEditorView extends AbstractWebview<
if (addedDatabase) {
// After the flow model has been generated, we can remove the temporary database
// which we used for generating the flow model.
await this.showProgress({
progress({
step: 3900,
maxStep: 4000,
message: "Removing temporary database",
});
await this.databaseManager.removeDatabaseItem(addedDatabase);
}
await this.clearProgress();
},
{ cancellable: false },
);
}
private async generateModeledMethodsFromLlm(
externalApiUsages: ExternalApiUsage[],
modeledMethods: Record<string, ModeledMethod>,
): Promise<void> {
await withProgress(
async (progress) => {
const maxStep = 3000;
await this.showProgress({
progress({
step: 0,
maxStep,
message: "Retrieving usages",
@@ -372,10 +369,10 @@ export class DataExtensionsEditorView extends AbstractWebview<
queryRunner: this.queryRunner,
queryStorageDir: this.queryStorageDir,
databaseItem: this.databaseItem,
progress: (update) => this.showProgress(update, maxStep),
progress: (update) => progress({ ...update, maxStep }),
});
await this.showProgress({
progress({
step: 1800,
maxStep,
message: "Creating request",
@@ -389,7 +386,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
this.mode,
);
await this.showProgress({
progress({
step: 2000,
maxStep,
message: "Sending request",
@@ -400,7 +397,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
return;
}
await this.showProgress({
progress({
step: 2500,
maxStep,
message: "Parsing response",
@@ -410,7 +407,7 @@ export class DataExtensionsEditorView extends AbstractWebview<
response.predicted || [],
);
await this.showProgress({
progress({
step: 2800,
maxStep,
message: "Applying results",
@@ -420,8 +417,9 @@ export class DataExtensionsEditorView extends AbstractWebview<
t: "addModeledMethods",
modeledMethods: predictedModeledMethods,
});
await this.clearProgress();
},
{ cancellable: false },
);
}
private async modelDependency(): Promise<void> {
@@ -482,46 +480,12 @@ export class DataExtensionsEditorView extends AbstractWebview<
return addedDatabase;
}
/*
* Progress in this class is a bit weird. Most of the progress is based on running the query.
* Query progress is always between 0 and 1000. However, we still have some steps that need
* to be done after the query has finished. Therefore, the maximum step is 1500. This captures
* that there's 1000 steps of the query progress since that takes the most time, and then
* an additional 500 steps for the rest of the work. The progress doesn't need to be 100%
* accurate, so this is just a rough estimate.
*
* For generating the modeled methods for an external library, the max step is 4000. This is
* based on the following steps:
* - 1000 for the summary model
* - 1000 for the sink model
* - 1000 for the source model
* - 1000 for the neutral model
*/
private async showProgress(update: ProgressUpdate, maxStep?: number) {
await this.postMessage({
t: "showProgress",
step: update.step,
maxStep: maxStep ?? update.maxStep,
message: update.message,
});
}
private async clearProgress() {
await this.showProgress({
step: 0,
maxStep: 0,
message: "",
});
}
private async callAutoModelApi(
request: ModelRequest,
): Promise<ModelResponse | null> {
try {
return await autoModel(this.app.credentials, request);
} catch (e) {
await this.clearProgress();
if (e instanceof RequestError && e.status === 429) {
void showAndLogExceptionWithTelemetry(
this.app.logger,

View File

@@ -1,9 +1,6 @@
import * as React from "react";
import { useCallback, useEffect, useMemo, useState } from "react";
import {
ShowProgressMessage,
ToDataExtensionsEditorMessage,
} from "../../common/interface-types";
import { ToDataExtensionsEditorMessage } from "../../common/interface-types";
import { VSCodeButton } from "@vscode/webview-ui-toolkit/react";
import styled from "styled-components";
import { ExternalApiUsage } from "../../data-extensions-editor/external-api-usage";
@@ -46,17 +43,6 @@ const ButtonsContainer = styled.div`
margin-bottom: 1rem;
`;
type ProgressBarProps = {
completion: number;
};
const ProgressBar = styled.div<ProgressBarProps>`
height: 10px;
width: ${(props) => props.completion * 100}%;
background-color: var(--vscode-progressBar-background);
`;
type Props = {
initialViewState?: DataExtensionEditorViewState;
initialExternalApiUsages?: ExternalApiUsage[];
@@ -82,11 +68,6 @@ export function DataExtensionsEditor({
const [modeledMethods, setModeledMethods] = useState<
Record<string, ModeledMethod>
>(initialModeledMethods);
const [progress, setProgress] = useState<Omit<ShowProgressMessage, "t">>({
step: 0,
maxStep: 0,
message: "",
});
useEffect(() => {
const listener = (evt: MessageEvent) => {
@@ -99,9 +80,6 @@ export function DataExtensionsEditor({
case "setExternalApiUsages":
setExternalApiUsages(msg.externalApiUsages);
break;
case "showProgress":
setProgress(msg);
break;
case "loadModeledMethods":
setModeledMethods((oldModeledMethods) => {
return {
@@ -244,21 +222,12 @@ export function DataExtensionsEditor({
});
}, [viewState?.mode]);
if (viewState === undefined) {
if (viewState === undefined || externalApiUsages.length === 0) {
return <LoadingContainer>Loading...</LoadingContainer>;
}
return (
<DataExtensionsEditorContainer>
{progress.maxStep > 0 && (
<p>
<ProgressBar completion={progress.step / progress.maxStep} />{" "}
{progress.message}
</p>
)}
{externalApiUsages.length > 0 && (
<>
<ViewTitle>
{getLanguageDisplayName(viewState.extensionPack.language)}
</ViewTitle>
@@ -267,9 +236,7 @@ export function DataExtensionsEditor({
<span slot="start" className="codicon codicon-package"></span>
{viewState.extensionPack.name}
</LinkIconButton>
<div>
{percentFormatter.format(modeledPercentage / 100)} modeled
</div>
<div>{percentFormatter.format(modeledPercentage / 100)} modeled</div>
<div>
{percentFormatter.format(unModeledPercentage / 100)} unmodeled
</div>
@@ -277,16 +244,11 @@ export function DataExtensionsEditor({
<>
<div>
Mode:{" "}
{viewState.mode === Mode.Framework
? "Framework"
: "Application"}
{viewState.mode === Mode.Framework ? "Framework" : "Application"}
</div>
<div>
<LinkIconButton onClick={onSwitchModeClick}>
<span
slot="start"
className="codicon codicon-library"
></span>
<span slot="start" className="codicon codicon-library"></span>
Switch mode
</LinkIconButton>
</div>
@@ -325,8 +287,6 @@ export function DataExtensionsEditor({
onModelDependencyClick={onModelDependencyClick}
/>
</EditorContainer>
</>
)}
</DataExtensionsEditorContainer>
);
}