Hook method modeling view to modeling store (#2870)

This commit is contained in:
Charis Kyriakou
2023-09-27 10:57:27 +01:00
committed by GitHub
parent 4efd3f8fe8
commit 3b00d74f47
5 changed files with 115 additions and 17 deletions

View File

@@ -599,11 +599,28 @@ export type FromModelEditorMessage =
export type FromMethodModelingMessage =
| TelemetryMessage
| UnhandledErrorMessage;
| UnhandledErrorMessage
| SetModeledMethodMessage;
interface SetMethodMessage {
t: "setMethod";
method: Method;
}
export type ToMethodModelingMessage = SetMethodMessage;
interface SetMethodModifiedMessage {
t: "setMethodModified";
isModified: boolean;
}
interface SetSelectedMethodMessage {
t: "setSelectedMethod";
method: Method;
modeledMethod: ModeledMethod;
isModified: boolean;
}
export type ToMethodModelingMessage =
| SetMethodMessage
| SetModeledMethodMessage
| SetMethodModifiedMessage
| SetSelectedMethodMessage;

View File

@@ -3,14 +3,15 @@ import { App } from "../../common/app";
import { DisposableObject } from "../../common/disposable-object";
import { MethodModelingViewProvider } from "./method-modeling-view-provider";
import { Method } from "../method";
import { ModelingStore } from "../modeling-store";
export class MethodModelingPanel extends DisposableObject {
private readonly provider: MethodModelingViewProvider;
constructor(app: App) {
constructor(app: App, modelingStore: ModelingStore) {
super();
this.provider = new MethodModelingViewProvider(app);
this.provider = new MethodModelingViewProvider(app, modelingStore);
this.push(this.provider);
this.push(
window.registerWebviewViewProvider(

View File

@@ -9,6 +9,7 @@ import { App } from "../../common/app";
import { redactableError } from "../../common/errors";
import { Method } from "../method";
import { DisposableObject } from "../../common/disposable-object";
import { ModelingStore } from "../modeling-store";
export class MethodModelingViewProvider
extends DisposableObject
@@ -18,7 +19,12 @@ export class MethodModelingViewProvider
private webviewView: vscode.WebviewView | undefined = undefined;
constructor(private readonly app: App) {
private method: Method | undefined = undefined;
constructor(
private readonly app: App,
private readonly modelingStore: ModelingStore,
) {
super();
}
@@ -51,9 +57,13 @@ export class MethodModelingViewProvider
webviewView.webview.onDidReceiveMessage(async (msg) => this.onMessage(msg));
this.webviewView = webviewView;
this.registerToModelingStoreEvents();
}
public async setMethod(method: Method): Promise<void> {
this.method = method;
if (this.webviewView) {
await this.webviewView.webview.postMessage({
t: "setMethod",
@@ -64,6 +74,18 @@ export class MethodModelingViewProvider
private async onMessage(msg: FromMethodModelingMessage): Promise<void> {
switch (msg.t) {
case "setModeledMethod": {
const activeState = this.modelingStore.getStateForActiveDb();
if (!activeState) {
throw new Error("No active state found in modeling store");
}
this.modelingStore.updateModeledMethod(
activeState.databaseItem,
msg.method,
);
break;
}
case "telemetry": {
telemetryListener?.sendUIInteraction(msg.action);
break;
@@ -79,4 +101,40 @@ export class MethodModelingViewProvider
break;
}
}
private registerToModelingStoreEvents(): void {
this.modelingStore.onModeledMethodsChanged(async (e) => {
if (this.webviewView && e.isActiveDb) {
const modeledMethod = e.modeledMethods[this.method?.signature ?? ""];
if (modeledMethod) {
await this.webviewView.webview.postMessage({
t: "setModeledMethod",
method: modeledMethod,
});
}
}
});
this.modelingStore.onModifiedMethodsChanged(async (e) => {
if (this.webviewView && e.isActiveDb && this.method) {
const isModified = e.modifiedMethods.has(this.method.signature);
await this.webviewView.webview.postMessage({
t: "setMethodModified",
isModified,
});
}
});
this.modelingStore.onSelectedMethodChanged(async (e) => {
if (this.webviewView) {
this.method = e.method;
await this.webviewView.webview.postMessage({
t: "setSelectedMethod",
method: e.method,
modeledMethod: e.modeledMethod,
isModified: e.isModified,
});
}
});
}
}

View File

@@ -42,7 +42,9 @@ export class ModelEditorModule extends DisposableObject {
this.methodsUsagePanel = this.push(
new MethodsUsagePanel(this.modelingStore, cliServer),
);
this.methodModelingPanel = this.push(new MethodModelingPanel(app));
this.methodModelingPanel = this.push(
new MethodModelingPanel(app, this.modelingStore),
);
this.registerToModelingStoreEvents();
}

View File

@@ -1,11 +1,12 @@
import * as React from "react";
import { useEffect, useState } from "react";
import { useEffect, useMemo, useState } from "react";
import { MethodModeling } from "./MethodModeling";
import { ModelingStatus } from "../../model-editor/shared/modeling-status";
import { getModelingStatus } from "../../model-editor/shared/modeling-status";
import { Method } from "../../model-editor/method";
import { ToMethodModelingMessage } from "../../common/interface-types";
import { assertNever } from "../../common/helpers-pure";
import { ModeledMethod } from "../../model-editor/modeled-method";
import { vscode } from "../vscode-api";
export function MethodModelingView(): JSX.Element {
const [method, setMethod] = useState<Method | undefined>(undefined);
@@ -14,14 +15,34 @@ export function MethodModelingView(): JSX.Element {
ModeledMethod | undefined
>(undefined);
const [isMethodModified, setIsMethodModified] = useState<boolean>(false);
const modelingStatus = useMemo(
() => getModelingStatus(modeledMethod, isMethodModified),
[modeledMethod, isMethodModified],
);
useEffect(() => {
const listener = (evt: MessageEvent) => {
if (evt.origin === window.origin) {
const msg: ToMethodModelingMessage = evt.data;
if (msg.t === "setMethod") {
setMethod(msg.method);
} else {
assertNever(msg.t);
switch (msg.t) {
case "setMethod":
setMethod(msg.method);
break;
case "setModeledMethod":
setModeledMethod(msg.method);
break;
case "setMethodModified":
setIsMethodModified(msg.isModified);
break;
case "setSelectedMethod":
setMethod(msg.method);
setModeledMethod(msg.modeledMethod);
setIsMethodModified(msg.isModified);
break;
default:
assertNever(msg);
}
} else {
// sanitize origin
@@ -40,12 +61,11 @@ export function MethodModelingView(): JSX.Element {
return <>Select method to model</>;
}
const modelingStatus: ModelingStatus = "saved";
// For now we just store the updated method in the state but soon
// we'll need to send it back to the other views.
const onChange = (modeledMethod: ModeledMethod) => {
setModeledMethod(modeledMethod);
vscode.postMessage({
t: "setModeledMethod",
method: modeledMethod,
});
};
return (