diff --git a/package.json b/package.json index 61cd91da..98954665 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "onCommand:kdb.newConnection.editInsightsConnection", "onCommand:kdb.newConnection.editMyQConnection", "onCommand:kdb.newConnection.editBundledConnection", + "onCommand:kdb.labels.create", "onView:kdb-datasources-explorer", "onTerminalProfile:kdb.q-terminal", "onLanguage:python" @@ -179,6 +180,18 @@ "description": "Connection map for workspace files", "default": {}, "scope": "resource" + }, + "kdb.connectionLabels": { + "type": "array", + "description": "List of label names and colorset", + "default": [], + "scope": "resource" + }, + "kdb.labelsConnectionMap": { + "type": "array", + "description": "Labels connection map", + "default": [], + "scope": "resource" } } }, diff --git a/src/commands/serverCommand.ts b/src/commands/serverCommand.ts index 68379855..2e9b6ddc 100644 --- a/src/commands/serverCommand.ts +++ b/src/commands/serverCommand.ts @@ -67,6 +67,7 @@ import { Telemetry } from "../utils/telemetryClient"; import { ConnectionManagementService } from "../services/connectionManagerService"; import { InsightsConnection } from "../classes/insightsConnection"; import { MetaContentProvider } from "../services/metaContentProvider"; +import { handleLabelsConnMap } from "../utils/connLabel"; export async function addNewConnection(): Promise { NewConnectionPannel.close(); @@ -78,7 +79,10 @@ export async function editConnection(viewItem: KdbNode | InsightsNode) { NewConnectionPannel.render(ext.context.extensionUri, viewItem); } -export async function addInsightsConnection(insightsData: InsightDetails) { +export async function addInsightsConnection( + insightsData: InsightDetails, + labels?: string[], +) { const aliasValidation = validateServerAlias(insightsData.alias, false); if (aliasValidation) { window.showErrorMessage(aliasValidation); @@ -127,12 +131,16 @@ export async function addInsightsConnection(insightsData: InsightDetails) { await updateInsights(insights); const newInsights = getInsights(); if (newInsights != undefined) { + if (labels && labels.length > 0) { + handleLabelsConnMap(labels, insightsData.alias); + } ext.serverProvider.refreshInsights(newInsights); Telemetry.sendEvent("Connection.Created.Insights"); } window.showInformationMessage( `Added Insights connection: ${insightsData.alias}`, ); + NewConnectionPannel.close(); } } @@ -141,6 +149,7 @@ export async function addInsightsConnection(insightsData: InsightDetails) { export async function editInsightsConnection( insightsData: InsightDetails, oldAlias: string, + labels?: string[], ) { const aliasValidation = oldAlias === insightsData.alias @@ -207,12 +216,16 @@ export async function editInsightsConnection( const newInsights = getInsights(); if (newInsights != undefined) { + if (labels && labels.length > 0) { + handleLabelsConnMap(labels, insightsData.alias); + } ext.serverProvider.refreshInsights(newInsights); Telemetry.sendEvent("Connection.Edited.Insights"); } window.showInformationMessage( `Edited Insights connection: ${insightsData.alias}`, ); + NewConnectionPannel.close(); } } @@ -301,6 +314,7 @@ export async function enableTLS(serverKey: string): Promise { export async function addKdbConnection( kdbData: ServerDetails, isLocal?: boolean, + labels?: string[], ): Promise { const aliasValidation = validateServerAlias(kdbData.serverAlias, isLocal!); const hostnameValidation = validateServerName(kdbData.serverName); @@ -359,6 +373,9 @@ export async function addKdbConnection( await updateServers(servers); const newServers = getServers(); if (newServers != undefined) { + if (labels && labels.length > 0) { + handleLabelsConnMap(labels, kdbData.serverAlias); + } Telemetry.sendEvent("Connection.Created.QProcess"); ext.serverProvider.refresh(newServers); } @@ -368,6 +385,7 @@ export async function addKdbConnection( window.showInformationMessage( `Added kdb connection: ${kdbData.serverAlias}`, ); + NewConnectionPannel.close(); } } @@ -378,6 +396,7 @@ export async function editKdbConnection( oldAlias: string, isLocal?: boolean, editAuth?: boolean, + labels?: string[], ) { const aliasValidation = oldAlias === kdbData.serverAlias @@ -455,6 +474,9 @@ export async function editKdbConnection( } const newServers = getServers(); if (newServers != undefined) { + if (labels && labels.length > 0) { + handleLabelsConnMap(labels, kdbData.serverAlias); + } ext.serverProvider.refresh(newServers); Telemetry.sendEvent("Connection.Edited.KDB"); } diff --git a/src/extension.ts b/src/extension.ts index 837505f3..13e4e964 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -104,6 +104,11 @@ import { connectBuildTools, lintCommand } from "./commands/buildToolsCommand"; import { CompletionProvider } from "./services/completionProvider"; import { QuickFixProvider } from "./services/quickFixProvider"; import { connectClientCommands } from "./commands/clientCommands"; +import { + createNewLabel, + getWorkspaceLabels, + getWorkspaceLabelsConnMap, +} from "./utils/connLabel"; let client: LanguageClient; @@ -112,6 +117,10 @@ export async function activate(context: ExtensionContext) { ext.outputChannel = window.createOutputChannel("kdb"); ext.openSslVersion = await checkOpenSslInstalled(); ext.isBundleQCreated = false; + + getWorkspaceLabelsConnMap(); + getWorkspaceLabels(); + // clear necessary contexts commands.executeCommand("setContext", "kdb.connected.active", false); commands.executeCommand("setContext", "kdb.insightsConnected", false); @@ -266,38 +275,53 @@ export async function activate(context: ExtensionContext) { ), commands.registerCommand( "kdb.newConnection.createNewInsightConnection", - async (insightsData: InsightDetails) => { - await addInsightsConnection(insightsData); + async (insightsData: InsightDetails, labels: string[]) => { + await addInsightsConnection(insightsData, labels); }, ), commands.registerCommand( "kdb.newConnection.createNewConnection", - async (kdbData: ServerDetails) => { - await addKdbConnection(kdbData, false); + async (kdbData: ServerDetails, labels: string[]) => { + await addKdbConnection(kdbData, false, labels); }, ), commands.registerCommand( "kdb.newConnection.createNewBundledConnection", - async (kdbData: ServerDetails) => { - await addKdbConnection(kdbData, true); + async (kdbData: ServerDetails, labels: string[]) => { + await addKdbConnection(kdbData, true, labels); }, ), commands.registerCommand( "kdb.newConnection.editInsightsConnection", - async (insightsData: InsightDetails, oldAlias: string) => { - await editInsightsConnection(insightsData, oldAlias); + async ( + insightsData: InsightDetails, + oldAlias: string, + labels: string[], + ) => { + await editInsightsConnection(insightsData, oldAlias, labels); }, ), commands.registerCommand( "kdb.newConnection.editMyQConnection", - async (kdbData: ServerDetails, oldAlias: string, editAuth: boolean) => { - await editKdbConnection(kdbData, oldAlias, false, editAuth); + async ( + kdbData: ServerDetails, + oldAlias: string, + editAuth: boolean, + labels: string[], + ) => { + await editKdbConnection(kdbData, oldAlias, false, editAuth, labels); }, ), commands.registerCommand( "kdb.newConnection.editBundledConnection", - async (kdbData: ServerDetails, oldAlias: string) => { - await editKdbConnection(kdbData, oldAlias, true); + async (kdbData: ServerDetails, oldAlias: string, labels: string[]) => { + await editKdbConnection(kdbData, oldAlias, true, false, labels); + }, + ), + commands.registerCommand( + "kdb.labels.create", + async (name: string, colorName: string) => { + await createNewLabel(name, colorName); }, ), commands.registerCommand( @@ -475,6 +499,12 @@ export async function activate(context: ExtensionContext) { ext.dataSourceTreeProvider.reload(); ext.scratchpadTreeProvider.reload(); } + if (event.affectsConfiguration("kdb.connectionLabelsMap")) { + ext.serverProvider.reload(); + } + if (event.affectsConfiguration("kdb.connectionLabels")) { + ext.serverProvider.reload(); + } }), ); diff --git a/src/extensionVariables.ts b/src/extensionVariables.ts index 735c5ab2..3a923739 100644 --- a/src/extensionVariables.ts +++ b/src/extensionVariables.ts @@ -37,6 +37,7 @@ import { ScratchpadFile } from "./models/scratchpad"; import { LocalConnection } from "./classes/localConnection"; import { InsightsConnection } from "./classes/insightsConnection"; import { DataSourceFiles } from "./models/dataSource"; +import { ConnectionLabel, LabelColors, Labels } from "./models/labels"; // eslint-disable-next-line @typescript-eslint/no-namespace export namespace ext { @@ -84,6 +85,8 @@ export namespace ext { export const kdbNodesWithoutAuth: string[] = []; export const kdbNodesWithoutTls: string[] = []; export const kdbConnectionAliasList: string[] = []; + export const connLabelList: Labels[] = []; + export const labelConnMapList: ConnectionLabel[] = []; export const maxRetryCount = 5; export let secretSettings: AuthSettings; @@ -306,4 +309,35 @@ export namespace ext { export const diagnosticCollection = languages.createDiagnosticCollection("kdb"); + + export const labelColors: LabelColors[] = [ + { + name: "White", + colorHex: "#FFFFFF", + }, + { + name: "Red", + colorHex: "#CD3131", + }, + { + name: "Green", + colorHex: "#10BC7A", + }, + { + name: "Yellow", + colorHex: "#E5E50E", + }, + { + name: "Blue", + colorHex: "#2371C8", + }, + { + name: "Magenta", + colorHex: "#BC3FBC", + }, + { + name: "Cyan", + colorHex: "#15A7CD", + }, + ]; } diff --git a/src/models/labels.ts b/src/models/labels.ts new file mode 100644 index 00000000..dc9797a6 --- /dev/null +++ b/src/models/labels.ts @@ -0,0 +1,27 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +export type LabelColors = { + name: string; + colorHex: string; +}; + +export type Labels = { + name: string; + color: LabelColors; +}; + +export type ConnectionLabel = { + labelName: string; + connections: string[]; +}; diff --git a/src/panels/newConnection.ts b/src/panels/newConnection.ts index 15528718..b6df569f 100644 --- a/src/panels/newConnection.ts +++ b/src/panels/newConnection.ts @@ -17,6 +17,7 @@ import { getNonce } from "../utils/getNonce"; import { ext } from "../extensionVariables"; import { InsightsNode, KdbNode } from "../services/kdbTreeProvider"; import { ConnectionType, EditConnectionMessage } from "../models/messages"; +import { retrieveConnLabelsNames } from "../utils/connLabel"; export class NewConnectionPannel { public static currentPanel: NewConnectionPannel | undefined; @@ -46,12 +47,20 @@ export class NewConnectionPannel { extensionUri, ); + panel.webview.postMessage({ + command: "refreshLabels", + data: ext.connLabelList, + colors: ext.labelColors, + }); + if (conn) { + const labels = retrieveConnLabelsNames(conn); const connType = this.getConnectionType(conn); const editConnData = this.createEditConnectionMessage(conn, connType); panel.webview.postMessage({ command: "editConnection", data: editConnData, + labels, }); } } @@ -82,6 +91,7 @@ export class NewConnectionPannel { vscode.commands.executeCommand( "kdb.newConnection.createNewBundledConnection", message.data, + message.labels, ); } } @@ -89,12 +99,14 @@ export class NewConnectionPannel { vscode.commands.executeCommand( "kdb.newConnection.createNewInsightConnection", message.data, + message.labels, ); } if (message.command === "kdb.newConnection.createNewConnection") { vscode.commands.executeCommand( "kdb.newConnection.createNewConnection", message.data, + message.labels, ); } if (message.command === "kdb.newConnection.editInsightsConnection") { @@ -102,6 +114,7 @@ export class NewConnectionPannel { "kdb.newConnection.editInsightsConnection", message.data, message.oldAlias, + message.labels, ); } if (message.command === "kdb.newConnection.editMyQConnection") { @@ -110,6 +123,7 @@ export class NewConnectionPannel { message.data, message.oldAlias, message.editAuth, + message.labels, ); } if (message.command === "kdb.newConnection.editBundledConnection") { @@ -117,7 +131,22 @@ export class NewConnectionPannel { "kdb.newConnection.editBundledConnection", message.data, message.oldAlias, + message.labels, + ); + } + if (message.command === "kdb.labels.create") { + vscode.commands.executeCommand( + "kdb.labels.create", + message.data.name, + message.data.colorName, ); + setTimeout(() => { + this._panel.webview.postMessage({ + command: "refreshLabels", + data: ext.connLabelList, + colors: ext.labelColors, + }); + }, 500); } }); } diff --git a/src/utils/connLabel.ts b/src/utils/connLabel.ts new file mode 100644 index 00000000..76b293bc --- /dev/null +++ b/src/utils/connLabel.ts @@ -0,0 +1,126 @@ +/* + * Copyright (c) 1998-2023 Kx Systems Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the + * License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the + * specific language governing permissions and limitations under the License. + */ + +import { ConnectionLabel, Labels } from "../models/labels"; +import { workspace } from "vscode"; +import { ext } from "../extensionVariables"; +import { kdbOutputLog } from "./core"; +import { InsightsNode, KdbNode } from "../services/kdbTreeProvider"; + +export function getWorkspaceLabels() { + const existingConnLbls = workspace + .getConfiguration() + .get("kdb.connectionLabels"); + ext.connLabelList.length = 0; + if (existingConnLbls && existingConnLbls.length > 0) { + existingConnLbls.forEach((label: Labels) => { + ext.connLabelList.push(label); + }); + } +} + +export function createNewLabel(name: string, colorName: string) { + getWorkspaceLabels(); + const color = ext.labelColors.find( + (color) => color.name.toLowerCase() === colorName.toLowerCase(), + ); + if (name === "") { + kdbOutputLog("Label name can't be empty", "ERROR"); + } + if (color && name !== "") { + const newLbl: Labels = { + name: name, + color: color, + }; + ext.connLabelList.push(newLbl); + workspace + .getConfiguration() + .update("kdb.connectionLabels", ext.connLabelList, true); + } else { + kdbOutputLog("No Color selected for the label", "ERROR"); + } +} + +export function getWorkspaceLabelsConnMap() { + const existingLabelConnMaps = workspace + .getConfiguration() + .get("kdb.labelsConnectionMap"); + ext.labelConnMapList.length = 0; + if (existingLabelConnMaps && existingLabelConnMaps.length > 0) { + existingLabelConnMaps.forEach((labelConnMap: ConnectionLabel) => { + ext.labelConnMapList.push(labelConnMap); + }); + } +} + +export function addConnToLabel(labelName: string, connName: string) { + const label = ext.connLabelList.find( + (lbl) => lbl.name.toLowerCase() === labelName.toLowerCase(), + ); + if (label) { + if (ext.labelConnMapList.length > 0) { + const labelConnMap = ext.labelConnMapList.find( + (lbl) => lbl.labelName === labelName, + ); + if (labelConnMap) { + if (!labelConnMap.connections.includes(connName)) { + labelConnMap.connections.push(connName); + } + } else { + ext.labelConnMapList.push({ + labelName: labelName, + connections: [connName], + }); + } + } else { + ext.labelConnMapList.push({ + labelName: labelName, + connections: [connName], + }); + } + } +} + +export function removeConnFromLabels(connName: string) { + ext.labelConnMapList.forEach((labelConnMap) => { + if (labelConnMap.connections.includes(connName)) { + labelConnMap.connections = labelConnMap.connections.filter( + (conn: string) => conn !== connName, + ); + } + }); +} + +export function handleLabelsConnMap(labels: string[], connName: string) { + removeConnFromLabels(connName); + labels.forEach((label) => { + addConnToLabel(label, connName); + }); + workspace + .getConfiguration() + .update("kdb.labelsConnectionMap", ext.labelConnMapList, true); +} + +export function retrieveConnLabelsNames( + conn: KdbNode | InsightsNode, +): string[] { + const connName = + conn instanceof KdbNode ? conn.details.serverAlias : conn.details.alias; + const labels: string[] = []; + ext.labelConnMapList.forEach((labelConnMap) => { + if (labelConnMap.connections.includes(connName)) { + labels.push(labelConnMap.labelName); + } + }); + return labels; +} diff --git a/src/webview/components/kdbNewConnectionView.ts b/src/webview/components/kdbNewConnectionView.ts index 93d79117..8cca7f0e 100644 --- a/src/webview/components/kdbNewConnectionView.ts +++ b/src/webview/components/kdbNewConnectionView.ts @@ -18,10 +18,16 @@ import { InsightDetails } from "../../models/insights"; import { kdbStyles, newConnectionStyles, vscodeStyles } from "./styles"; import { EditConnectionMessage } from "../../models/messages"; +import { repeat } from "lit/directives/repeat.js"; +import { LabelColors, Labels } from "../../models/labels"; @customElement("kdb-new-connection-view") export class KdbNewConnectionView extends LitElement { static styles = [vscodeStyles, kdbStyles, newConnectionStyles]; + lblColorsList: LabelColors[] = []; + lblNamesList: Labels[] = []; + newLblName = ""; + newLblColorName = ""; kdbServer: ServerDetails = { serverName: "", serverPort: "", @@ -47,10 +53,12 @@ export class KdbNewConnectionView extends LitElement { realm: "", insecure: false, }; + labels: string[] = []; serverType: ServerType = ServerType.KDB; isBundledQ: boolean = true; oldAlias: string = ""; editAuth: boolean = false; + private isModalOpen = false; private _connectionData: EditConnectionMessage | undefined = undefined; private readonly vscode = acquireVsCodeApi(); private tabConfig = { @@ -70,6 +78,18 @@ export class KdbNewConnectionView extends LitElement { this.requestUpdate("connectionData", oldValue); } + openModal() { + this.isModalOpen = true; + this.requestUpdate(); + } + + closeModal() { + this.newLblColorName = ""; + this.newLblName = ""; + this.isModalOpen = false; + this.requestUpdate(); + } + connectedCallback() { super.connectedCallback(); window.addEventListener("message", this.handleMessage.bind(this)); @@ -97,6 +117,13 @@ export class KdbNewConnectionView extends LitElement { const message = event.data; if (message.command === "editConnection") { this.connectionData = message.data; + this.labels = message.labels; + this.requestUpdate(); + } + if (message.command === "refreshLabels") { + this.lblNamesList = message.data; + this.lblColorsList = message.colors; + this.requestUpdate(); } } @@ -279,9 +306,138 @@ export class KdbNewConnectionView extends LitElement { this.serverType = config.serverType; } + renderLblDropdownColorOptions() { + return html` + No Color Selected + ${repeat( + this.lblColorsList, + (color) => color, + (color) => + html` +
+ ${color.name}
+
`, + )} + `; + } + + renderLblDropdownOptions() { + return html` + No Label Selected + ${repeat( + this.lblNamesList, + (lbl) => lbl.name, + (lbl) => html` + + +
+ ${lbl.name} +
+
+ `, + )} + `; + } + + renderNewLabelModal() { + return html` +
+ + + + `; + } + + renderNewLblBtn() { + return html` + + Create New Label + + `; + } + + renderConnectionLabelsSection() { + return html`
+
+
Connection label (optional)
+
+ + ${this.renderNewLblBtn()} +
+
+
`; + } + renderNewConnectionForm() { return html`
+ ${this.isModalOpen ? this.renderNewLabelModal() : ""}
@@ -345,6 +501,7 @@ export class KdbNewConnectionView extends LitElement {
${this.renderPortNumber()}
+ ${this.renderConnectionLabelsSection()}
@@ -415,6 +572,7 @@ export class KdbNewConnectionView extends LitElement {
+ ${this.renderConnectionLabelsSection()} @@ -448,6 +606,7 @@ export class KdbNewConnectionView extends LitElement { + ${this.renderConnectionLabelsSection()} @@ -482,6 +641,7 @@ export class KdbNewConnectionView extends LitElement {
${this.renderEditConnFields()}
+
${this.renderConnectionLabelsSection()}
@@ -633,7 +793,6 @@ export class KdbNewConnectionView extends LitElement { this.insightsServer.alias = this.connectionData.serverName; this.insightsServer.server = this.connectionData.serverAddress; this.insightsServer.realm = this.connectionData.realm ?? ""; - this.insightsServer.insecure = this.connectionData.insecure ?? false; return html`
@@ -651,17 +810,6 @@ export class KdbNewConnectionView extends LitElement {
Advanced ${this.renderRealm()} -
- Accept insecure SSL certifcates -
@@ -696,20 +844,36 @@ export class KdbNewConnectionView extends LitElement { this.vscode.postMessage({ command: "kdb.newConnection.createNewBundledConnection", data: this.bundledServer, + labels: this.labels, }); } else if (this.serverType === ServerType.INSIGHTS) { this.vscode.postMessage({ command: "kdb.newConnection.createNewInsightConnection", data: this.data, + labels: this.labels, }); } else { this.vscode.postMessage({ command: "kdb.newConnection.createNewConnection", data: this.data, + labels: this.labels, }); } } + private createLabel() { + this.vscode.postMessage({ + command: "kdb.labels.create", + data: { + name: this.newLblName, + colorName: this.newLblColorName, + }, + }); + setTimeout(() => { + this.closeModal(); + }, 500); + } + private editConnection() { if (!this.connectionData) { return; @@ -719,6 +883,7 @@ export class KdbNewConnectionView extends LitElement { command: "kdb.newConnection.editBundledConnection", data: this.bundledServer, oldAlias: "local", + labels: this.labels, }); } else if (this.connectionData.connType === 1) { this.vscode.postMessage({ @@ -726,12 +891,14 @@ export class KdbNewConnectionView extends LitElement { data: this.data, oldAlias: this.oldAlias, editAuth: this.editAuth, + labels: this.labels, }); } else { this.vscode.postMessage({ command: "kdb.newConnection.editInsightsConnection", data: this.data, oldAlias: this.oldAlias, + labels: this.labels, }); } } diff --git a/src/webview/components/styles.ts b/src/webview/components/styles.ts index 5066127f..ee290445 100644 --- a/src/webview/components/styles.ts +++ b/src/webview/components/styles.ts @@ -165,4 +165,37 @@ export const newConnectionStyles = css` .text-field.larger { width: 20em; } + + .modal { + position: fixed; + top: 50%; + transform: translate(-50%, -50%); + background: var(--vscode-editor-background); + color: var(--vscode-editor-foreground); + padding: 1rem; + z-index: 1001; + border: 1px solid var(--vscode-editorWidget-border); + box-shadow: 0 2px 10px var(--vscode-widget-shadow); + } + + .modal-content h2 { + color: var(--vscode-editor-foreground); + } + vscode-text-field, + vscode-dropdown, + vscode-button { + --vscode-input-background: var(--vscode-editor-background); + --vscode-input-foreground: var(--vscode-editor-foreground); + --vscode-input-border: var(--vscode-editorWidget-border); + } + + .overlay { + position: fixed; + top: 0; + left: 0; + width: 100%; + height: 100%; + background: rgba(0, 0, 0, 0.5); + z-index: 1000; + } `; diff --git a/test/suite/utils.test.ts b/test/suite/utils.test.ts index 3572807c..aa41407b 100644 --- a/test/suite/utils.test.ts +++ b/test/suite/utils.test.ts @@ -23,13 +23,13 @@ import { QueryResultType } from "../../src/models/queryResult"; import { ServerDetails, ServerType } from "../../src/models/server"; import { InsightsNode, KdbNode } from "../../src/services/kdbTreeProvider"; import { QueryHistoryProvider } from "../../src/services/queryHistoryProvider"; -import { KdbResultsViewProvider } from "../../src/services/resultsPanelProvider"; import * as coreUtils from "../../src/utils/core"; import * as cpUtils from "../../src/utils/cpUtils"; import * as dataSourceUtils from "../../src/utils/dataSource"; import * as decodeUtils from "../../src/utils/decode"; import * as executionUtils from "../../src/utils/execution"; import * as executionConsoleUtils from "../../src/utils/executionConsole"; +import * as LabelsUtils from "../../src/utils/connLabel"; import { getNonce } from "../../src/utils/getNonce"; import { getUri } from "../../src/utils/getUri"; import { openUrl } from "../../src/utils/openUrl"; @@ -51,6 +51,7 @@ import { import { DataSourceTypes } from "../../src/models/dataSource"; import { InsightDetails } from "../../src/models/insights"; import { LocalConnection } from "../../src/classes/localConnection"; +import { Labels } from "../../src/models/labels"; interface ITestItem extends vscode.QuickPickItem { id: number; @@ -1593,4 +1594,156 @@ describe("Utils", () => { }); }); }); + + describe("connLabelsUtils", () => { + let getConfigurationStub: sinon.SinonStub; + + beforeEach(() => { + getConfigurationStub = sinon.stub(vscode.workspace, "getConfiguration"); + ext.connLabelList.length = 0; + ext.labelConnMapList.length = 0; + }); + + afterEach(() => { + sinon.restore(); + }); + + it("should get workspace labels", () => { + const labels: Labels[] = [ + { name: "label1", color: { name: "red", colorHex: "#FF0000" } }, + ]; + getConfigurationStub.returns({ + get: sinon.stub().returns(labels), + update: sinon.stub(), + }); + + LabelsUtils.getWorkspaceLabels(); + + assert.strictEqual(ext.connLabelList.length, 1); + + assert.deepStrictEqual(ext.connLabelList, labels); + }); + + it("should create a new label", () => { + getConfigurationStub.returns({ + get: sinon.stub().returns([]), + update: sinon.stub(), + }); + + LabelsUtils.createNewLabel("label1", "red"); + + assert.strictEqual(ext.connLabelList.length, 1); + assert.strictEqual(ext.connLabelList[0].name, "label1"); + assert.strictEqual(ext.connLabelList[0].color.name, "Red"); + }); + + it("should handle empty label name", () => { + getConfigurationStub.returns({ + get: sinon.stub(), + update: sinon.stub(), + }); + const logStub = sinon.stub(coreUtils, "kdbOutputLog"); + + LabelsUtils.createNewLabel("", "red"); + + sinon.assert.calledWith(logStub, "Label name can't be empty", "ERROR"); + }); + + it("should handle no color selected", () => { + getConfigurationStub.returns({ + get: sinon.stub(), + update: sinon.stub(), + }); + const logStub = sinon.stub(coreUtils, "kdbOutputLog"); + + LabelsUtils.createNewLabel("label1", "randomColorName"); + + sinon.assert.calledWith( + logStub, + "No Color selected for the label", + "ERROR", + ); + }); + + it("should get workspace labels connection map", () => { + const connMap = [{ labelName: "label1", connections: ["conn1"] }]; + getConfigurationStub.returns({ + get: sinon.stub().returns(connMap), + update: sinon.stub(), + }); + + LabelsUtils.getWorkspaceLabelsConnMap(); + + assert.deepStrictEqual(ext.labelConnMapList, connMap); + }); + + it("should add connection to label", () => { + ext.connLabelList.push({ + name: "label1", + color: { name: "red", colorHex: "#FF0000" }, + }); + + LabelsUtils.addConnToLabel("label1", "conn1"); + + assert.strictEqual(ext.labelConnMapList.length, 1); + assert.strictEqual(ext.labelConnMapList[0].labelName, "label1"); + assert.deepStrictEqual(ext.labelConnMapList[0].connections, ["conn1"]); + }); + + it("should remove connection from labels", () => { + ext.labelConnMapList.push({ + labelName: "label1", + connections: ["conn1", "conn2"], + }); + + LabelsUtils.removeConnFromLabels("conn1"); + + assert.deepStrictEqual(ext.labelConnMapList[0].connections, ["conn2"]); + }); + + it("should handle labels connection map", () => { + ext.connLabelList.push({ + name: "label1", + color: { name: "Red", colorHex: "#FF0000" }, + }); + ext.labelConnMapList.push({ + labelName: "label1", + connections: ["conn2"], + }); + + getConfigurationStub.returns({ + get: sinon.stub(), + update: sinon.stub(), + }); + + LabelsUtils.handleLabelsConnMap(["label1"], "conn2"); + + assert.strictEqual(ext.labelConnMapList.length, 1); + assert.deepStrictEqual(ext.labelConnMapList[0].connections, ["conn2"]); + }); + + it("should retrieve connection labels names", () => { + ext.labelConnMapList.push({ + labelName: "label1", + connections: ["conn1"], + }); + const conn = new KdbNode( + [], + "conn1", + { + serverName: "kdbservername", + serverAlias: "conn1", + serverPort: "5001", + managed: false, + auth: false, + tls: false, + }, + TreeItemCollapsibleState.None, + ); + + const labels = LabelsUtils.retrieveConnLabelsNames(conn); + + assert.deepStrictEqual(labels, ["label1"]); + }); + }); }); diff --git a/test/suite/webview.test.ts b/test/suite/webview.test.ts index dd4d9e54..1bd2320a 100644 --- a/test/suite/webview.test.ts +++ b/test/suite/webview.test.ts @@ -22,7 +22,6 @@ import { ServerType } from "../../src/models/server"; import { InsightDetails } from "../../src/models/insights"; import { - ConnectionType, DataSourceCommand, DataSourceMessage2, } from "../../src/models/messages"; @@ -36,6 +35,7 @@ import { } from "../../src/models/dataSource"; import { MetaObjectPayload } from "../../src/models/meta"; import { html, TemplateResult } from "lit"; +import { ext } from "../../src/extensionVariables"; describe("KdbDataSourceView", () => { let view: KdbDataSourceView; @@ -247,6 +247,20 @@ describe("KdbNewConnectionView", () => { assert.equal(view.connectionData, event.data.data); }); + it('should update connectionData when command is "refreshLabels"', () => { + const event = { + data: { + command: "refreshLabels", + data: ["test"], + colors: ext.labelColors, + }, + }; + + view.handleMessage(event); + + assert.equal(view.lblNamesList, event.data.data); + }); + it('should not update connectionData when command is not "editConnection"', () => { const event = { data: { @@ -442,6 +456,62 @@ describe("KdbNewConnectionView", () => { true, ); }); + + it("should render label dropdown color options", () => { + view.lblColorsList = [ + { name: "red", colorHex: "#FF0000" }, + { name: "green", colorHex: "#00FF00" }, + ]; + + const result = view.renderLblDropdownColorOptions(); + + assert.strictEqual( + JSON.stringify(result).includes("No Color Selected"), + true, + ); + }); + + it("should render label dropdown options", () => { + view.lblNamesList = [ + { name: "label1", color: { colorHex: "#FF0000" } }, + { name: "label2", color: { colorHex: "#00FF00" } }, + ]; + view.labels = ["label1"]; + + const result = view.renderLblDropdownOptions(); + + assert.strictEqual( + JSON.stringify(result).includes("No Label Selected"), + true, + ); + }); + + it("should render New Label Modal", () => { + const result = view.renderNewLabelModal(); + + assert.strictEqual( + JSON.stringify(result).includes("Add a New Label"), + true, + ); + }); + + it("should render New Label Btn", () => { + const result = view.renderNewLblBtn(); + + assert.strictEqual( + JSON.stringify(result).includes("Create New Label"), + true, + ); + }); + + it("should render Connection Label Section", () => { + const result = view.renderConnectionLabelsSection(); + + assert.strictEqual( + JSON.stringify(result).includes("Connection label (optional)"), + true, + ); + }); }); describe("tabClickAction", () => {