Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New connection settings Connection Timeout field #2443

Merged
merged 8 commits into from
Jan 6, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2983,7 +2983,7 @@
},
"dependencies": {
"@ibm/ibmi-eventf-parser": "^1.0.2",
"@vscode-elements/elements": "^1.9.0",
"@vscode-elements/elements": "^1.9.1",
"adm-zip": "^0.5.14",
"crc-32": "https://cdn.sheetjs.com/crc-32-latest/crc-32-latest.tgz",
"csv": "^6.2.1",
Expand Down
25 changes: 21 additions & 4 deletions src/api/CustomUI.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ interface WebviewMessageRequest {
data?: any;
}

type InputType = "text" | "number";

export class Section {
readonly fields: Field[] = [];

Expand All @@ -61,7 +63,7 @@ export class Section {
return this;
}

addInput(id: string, label: string, description?: string, options?: { default?: string, readonly?: boolean, rows?: number, minlength?: number, maxlength?: number, regexTest?: string }) {
addInput(id: string, label: string, description?: string, options?: { default?: string, readonly?: boolean, rows?: number, minlength?: number, maxlength?: number, regexTest?: string, inputType?: InputType, min?:number, max?:number }) {
const input = Object.assign(new Field('input', id, label, description), options);
this.addField(input);
return this;
Expand Down Expand Up @@ -327,6 +329,13 @@ export class CustomUI extends Section {
}
}

if(field.inputType === "number"){
const numberValue = Number(currentValue);
isInvalid = isNaN(numberValue) ||
(field.min !== undefined && numberValue < Number(field.min)) ||
(field.max !== undefined && numberValue > Number(field.max));
}

if (isInvalid) {
fieldElement.setAttribute("invalid", "true");
isValid = false;
Expand Down Expand Up @@ -389,7 +398,7 @@ export class CustomUI extends Section {
// Setup the input fields for validation
for (const field of inputFields) {
const fieldElement = document.getElementById(field.id);
fieldElement.onkeyup = (e) => {validateInputs()};
fieldElement.addEventListener("change", (e) => {validateInputs()});
}

// Now many buttons can be pressed to submit
Expand Down Expand Up @@ -505,6 +514,9 @@ export class Field {
public minlength?: number;
public maxlength?: number;
public regexTest?: string;
public inputType?: InputType;
public min?: number;
public max?: number;

constructor(readonly type: FieldType, readonly id: string, readonly label: string, readonly description?: string) {

Expand Down Expand Up @@ -565,12 +577,17 @@ export class Field {
${this.renderLabel()}
${this.renderDescription()}
<${tag} class="long-input" id="${this.id}" name="${this.id}"
${this.inputType ? `type="${this.inputType}"` : ``}
${this.default ? `value="${this.default}"` : ``}
${this.readonly ? `readonly` : ``}
${multiline ? `rows="${this.rows}" resize="vertical"` : ''}
${this.minlength ? `minlength="${this.minlength}"` : ``}
${this.maxlength ? `maxlength="${this.maxlength}"` : ``}>
/${tag}>
${this.maxlength ? `maxlength="${this.maxlength}"` : ``}
${this.min ? `min="${this.min}"` : ``}
${this.max ? `max="${this.max}"` : ``}
${this.inputType === 'number' ? `step="1"` : ``}
>
<${tag}>
</vscode-form-group>`;

case `paragraph`:
Expand Down
6 changes: 3 additions & 3 deletions src/api/IBMi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { IBMiComponent } from "../components/component";
import { CopyToImport } from "../components/copyToImport";
import { CustomQSh } from '../components/cqsh';
import { ComponentManager } from "../components/manager";
import { CommandData, CommandResult, ConnectionData, IBMiMember, RemoteCommand, SpecialAuthorities, WrapResult } from "../typings";
import { CommandData, CommandResult, ConnectionData, IBMiMember, RemoteCommand, WrapResult } from "../typings";
import { CompileTools } from "./CompileTools";
import { ConnectionConfiguration } from "./Configuration";
import IBMiContent from "./IBMiContent";
Expand Down Expand Up @@ -76,7 +76,7 @@ export default class IBMi {
*/
content = new IBMiContent(this);

client: node_ssh.NodeSSH|undefined;
client: node_ssh.NodeSSH | undefined;
currentHost: string = ``;
currentPort: number = 22;
currentUser: string = ``;
Expand Down Expand Up @@ -106,7 +106,7 @@ export default class IBMi {
//Maximum admited length for command's argument - any command whose arguments are longer than this won't be executed by the shell
maximumArgsLength = 0;

private disconnectedCallback: (DisconnectCallback)|undefined;
private disconnectedCallback: (DisconnectCallback) | undefined;

/**
* Will only be called once per connection.
Expand Down
1 change: 1 addition & 0 deletions src/typings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ export interface ConnectionData {
password?: string;
privateKeyPath?: string;
keepaliveInterval?: number;
readyTimeout?: number;
}

export interface Server {
Expand Down
15 changes: 9 additions & 6 deletions src/webviews/login/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import vscode, { l10n, ThemeIcon } from "vscode";
import { ConnectionConfiguration, ConnectionManager } from "../../api/Configuration";
import { CustomUI, Section } from "../../api/CustomUI";
import IBMi from "../../api/IBMi";
import { safeDisconnect, instance } from "../../instantiate";
import { Tools } from "../../api/Tools";
import { instance, safeDisconnect } from "../../instantiate";
import { ConnectionData } from '../../typings';

type NewLoginSettings = ConnectionData & {
Expand All @@ -28,12 +27,15 @@ export class Login {
const connectionTab = new Section()
.addInput(`name`, `Connection Name`, undefined, { minlength: 1 })
.addInput(`host`, l10n.t(`Host or IP Address`), undefined, { minlength: 1 })
.addInput(`port`, l10n.t(`Port (SSH)`), ``, { default: `22`, minlength: 1, maxlength: 5, regexTest: `^\\d+$` })
.addInput(`port`, l10n.t(`Port (SSH)`), ``, { default: `22`, min: 1, max: 65535, inputType: "number" })
.addInput(`username`, l10n.t(`Username`), undefined, { minlength: 1, maxlength: 10 })
.addHorizontalRule()
.addParagraph(l10n.t(`Only provide either the password or a private key - not both.`))
.addPassword(`password`, l10n.t(`Password`))
.addCheckbox(`savePassword`, l10n.t(`Save Password`))
.addFile(`privateKeyPath`, l10n.t(`Private Key`), l10n.t(`OpenSSH, RFC4716, or PPK formats are supported.`));
.addFile(`privateKeyPath`, l10n.t(`Private Key`), l10n.t(`OpenSSH, RFC4716, or PPK formats are supported.`))
.addHorizontalRule()
.addInput(`readyTimeout`, l10n.t(`Connection Timeout (in milliseconds)`), l10n.t(`How long to wait for the SSH handshake to complete.`), { inputType: "number", min: 1, default: "20000" });

const tempTab = new Section()
.addInput(`tempLibrary`, `Temporary library`, `Temporary library. Cannot be QTEMP.`, { default: `ILEDITOR`, minlength: 1, maxlength: 10 })
Expand All @@ -55,6 +57,7 @@ export class Login {
page.panel.dispose();

data.port = Number(data.port);
data.readyTimeout = Number(data.readyTimeout);
data.privateKeyPath = data.privateKeyPath?.trim() ? Tools.normalizePath(data.privateKeyPath) : undefined;
if (data.name) {
const existingConnection = ConnectionManager.getByName(data.name);
Expand Down Expand Up @@ -96,7 +99,7 @@ export class Login {

if (data.password || data.privateKeyPath) {
try {
const connected = await instance.connect({data, onConnectedOperations: toDoOnConnected});
const connected = await instance.connect({ data, onConnectedOperations: toDoOnConnected });
if (connected.success) {
if (newConnection) {
vscode.window.showInformationMessage(`Connected to ${data.host}! Would you like to configure this connection?`, `Open configuration`).then(async (selectionA) => {
Expand Down Expand Up @@ -172,7 +175,7 @@ export class Login {
}

try {
const connected = await instance.connect({data: connectionConfig, onConnectedOperations: toDoOnConnected, reloadServerSettings});
const connected = await instance.connect({ data: connectionConfig, onConnectedOperations: toDoOnConnected, reloadServerSettings });
if (connected.success) {
vscode.window.showInformationMessage(`Connected to ${connectionConfig.host}!`);
} else {
Expand Down
6 changes: 5 additions & 1 deletion src/webviews/settings/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -360,11 +360,14 @@ export class SettingsUI {
const privateKeyWarning = !privateKeyPath || existsSync(privateKeyPath) ? "" : "<b>⚠️ This private key doesn't exist on this system! ⚠️</b></br></br>";
const ui = new CustomUI()
.addInput(`host`, vscode.l10n.t(`Host or IP Address`), undefined, { default: stored.host, minlength: 1 })
.addInput(`port`, vscode.l10n.t(`Port (SSH)`), undefined, { default: String(stored.port), minlength: 1, maxlength: 5, regexTest: `^\\d+$` })
.addInput(`port`, vscode.l10n.t(`Port (SSH)`), undefined, { default: String(stored.port), min: 1, max: 65535, inputType: "number" })
.addInput(`username`, vscode.l10n.t(`Username`), undefined, { default: stored.username, minlength: 1 })
.addHorizontalRule()
.addParagraph(vscode.l10n.t(`Only provide either the password or a private key - not both.`))
.addPassword(`password`, `${vscode.l10n.t(`Password`)}${storedPassword ? ` (${vscode.l10n.t(`stored`)})` : ``}`, vscode.l10n.t("Only provide a password if you want to update an existing one or set a new one."))
.addFile(`privateKeyPath`, `${vscode.l10n.t(`Private Key`)}${privateKeyPath ? ` (${vscode.l10n.t(`Private Key`)}: ${privateKeyPath})` : ``}`, privateKeyWarning + vscode.l10n.t("Only provide a private key if you want to update from the existing one or set one.") + '<br />' + vscode.l10n.t("OpenSSH, RFC4716 and PPK formats are supported."))
.addHorizontalRule()
.addInput(`readyTimeout`, vscode.l10n.t(`Connection Timeout (in milliseconds)`), vscode.l10n.t(`How long to wait for the SSH handshake to complete.`), { inputType: "number", min: 1, default: stored.readyTimeout ? String(stored.readyTimeout) : "20000" })
.addButtons(
{ id: `submitButton`, label: vscode.l10n.t(`Save`), requiresValidation: true },
{ id: `removeAuth`, label: vscode.l10n.t(`Remove auth methods`) }
Expand Down Expand Up @@ -410,6 +413,7 @@ export class SettingsUI {

//Fix values before assigning the data
data.port = Number(data.port);
data.readyTimeout = Number(data.readyTimeout);
delete data.password;
delete data.buttons;

Expand Down
Loading