Wire up modeling panel empty states (#2915)

This commit is contained in:
Charis Kyriakou
2023-10-06 11:27:16 +01:00
committed by GitHub
parent b1df4a4f0a
commit 20c63921f7
6 changed files with 65 additions and 38 deletions

View File

@@ -1996,7 +1996,7 @@
"id": "codeQLMethodModeling", "id": "codeQLMethodModeling",
"type": "webview", "type": "webview",
"name": "CodeQL Method Modeling", "name": "CodeQL Method Modeling",
"when": "config.codeQL.canary && config.codeQL.model.methodModelingView && codeql.modelEditorOpen && !codeql.modelEditorActive" "when": "config.codeQL.canary && config.codeQL.model.methodModelingView"
} }
], ],
"codeql-methods-usage": [ "codeql-methods-usage": [

View File

@@ -577,6 +577,11 @@ interface SetModeledMethodMessage {
method: ModeledMethod; method: ModeledMethod;
} }
interface SetInModelingModeMessage {
t: "setInModelingMode";
inModelingMode: boolean;
}
interface RevealMethodMessage { interface RevealMethodMessage {
t: "revealMethod"; t: "revealMethod";
method: Method; method: Method;
@@ -641,4 +646,5 @@ export type ToMethodModelingMessage =
| SetMethodMessage | SetMethodMessage
| SetModeledMethodMessage | SetModeledMethodMessage
| SetMethodModifiedMessage | SetMethodModifiedMessage
| SetSelectedMethodMessage; | SetSelectedMethodMessage
| SetInModelingModeMessage;

View File

@@ -46,14 +46,16 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
} }
private setInitialState(): void { private setInitialState(): void {
const selectedMethod = this.modelingStore.getSelectedMethodDetails(); if (this.modelingStore.hasStateForActiveDb()) {
if (selectedMethod) { const selectedMethod = this.modelingStore.getSelectedMethodDetails();
void this.postMessage({ if (selectedMethod) {
t: "setSelectedMethod", void this.postMessage({
method: selectedMethod.method, t: "setSelectedMethod",
modeledMethod: selectedMethod.modeledMethod, method: selectedMethod.method,
isModified: selectedMethod.isModified, modeledMethod: selectedMethod.modeledMethod,
}); isModified: selectedMethod.isModified,
});
}
} }
} }
@@ -165,5 +167,25 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
} }
}), }),
); );
this.push(
this.modelingStore.onDbOpened(async () => {
await this.postMessage({
t: "setInModelingMode",
inModelingMode: true,
});
}),
);
this.push(
this.modelingStore.onDbClosed(async () => {
if (!this.modelingStore.anyDbsBeingModeled()) {
await this.postMessage({
t: "setInModelingMode",
inModelingMode: false,
});
}
}),
);
} }
} }

View File

@@ -100,9 +100,6 @@ export class ModelEditorView extends AbstractWebview<
panel.onDidChangeViewState(async () => { panel.onDidChangeViewState(async () => {
if (panel.active) { if (panel.active) {
this.modelingStore.setActiveDb(this.databaseItem); this.modelingStore.setActiveDb(this.databaseItem);
await this.markModelEditorAsActive();
} else {
await this.updateModelEditorActiveContext();
} }
}); });
@@ -126,36 +123,12 @@ export class ModelEditorView extends AbstractWebview<
); );
} }
private async markModelEditorAsActive(): Promise<void> {
void this.app.commands.execute(
"setContext",
"codeql.modelEditorActive",
true,
);
}
private async updateModelEditorActiveContext(): Promise<void> {
await this.app.commands.execute(
"setContext",
"codeql.modelEditorActive",
this.isAModelEditorActive(),
);
}
private isAModelEditorOpen(): boolean { private isAModelEditorOpen(): boolean {
return window.tabGroups.all.some((tabGroup) => return window.tabGroups.all.some((tabGroup) =>
tabGroup.tabs.some((tab) => this.isTabModelEditorView(tab)), tabGroup.tabs.some((tab) => this.isTabModelEditorView(tab)),
); );
} }
private isAModelEditorActive(): boolean {
return window.tabGroups.all.some((tabGroup) =>
tabGroup.tabs.some(
(tab) => this.isTabModelEditorView(tab) && tab.isActive,
),
);
}
private isTabModelEditorView(tab: Tab): boolean { private isTabModelEditorView(tab: Tab): boolean {
if (!(tab.input instanceof TabInputWebview)) { if (!(tab.input instanceof TabInputWebview)) {
return false; return false;

View File

@@ -49,6 +49,7 @@ interface SelectedMethodChangedEvent {
export class ModelingStore extends DisposableObject { export class ModelingStore extends DisposableObject {
public readonly onActiveDbChanged: AppEvent<void>; public readonly onActiveDbChanged: AppEvent<void>;
public readonly onDbOpened: AppEvent<string>;
public readonly onDbClosed: AppEvent<string>; public readonly onDbClosed: AppEvent<string>;
public readonly onMethodsChanged: AppEvent<MethodsChangedEvent>; public readonly onMethodsChanged: AppEvent<MethodsChangedEvent>;
public readonly onHideModeledMethodsChanged: AppEvent<HideModeledMethodsChangedEvent>; public readonly onHideModeledMethodsChanged: AppEvent<HideModeledMethodsChangedEvent>;
@@ -60,6 +61,7 @@ export class ModelingStore extends DisposableObject {
private activeDb: string | undefined; private activeDb: string | undefined;
private readonly onActiveDbChangedEventEmitter: AppEventEmitter<void>; private readonly onActiveDbChangedEventEmitter: AppEventEmitter<void>;
private readonly onDbOpenedEventEmitter: AppEventEmitter<string>;
private readonly onDbClosedEventEmitter: AppEventEmitter<string>; private readonly onDbClosedEventEmitter: AppEventEmitter<string>;
private readonly onMethodsChangedEventEmitter: AppEventEmitter<MethodsChangedEvent>; private readonly onMethodsChangedEventEmitter: AppEventEmitter<MethodsChangedEvent>;
private readonly onHideModeledMethodsChangedEventEmitter: AppEventEmitter<HideModeledMethodsChangedEvent>; private readonly onHideModeledMethodsChangedEventEmitter: AppEventEmitter<HideModeledMethodsChangedEvent>;
@@ -79,6 +81,9 @@ export class ModelingStore extends DisposableObject {
); );
this.onActiveDbChanged = this.onActiveDbChangedEventEmitter.event; this.onActiveDbChanged = this.onActiveDbChangedEventEmitter.event;
this.onDbOpenedEventEmitter = this.push(app.createEventEmitter<string>());
this.onDbOpened = this.onDbOpenedEventEmitter.event;
this.onDbClosedEventEmitter = this.push(app.createEventEmitter<string>()); this.onDbClosedEventEmitter = this.push(app.createEventEmitter<string>());
this.onDbClosed = this.onDbClosedEventEmitter.event; this.onDbClosed = this.onDbClosedEventEmitter.event;
@@ -123,6 +128,8 @@ export class ModelingStore extends DisposableObject {
selectedMethod: undefined, selectedMethod: undefined,
selectedUsage: undefined, selectedUsage: undefined,
}); });
this.onDbOpenedEventEmitter.fire(dbUri);
} }
public setActiveDb(databaseItem: DatabaseItem) { public setActiveDb(databaseItem: DatabaseItem) {
@@ -154,6 +161,14 @@ export class ModelingStore extends DisposableObject {
return this.state.get(this.activeDb); return this.state.get(this.activeDb);
} }
public hasStateForActiveDb(): boolean {
return !!this.getStateForActiveDb();
}
public anyDbsBeingModeled(): boolean {
return this.state.size > 0;
}
public setMethods(dbItem: DatabaseItem, methods: Method[]) { public setMethods(dbItem: DatabaseItem, methods: Method[]) {
const dbState = this.getState(dbItem); const dbState = this.getState(dbItem);
const dbUri = dbItem.databaseUri.toString(); const dbUri = dbItem.databaseUri.toString();

View File

@@ -7,8 +7,12 @@ import { ToMethodModelingMessage } from "../../common/interface-types";
import { assertNever } from "../../common/helpers-pure"; import { assertNever } from "../../common/helpers-pure";
import { ModeledMethod } from "../../model-editor/modeled-method"; import { ModeledMethod } from "../../model-editor/modeled-method";
import { vscode } from "../vscode-api"; import { vscode } from "../vscode-api";
import { NotInModelingMode } from "./NotInModelingMode";
import { NoMethodSelected } from "./NoMethodSelected";
export function MethodModelingView(): JSX.Element { export function MethodModelingView(): JSX.Element {
const [inModelingMode, setInModelingMode] = useState<boolean>(false);
const [method, setMethod] = useState<Method | undefined>(undefined); const [method, setMethod] = useState<Method | undefined>(undefined);
const [modeledMethod, setModeledMethod] = React.useState< const [modeledMethod, setModeledMethod] = React.useState<
@@ -27,6 +31,9 @@ export function MethodModelingView(): JSX.Element {
if (evt.origin === window.origin) { if (evt.origin === window.origin) {
const msg: ToMethodModelingMessage = evt.data; const msg: ToMethodModelingMessage = evt.data;
switch (msg.t) { switch (msg.t) {
case "setInModelingMode":
setInModelingMode(msg.inModelingMode);
break;
case "setMethod": case "setMethod":
setMethod(msg.method); setMethod(msg.method);
break; break;
@@ -57,8 +64,12 @@ export function MethodModelingView(): JSX.Element {
}; };
}, []); }, []);
if (!inModelingMode) {
return <NotInModelingMode />;
}
if (!method) { if (!method) {
return <>Select method to model</>; return <NoMethodSelected />;
} }
const onChange = (modeledMethod: ModeledMethod) => { const onChange = (modeledMethod: ModeledMethod) => {