Add empty states for modeling panel (#2914)

This commit is contained in:
Charis Kyriakou
2023-10-06 09:34:54 +01:00
committed by GitHub
parent 1806108166
commit db3d24236c
11 changed files with 227 additions and 111 deletions

View File

@@ -323,6 +323,7 @@ export type PackagingCommands = {
export type ModelEditorCommands = {
"codeQL.openModelEditor": () => Promise<void>;
"codeQL.openModelEditorFromModelingPanel": () => Promise<void>;
"codeQLModelEditor.jumpToUsageLocation": (
method: Method,
usage: Usage,

View File

@@ -610,10 +610,15 @@ interface RevealInEditorMessage {
method: Method;
}
interface StartModelingMessage {
t: "startModeling";
}
export type FromMethodModelingMessage =
| CommonFromViewMessages
| SetModeledMethodMessage
| RevealInEditorMessage;
| RevealInEditorMessage
| StartModelingMessage;
interface SetMethodMessage {
t: "setMethod";

View File

@@ -13,7 +13,7 @@ export abstract class AbstractWebviewViewProvider<
private disposables: Disposable[] = [];
constructor(
private readonly app: App,
protected readonly app: App,
private readonly webviewKind: WebviewKind,
) {}

View File

@@ -92,6 +92,12 @@ export class MethodModelingViewProvider extends AbstractWebviewViewProvider<
await this.revealInModelEditor(msg.method);
break;
case "startModeling":
await this.app.commands.execute(
"codeQL.openModelEditorFromModelingPanel",
);
break;
default:
assertNever(msg);
}

View File

@@ -73,7 +73,43 @@ export class ModelEditorModule extends DisposableObject {
public getCommands(): ModelEditorCommands {
return {
"codeQL.openModelEditor": async () => {
"codeQL.openModelEditor": this.openModelEditor.bind(this),
"codeQL.openModelEditorFromModelingPanel":
this.openModelEditor.bind(this),
"codeQLModelEditor.jumpToUsageLocation": async (
method: Method,
usage: Usage,
databaseItem: DatabaseItem,
) => {
this.modelingStore.setSelectedMethod(databaseItem, method, usage);
},
};
}
private async initialize(): Promise<void> {
await ensureDir(this.queryStorageDir);
}
private registerToModelingStoreEvents(): void {
this.push(
this.modelingStore.onSelectedMethodChanged(async (event) => {
await this.showMethod(event.databaseItem, event.method, event.usage);
}),
);
}
private async showMethod(
databaseItem: DatabaseItem,
method: Method,
usage: Usage,
): Promise<void> {
await this.methodsUsagePanel.revealItem(usage);
await this.methodModelingPanel.setMethod(method);
await showResolvableLocation(usage.url, databaseItem, this.app.logger);
}
private async openModelEditor(): Promise<void> {
{
const db = this.databaseManager.currentDatabaseItem;
if (!db) {
void showAndLogErrorMessage(this.app.logger, "No database selected");
@@ -181,36 +217,6 @@ export class ModelEditorModule extends DisposableObject {
title: "Opening CodeQL Model Editor",
},
);
},
"codeQLModelEditor.jumpToUsageLocation": async (
method: Method,
usage: Usage,
databaseItem: DatabaseItem,
) => {
this.modelingStore.setSelectedMethod(databaseItem, method, usage);
},
};
}
private async initialize(): Promise<void> {
await ensureDir(this.queryStorageDir);
}
private registerToModelingStoreEvents(): void {
this.push(
this.modelingStore.onSelectedMethodChanged(async (event) => {
await this.showMethod(event.databaseItem, event.method, event.usage);
}),
);
}
private async showMethod(
databaseItem: DatabaseItem,
method: Method,
usage: Usage,
): Promise<void> {
await this.methodsUsagePanel.revealItem(usage);
await this.methodModelingPanel.setMethod(method);
await showResolvableLocation(usage.url, databaseItem, this.app.logger);
}
}

View File

@@ -0,0 +1,18 @@
import * as React from "react";
import { Meta, StoryFn } from "@storybook/react";
import { ResponsiveContainer as ResponsiveContainerComponent } from "../../view/common/ResponsiveContainer";
export default {
title: "Responsive Container",
component: ResponsiveContainerComponent,
} as Meta<typeof ResponsiveContainerComponent>;
const Template: StoryFn<typeof ResponsiveContainerComponent> = (args) => (
<ResponsiveContainerComponent>
<span>Hello</span>
</ResponsiveContainerComponent>
);
export const ResponsiveContainer = Template.bind({});

View File

@@ -0,0 +1,16 @@
import * as React from "react";
import { Meta, StoryFn } from "@storybook/react";
import { NoMethodSelected as NoMethodSelectedComponent } from "../../view/method-modeling/NoMethodSelected";
export default {
title: "Method Modeling/No Method Selected",
component: NoMethodSelectedComponent,
} as Meta<typeof NoMethodSelectedComponent>;
const Template: StoryFn<typeof NoMethodSelectedComponent> = () => (
<NoMethodSelectedComponent />
);
export const NoMethodSelected = Template.bind({});

View File

@@ -0,0 +1,16 @@
import * as React from "react";
import { Meta, StoryFn } from "@storybook/react";
import { NotInModelingMode as NotInModelingModeComponent } from "../../view/method-modeling/NotInModelingMode";
export default {
title: "Method Modeling/Not In Modeling Mode",
component: NotInModelingModeComponent,
} as Meta<typeof NotInModelingModeComponent>;
const Template: StoryFn<typeof NotInModelingModeComponent> = () => (
<NotInModelingModeComponent />
);
export const NotInModelingMode = Template.bind({});

View File

@@ -0,0 +1,15 @@
import { styled } from "styled-components";
export const ResponsiveContainer = styled.div`
display: flex;
flex-direction: column;
align-items: flex-start;
justify-content: flex-start;
height: 100vh;
@media (min-height: 300px) {
align-items: center;
justify-content: center;
text-align: center;
}
`;

View File

@@ -0,0 +1,8 @@
import * as React from "react";
import { ResponsiveContainer } from "../common/ResponsiveContainer";
export const NoMethodSelected = () => {
return (
<ResponsiveContainer>Select an API or method to model</ResponsiveContainer>
);
};

View File

@@ -0,0 +1,25 @@
import * as React from "react";
import { useCallback } from "react";
import { vscode } from "../vscode-api";
import { styled } from "styled-components";
import TextButton from "../common/TextButton";
import { ResponsiveContainer } from "../common/ResponsiveContainer";
const Button = styled(TextButton)`
margin-top: 0.2rem;
`;
export const NotInModelingMode = () => {
const handleClick = useCallback(() => {
vscode.postMessage({
t: "startModeling",
});
}, []);
return (
<ResponsiveContainer>
<span>Not in modeling mode</span>
<Button onClick={handleClick}>Start modeling</Button>
</ResponsiveContainer>
);
};