From 23abc5de0d32ca9d97cfb6f64b7dbbdb4e3ebb73 Mon Sep 17 00:00:00 2001 From: Koen Vlaswinkel Date: Tue, 18 Apr 2023 15:47:18 +0200 Subject: [PATCH] Hide link when model file does not exist This removes the link to the model file when it does not exist. It will still show the filename of the model file. When clicking on "Apply", it will refresh whether the model file exists after writing the file. --- .../data-extensions-editor-view.ts | 20 ++++--- .../extension-pack-picker.ts | 17 +----- .../shared/extension-pack.ts | 15 +++++ .../shared/view-state.ts | 6 ++ .../ql-vscode/src/pure/interface-types.ts | 10 ++-- .../DataExtensionsEditor.stories.tsx | 19 +++++- .../DataExtensionsEditor.tsx | 59 +++++++++++-------- .../extension-pack-picker.test.ts | 6 +- 8 files changed, 93 insertions(+), 59 deletions(-) create mode 100644 extensions/ql-vscode/src/data-extensions-editor/shared/extension-pack.ts create mode 100644 extensions/ql-vscode/src/data-extensions-editor/shared/view-state.ts diff --git a/extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts b/extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts index 508641c1b2e..e58d6c21df5 100644 --- a/extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts +++ b/extensions/ql-vscode/src/data-extensions-editor/data-extensions-editor-view.ts @@ -35,7 +35,7 @@ import { readQueryResults, runQuery } from "./external-api-usage-query"; import { createDataExtensionYaml, loadDataExtensionYaml } from "./yaml"; import { ExternalApiUsage } from "./external-api-usage"; import { ModeledMethod } from "./modeled-method"; -import { ExtensionPackModelFile } from "./extension-pack-picker"; +import { ExtensionPackModelFile } from "./shared/extension-pack"; function getQlSubmoduleFolder(): WorkspaceFolder | undefined { const workspaceFolder = workspace.workspaceFolders?.find( @@ -118,7 +118,7 @@ export class DataExtensionsEditorView extends AbstractWebview< msg.externalApiUsages, msg.modeledMethods, ); - await this.loadExternalApiUsages(); + await Promise.all([this.setViewState(), this.loadExternalApiUsages()]); break; case "generateExternalApi": @@ -134,16 +134,22 @@ export class DataExtensionsEditorView extends AbstractWebview< super.onWebViewLoaded(); await Promise.all([ - this.postMessage({ - t: "setDataExtensionEditorInitialData", - extensionPackName: this.modelFile.extensionPack.name, - modelFilename: this.modelFile.filename, - }), + this.setViewState(), this.loadExternalApiUsages(), this.loadExistingModeledMethods(), ]); } + private async setViewState(): Promise { + await this.postMessage({ + t: "setDataExtensionEditorViewState", + viewState: { + extensionPackModelFile: this.modelFile, + modelFileExists: await pathExists(this.modelFile.filename), + }, + }); + } + protected async jumpToUsage( location: ResolvableLocationValue, ): Promise { diff --git a/extensions/ql-vscode/src/data-extensions-editor/extension-pack-picker.ts b/extensions/ql-vscode/src/data-extensions-editor/extension-pack-picker.ts index b0d102c6e6f..dc2c4969af0 100644 --- a/extensions/ql-vscode/src/data-extensions-editor/extension-pack-picker.ts +++ b/extensions/ql-vscode/src/data-extensions-editor/extension-pack-picker.ts @@ -13,6 +13,7 @@ import { ProgressCallback } from "../progress"; import { DatabaseItem } from "../local-databases"; import { getQlPackPath, QLPACK_FILENAMES } from "../pure/ql"; import { getErrorMessage } from "../pure/helpers-pure"; +import { ExtensionPack, ExtensionPackModelFile } from "./shared/extension-pack"; const maxStep = 3; @@ -22,22 +23,6 @@ const packNameRegex = new RegExp( ); const packNameLength = 128; -export interface ExtensionPack { - path: string; - yamlPath: string; - - name: string; - version: string; - - extensionTargets: Record; - dataExtensions: string[]; -} - -export interface ExtensionPackModelFile { - filename: string; - extensionPack: ExtensionPack; -} - export async function pickExtensionPackModelFile( cliServer: Pick, databaseItem: Pick, diff --git a/extensions/ql-vscode/src/data-extensions-editor/shared/extension-pack.ts b/extensions/ql-vscode/src/data-extensions-editor/shared/extension-pack.ts new file mode 100644 index 00000000000..7ac80099327 --- /dev/null +++ b/extensions/ql-vscode/src/data-extensions-editor/shared/extension-pack.ts @@ -0,0 +1,15 @@ +export interface ExtensionPack { + path: string; + yamlPath: string; + + name: string; + version: string; + + extensionTargets: Record; + dataExtensions: string[]; +} + +export interface ExtensionPackModelFile { + filename: string; + extensionPack: ExtensionPack; +} diff --git a/extensions/ql-vscode/src/data-extensions-editor/shared/view-state.ts b/extensions/ql-vscode/src/data-extensions-editor/shared/view-state.ts new file mode 100644 index 00000000000..0da3f0d2588 --- /dev/null +++ b/extensions/ql-vscode/src/data-extensions-editor/shared/view-state.ts @@ -0,0 +1,6 @@ +import { ExtensionPackModelFile } from "./extension-pack"; + +export interface DataExtensionEditorViewState { + extensionPackModelFile: ExtensionPackModelFile; + modelFileExists: boolean; +} diff --git a/extensions/ql-vscode/src/pure/interface-types.ts b/extensions/ql-vscode/src/pure/interface-types.ts index 6dda76926b6..0dcfc0fd937 100644 --- a/extensions/ql-vscode/src/pure/interface-types.ts +++ b/extensions/ql-vscode/src/pure/interface-types.ts @@ -16,6 +16,7 @@ import { ErrorLike } from "./errors"; import { DataFlowPaths } from "../variant-analysis/shared/data-flow-paths"; import { ExternalApiUsage } from "../data-extensions-editor/external-api-usage"; import { ModeledMethod } from "../data-extensions-editor/modeled-method"; +import { DataExtensionEditorViewState } from "../data-extensions-editor/shared/view-state"; /** * This module contains types and code that are shared between @@ -481,10 +482,9 @@ export type ToDataFlowPathsMessage = SetDataFlowPathsMessage; export type FromDataFlowPathsMessage = CommonFromViewMessages; -export interface SetDataExtensionEditorInitialDataMessage { - t: "setDataExtensionEditorInitialData"; - extensionPackName: string; - modelFilename: string; +export interface SetExtensionPackStateMessage { + t: "setDataExtensionEditorViewState"; + viewState: DataExtensionEditorViewState; } export interface SetExternalApiUsagesMessage { @@ -536,7 +536,7 @@ export interface GenerateExternalApiMessage { } export type ToDataExtensionsEditorMessage = - | SetDataExtensionEditorInitialDataMessage + | SetExtensionPackStateMessage | SetExternalApiUsagesMessage | ShowProgressMessage | AddModeledMethodsMessage; diff --git a/extensions/ql-vscode/src/stories/data-extensions-editor/DataExtensionsEditor.stories.tsx b/extensions/ql-vscode/src/stories/data-extensions-editor/DataExtensionsEditor.stories.tsx index 46b10ff5c77..3df104db76d 100644 --- a/extensions/ql-vscode/src/stories/data-extensions-editor/DataExtensionsEditor.stories.tsx +++ b/extensions/ql-vscode/src/stories/data-extensions-editor/DataExtensionsEditor.stories.tsx @@ -15,9 +15,22 @@ const Template: ComponentStory = ( export const DataExtensionsEditor = Template.bind({}); DataExtensionsEditor.args = { - initialExtensionPackName: "codeql/sql2o-models", - initialModelFilename: - "/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o/models/sql2o.yml", + initialViewState: { + extensionPackModelFile: { + extensionPack: { + path: "/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o", + yamlPath: + "/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o/codeql-pack.yml", + name: "codeql/sql2o-models", + version: "0.0.0", + extensionTargets: {}, + dataExtensions: [], + }, + filename: + "/home/user/vscode-codeql-starter/codeql-custom-queries-java/sql2o/models/sql2o.yml", + }, + modelFileExists: true, + }, initialExternalApiUsages: [ { signature: "org.sql2o.Connection#createQuery(String)", diff --git a/extensions/ql-vscode/src/view/data-extensions-editor/DataExtensionsEditor.tsx b/extensions/ql-vscode/src/view/data-extensions-editor/DataExtensionsEditor.tsx index 129f69f3683..592625e5f36 100644 --- a/extensions/ql-vscode/src/view/data-extensions-editor/DataExtensionsEditor.tsx +++ b/extensions/ql-vscode/src/view/data-extensions-editor/DataExtensionsEditor.tsx @@ -20,6 +20,7 @@ import { calculateModeledPercentage } from "./modeled"; import { LinkIconButton } from "../variant-analysis/LinkIconButton"; import { basename } from "../common/path"; import { ViewTitle } from "../common"; +import { DataExtensionEditorViewState } from "../../data-extensions-editor/shared/view-state"; const DataExtensionsEditorContainer = styled.div` margin-top: 1rem; @@ -31,6 +32,12 @@ const DetailsContainer = styled.div` align-items: center; `; +const NonExistingModelFileContainer = styled.div` + display: flex; + gap: 0.2em; + align-items: center; +`; + const EditorContainer = styled.div` margin-top: 1rem; `; @@ -47,24 +54,19 @@ const ProgressBar = styled.div` `; type Props = { - initialExtensionPackName?: string; - initialModelFilename?: string; + initialViewState?: DataExtensionEditorViewState; initialExternalApiUsages?: ExternalApiUsage[]; initialModeledMethods?: Record; }; export function DataExtensionsEditor({ - initialExtensionPackName, - initialModelFilename, + initialViewState, initialExternalApiUsages = [], initialModeledMethods = {}, }: Props): JSX.Element { - const [extensionPackName, setExtensionPackName] = useState< - string | undefined - >(initialExtensionPackName); - const [modelFilename, setModelFilename] = useState( - initialModelFilename, - ); + const [viewState, setViewState] = useState< + DataExtensionEditorViewState | undefined + >(initialViewState); const [externalApiUsages, setExternalApiUsages] = useState< ExternalApiUsage[] @@ -83,9 +85,8 @@ export function DataExtensionsEditor({ if (evt.origin === window.origin) { const msg: ToDataExtensionsEditorMessage = evt.data; switch (msg.t) { - case "setDataExtensionEditorInitialData": - setExtensionPackName(msg.extensionPackName); - setModelFilename(msg.modelFilename); + case "setDataExtensionEditorViewState": + setViewState(msg.viewState); break; case "setExternalApiUsages": setExternalApiUsages(msg.externalApiUsages); @@ -181,17 +182,27 @@ export function DataExtensionsEditor({ <> Data extensions editor - {extensionPackName && ( - - - {extensionPackName} - - )} - {modelFilename && ( - - - {basename(modelFilename)} - + {viewState?.extensionPackModelFile && ( + <> + + + {viewState.extensionPackModelFile.extensionPack.name} + + {viewState.modelFileExists ? ( + + + {basename(viewState.extensionPackModelFile.filename)} + + ) : ( + + + {basename(viewState.extensionPackModelFile.filename)} + + )} + )}
{modeledPercentage.toFixed(2)}% modeled
{unModeledPercentage.toFixed(2)}% unmodeled
diff --git a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/extension-pack-picker.test.ts b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/extension-pack-picker.test.ts index 80662b0a3ce..708b4a4cec2 100644 --- a/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/extension-pack-picker.test.ts +++ b/extensions/ql-vscode/test/vscode-tests/no-workspace/data-extensions-editor/extension-pack-picker.test.ts @@ -6,10 +6,8 @@ import { dir } from "tmp-promise"; import { QlpacksInfo, ResolveExtensionsResult } from "../../../../src/cli"; import * as helpers from "../../../../src/helpers"; -import { - ExtensionPack, - pickExtensionPackModelFile, -} from "../../../../src/data-extensions-editor/extension-pack-picker"; +import { pickExtensionPackModelFile } from "../../../../src/data-extensions-editor/extension-pack-picker"; +import { ExtensionPack } from "../../../../src/data-extensions-editor/shared/extension-pack"; describe("pickExtensionPackModelFile", () => { let tmpDir: string;