Skip to content

Commit

Permalink
Merge pull request #136 from R0tenur/toggle-view-visibility
Browse files Browse the repository at this point in the history
feat(views): toggle visibility #135
  • Loading branch information
R0tenur authored Oct 21, 2023
2 parents 0f92458 + 296469e commit 2821ebd
Show file tree
Hide file tree
Showing 23 changed files with 505 additions and 185 deletions.
1 change: 0 additions & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
"isDefault": true
},
"dependsOn": [
"Frontend Build",
]
}
]
Expand Down
27 changes: 22 additions & 5 deletions backend/__mocks__/azdata.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@


const connection = {}, ConnectionProvider = {}, dataprotocol = {}, DataProviderType = {}, QueryProvider = {}, SimpleExecuteResult = {};
const connection = {
getUriForConnection: jest.fn(),
},
ConnectionProvider = {
changeDatabase: jest.fn(),
connect: jest.fn(),
disconnect: jest.fn(),
getConnection: jest.fn(),
},
dataprotocol = {
getProvider: jest.fn(),
},
DataProviderType = {},
QueryProvider = {},
SimpleExecuteResult = {};

module.exports = {
connection, ConnectionProvider, dataprotocol, DataProviderType, QueryProvider, SimpleExecuteResult
};
connection,
ConnectionProvider,
dataprotocol,
DataProviderType,
QueryProvider,
SimpleExecuteResult,
};
3 changes: 1 addition & 2 deletions backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "schema-visualization",
"displayName": "Schema Visualization",
"description": "Erd, Er-diagram. Visualization of databases",
"version": "0.9.2",
"version": "0.9.3",
"publisher": "R0tenur",
"license": "MIT",
"icon": "logo.png",
Expand Down Expand Up @@ -40,7 +40,6 @@
"vscode:prepublish": "yarn run compile",
"compile": "tsc -p ./",
"watch": "tsc -watch -p ./",
"proposedapi": "node installTypings.js",
"pack": "vsce package",
"test": "jest --config=jest.config.js"
},
Expand Down
76 changes: 17 additions & 59 deletions backend/src/controllers/visualization.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,71 +2,29 @@
import { dashboard, DashboardWebview } from "azdata";
import { loadWebView } from "../web.loader";
import { visualizationPanelName } from "../constants";
import { getMssqlDbSchema } from "../repositories/mssql.repository";
import { chartBuilder } from "../services/builder.service";
import { Database } from "../models/database.model";
import { Status } from "../models/status.enum";
import { messageHandler } from "../message.handler";
import { getMermaidForDb, messageHandler } from "../message.handler";

let view: DashboardWebview;
export const VisualizationController = () => {
let counterHtml = loadWebView();
let counterHtml = loadWebView();

dashboard.registerWebviewProvider(
visualizationPanelName,
async (webview: DashboardWebview) => {
webview.html = counterHtml;
webview.onMessage(messageHandler);
dashboard.registerWebviewProvider(
visualizationPanelName,
async (webview: DashboardWebview) => {
view = webview;
view.html = counterHtml;
view.onMessage((m) => messageHandler(view, m));

if (webview.connection.options.database) {
await getMermaidForDb(webview);
} else {
webview.postMessage({
status: Status.NoDatabase,
});
}
}
);
};

const getMermaidForDb = async (webview: DashboardWebview) => {
webview.postMessage({
status: Status.GettingTableData,
});
try {
const database = await getMssqlDbSchema(
webview.connection.connectionId,
webview.connection.options.database);
webview.postMessage({
status: Status.BuildingChart,
databaseRaw: database.tables
});
const chart = chartBuilder(database.tables);

showResult(webview, chart, database);
} catch (error) {
showError(webview, error);
}
};

const showResult = (webview: DashboardWebview, chart: string, database: Database) => {
if (chart) {
webview.postMessage({
status: Status.Complete,
databaseName: webview.connection.options.database,
chart,
errors: database.errors,
tables: database.tables,
if (view.connection.options.database) {
await getMermaidForDb(view, {
options: { showTables: true, showViews: true },
});
} else {
webview.postMessage({
status: Status.Error,
errors: database.errors,
databaseRaw: database.tables
} else {
view.postMessage({
status: Status.NoDatabase,
});
}
}
);
};
const showError = (webview: DashboardWebview, error: Error) => webview.postMessage({
status: Status.Error,
errors: [error.message],
rawData: error.stack
});
1 change: 1 addition & 0 deletions backend/src/extension.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* istanbul ignore file */
import { ExtensionContext } from "vscode";
import { VisualizationController } from "./controllers/visualization.controller";

Expand Down
36 changes: 36 additions & 0 deletions backend/src/message.function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import { DashboardWebview } from "azdata";
import { Status } from "./models/status.enum";
import { Database } from "./models/database.model";

export const showError = (webview: DashboardWebview, error: Error) =>
webview.postMessage({
status: Status.Error,
errors: [error.message],
rawData: error.stack,
});

export const showStatus = (webview: DashboardWebview, status: string) =>
webview.postMessage({
status,
});
export const showResult = (
webview: DashboardWebview,
chart: string,
database: Database
) => {
if (chart) {
webview.postMessage({
status: Status.Complete,
databaseName: webview.connection.options.database,
chart,
errors: database.errors,
tables: database.tables,
});
} else {
webview.postMessage({
status: Status.Error,
errors: database.errors,
databaseRaw: database.tables,
});
}
};
140 changes: 107 additions & 33 deletions backend/src/message.handler.spec.ts
Original file line number Diff line number Diff line change
@@ -1,46 +1,120 @@
import { DashboardWebview } from "azdata";
import { messageHandler } from "./message.handler";
import * as exporter from "./services/export.service";
import * as messageFunction from "./message.function";
import * as repository from "./repositories/mssql.repository";
import { Status } from "./models/status.enum";
const vscode = require("../__mocks__/vscode");

const vscode = require('../__mocks__/vscode');
describe("messageHandler", () => {
const view = {
connection: {
connectionId: "id",
options: {
database: "database",
},
},
postMessage: jest.fn(),
} as unknown as DashboardWebview;
let getMssqlDbSchemaSpy;
let showErrorSpy;
let exportSpy;
let showResultSpy;
let chartBuilderSpy;

beforeEach(() => {
getMssqlDbSchemaSpy = spyOn(repository, "getMssqlDbSchema");
showErrorSpy = spyOn(messageFunction, "showError");
exportSpy = spyOn(exporter, "exportService");
showResultSpy = spyOn(messageFunction, "showResult");
chartBuilderSpy = spyOn(
require("./services/builder.service"),
"chartBuilder"
).and.returnValue("chart");
});

describe("load", () => {
it("shows error when connectionError", async () => {
// Arrange
getMssqlDbSchemaSpy.and.throwError("connectionError");

describe('exportService', () => {
// Act
await messageHandler(view, {
command: "load",
options: {},
});

it('selects value from quick pick', async () => {
// Arrange
const data = {
chart: 'svg'
};
const exportSpy = spyOn(exporter, 'exportService').and.returnValue(Promise.resolve());
spyOn(vscode.window, 'showQuickPick').and.returnValue(Promise.resolve('svg'));
// Assert
expect(showErrorSpy).toHaveBeenCalledWith(
view,
new Error("connectionError")
);
});
it("updates status when fetched tables", async () => {
// Arrange
getMssqlDbSchemaSpy.and.returnValue(Promise.resolve({ tables: [] }));

// Act
await messageHandler({
data
});
// Act
await messageHandler(view, {
command: "load",
options: {},
});

// Assert
expect(vscode.window.showQuickPick).toHaveBeenCalledWith(['svg', 'md']);
expect(exportSpy).toHaveBeenCalledWith(`chart.svg`, data, 'svg');
// Assert
expect(view.postMessage).toHaveBeenCalledWith({
status: Status.BuildingChart,
databaseRaw: [],
});
expect(chartBuilderSpy).toHaveBeenCalledWith([]);
expect(showResultSpy).toHaveBeenCalledWith(view, "chart", { tables: [] });
});
});
describe("save", () => {
it("selects value from quick pick", async () => {
// Arrange
const data = {
chart: "svg",
};
exportSpy.and.returnValue(Promise.resolve());
spyOn(vscode.window, "showQuickPick").and.returnValue(
Promise.resolve("svg")
);

// Act
await messageHandler(
{} as DashboardWebview,

{
command: "save",

it('only md aviable when svg not present', async () => {
// Arrange
const data = {
mermaid: 'dummymermaid'
};
const exportSpy = spyOn(exporter, 'exportService').and.returnValue(Promise.resolve());
spyOn(vscode.window, 'showQuickPick').and.returnValue(Promise.resolve('md'));

// Act
await messageHandler({
data
});

// Assert
expect(vscode.window.showQuickPick).toHaveBeenCalledWith(['md']);
expect(exportSpy).toHaveBeenCalledWith(`chart.md`, data, 'md');
data,
}
);

// Assert
expect(vscode.window.showQuickPick).toHaveBeenCalledWith(["svg", "md"]);
expect(exportSpy).toHaveBeenCalledWith(`chart.svg`, data, "svg");
});
});

it("only md aviable when svg not present", async () => {
// Arrange
const data = {
mermaid: "dummymermaid",
};
exportSpy.and.returnValue(Promise.resolve());
spyOn(vscode.window, "showQuickPick").and.returnValue(
Promise.resolve("md")
);

// Act
await messageHandler(view, {
command: "save",
data,
});

// Assert
expect(vscode.window.showQuickPick).toHaveBeenCalledWith(["md"]);
expect(exportSpy).toHaveBeenCalledWith(`chart.md`, data, "md");
});
});
});
53 changes: 47 additions & 6 deletions backend/src/message.handler.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,51 @@
import { window } from "vscode";
import { exportService } from "./services/export.service";
import { DashboardWebview } from "azdata";
import { Status } from "./models/status.enum";
import { getMssqlDbSchema } from "./repositories/mssql.repository";
import { chartBuilder } from "./services/builder.service";
import { showError, showResult, showStatus } from "./message.function";

export const messageHandler = async (e: any) => {
const selectable = !e.data.chart ? ['md'] : ['svg', 'md'];
await new Promise(resolve => setTimeout(resolve, 100));
const selected = await window.showQuickPick([...selectable]);
let data = e.data;
await exportService(`chart.${selected}`, data, selected);
export const messageHandler = async (view: DashboardWebview, e: any) => {
const handlers = {
save: saveHandler,
load: getMermaidForDb,
};
const handler = handlers[e.command];

if (handler) {
await handler(view, e);
}
};

export const getMermaidForDb = async (
webview: DashboardWebview,
message: any
) => {
showStatus(webview, Status.GettingTableData);

try {
const database = await getMssqlDbSchema(
webview.connection.connectionId,
webview.connection.options.database,
message.options
);
webview.postMessage({
status: Status.BuildingChart,
databaseRaw: database.tables,
});
const chart = chartBuilder(database.tables);

showResult(webview, chart, database);
} catch (error) {
showError(webview, error);
}
};

const saveHandler = async (_: DashboardWebview, e: any) => {
const selectable = !e.data.chart ? ["md"] : ["svg", "md"];
await new Promise((resolve) => setTimeout(resolve, 100));
const selected = await window.showQuickPick([...selectable]);
let data = e.data;
await exportService(`chart.${selected}`, data, selected);
};
Loading

0 comments on commit 2821ebd

Please sign in to comment.