diff --git a/TestPlan.md b/TestPlan.md index fe88ff3..9c286ce 100644 --- a/TestPlan.md +++ b/TestPlan.md @@ -120,6 +120,8 @@ - download ok # Terminal +- reconnect: open a ssh terminal, reboot, then the reconnect button should appear + - after you click it, your session should be reconnected ## Local Terminal - (Settings) if default open option checked, then a local terminal should start at startup diff --git a/package-lock.json b/package-lock.json index 1197729..8c6f6dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "yet-another-electron-term", - "version": "1.0.1", + "version": "1.0.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "yet-another-electron-term", - "version": "1.0.1", + "version": "1.0.2", "hasInstallScript": true, "dependencies": { "@angular/animations": "^18.2.0", diff --git a/package.json b/package.json index 5799874..fcb5582 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "yet-another-electron-term", - "version": "1.0.1", + "version": "1.0.0", "main": "src-electron/electronMain.js", "scripts": { "ng": "ng", @@ -13,7 +13,7 @@ "electron:dev": "wait-on http://localhost:4200 && cross-env NODE_ENV=development electron .", "postinstall": "patch-package", "build:release": "npm run clean && patch-package && ng build --base-href ./ && electron-builder --publish always", - "release": "npm run build:release && npm version patch" + "release": "npm version patch && npm run build:release" }, "build": { "appId": "io.github.invince", @@ -21,7 +21,7 @@ "publish": { "provider": "github", "owner": "invince", - "repo": "YAET" + "repo": "YAET-RELEASE" }, "nsis": { "oneClick": false, diff --git a/src-electron/ipc/terminal.js b/src-electron/ipc/terminal.js index f81e9c3..ad71cdb 100644 --- a/src-electron/ipc/terminal.js +++ b/src-electron/ipc/terminal.js @@ -136,12 +136,15 @@ function initTerminalIpcHandler(log, terminalMap) { // Handle end event conn.on('end', () => { log.info('SSH connection ended for id:', id); + }); // Handle close event conn.on('close', (hadError) => { if (hadError) { log.info(`SSH connection closed for id: ${id}, hadError: ${hadError}`); + event.sender.send('session.disconnect.terminal.ssh', { id: id , error: hadError }); + } else { event.sender.send('session.disconnect.terminal.ssh', { id: id }); } }); diff --git a/src/app/app.component.html b/src/app/app.component.html index 77cebc4..21954bc 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -26,7 +26,7 @@ - + @for (tab of tabService.tabs ; let i = $index; track tab.id) { diff --git a/src/app/app.component.ts b/src/app/app.component.ts index c557839..f051bc9 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -107,8 +107,9 @@ export class AppComponent implements OnInit, OnDestroy{ } this.modalControl.closeModal([this.MENU_PROFILE, this.MENU_ADD ]); if (Profile.requireOpenNewTab(profile)) { - this.tabService.addTab(new TabInstance(profile.category, this.sessionService.create(profile, profile.profileType))); // Adds a new terminal identifier - this.tabService.currentTabIndex = this.tabService.tabs.length - 1; + const tab = new TabInstance(profile.category, this.sessionService.create(profile, profile.profileType)); + this.tabService.addTab(tab); // Adds a new terminal identifier + this.tabService.currentTabIndex = this.tabService.tabs.findIndex(one => one.id === tab.id); } else { this.sessionService.openSessionWithoutTab(profile); } @@ -145,7 +146,8 @@ export class AppComponent implements OnInit, OnDestroy{ } removeTab(index: number) { - this.tabService.tabs.splice(index, 1); + this.tabService.removeTab(index); + } @@ -154,14 +156,15 @@ export class AppComponent implements OnInit, OnDestroy{ } reconnect(i: number) { - this.tabService.reconnect(i); + this.sessionService.reconnect(i); } addLocalTerminal() { this.modalControl.closeModal(); - this.tabService.addTab(new TabInstance( ProfileCategory.TERMINAL, - this.sessionService.create(this.settingService.createLocalTerminalProfile(),ProfileType.LOCAL_TERMINAL))); // Adds a new terminal identifier - this.tabService.currentTabIndex = this.tabService.tabs.length - 1; + const tab = new TabInstance( ProfileCategory.TERMINAL, + this.sessionService.create(this.settingService.createLocalTerminalProfile(),ProfileType.LOCAL_TERMINAL)); + this.tabService.addTab(tab); // Adds a new terminal identifier + this.tabService.currentTabIndex = this.tabService.tabs.findIndex(one => one.id === tab.id); } diff --git a/src/app/components/menu/cloud/cloud.component.ts b/src/app/components/menu/cloud/cloud.component.ts index fb8eeec..b31ac0f 100644 --- a/src/app/components/menu/cloud/cloud.component.ts +++ b/src/app/components/menu/cloud/cloud.component.ts @@ -214,7 +214,7 @@ export class CloudComponent extends MenuComponent implements OnInit, OnDestroy { } filterSecret() { - return this.secretStorageService.data.secrets?.filter(one => one.secretType == SecretType.LOGIN_PASSWORD); + return this.secretStorageService.filter(one => one.secretType == SecretType.LOGIN_PASSWORD); } quickCreateSecret() { diff --git a/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.html b/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.html index 0aa90d9..80534c1 100644 --- a/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.html +++ b/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.html @@ -50,8 +50,15 @@ Secret - @for (oneSecret of secretStorageService.data.secrets; track oneSecret.id) { + + add + Add New... + + @for (oneSecret of filterSecret(); track oneSecret.id) { + @if (oneSecret.icon) { + {{oneSecret.icon}} + } {{ secretService.displaySecretOptionName(oneSecret) }} } diff --git a/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.ts b/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.ts index 8eece62..50d2316 100644 --- a/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.ts +++ b/src/app/components/menu/profile-form/custom-profile-form/custom-profile-form.component.ts @@ -1,9 +1,10 @@ -import {Component, forwardRef, Injector, Self} from '@angular/core'; +import {Component, forwardRef, Injector} from '@angular/core'; import {CommonModule} from '@angular/common'; import { FormBuilder, FormGroup, - FormsModule, NG_VALIDATORS, + FormsModule, + NG_VALIDATORS, NG_VALUE_ACCESSOR, ReactiveFormsModule, Validators @@ -16,7 +17,7 @@ import {MatIcon} from '@angular/material/icon'; import {MatIconButton} from '@angular/material/button'; import {ChildFormAsFormControl} from '../../../enhanced-form-mixin'; import {MenuComponent} from '../../menu.component'; -import {AuthType} from '../../../../domain/Secret'; +import {AuthType, SecretType} from '../../../../domain/Secret'; import {SecretStorageService} from '../../../../services/secret-storage.service'; import {SecretService} from '../../../../services/secret.service'; import {SettingStorageService} from '../../../../services/setting-storage.service'; @@ -27,6 +28,8 @@ import { ModelFieldWithPrecondition, ModelFormController } from '../../../../utils/ModelFormController'; +import {SecretQuickFormComponent} from '../../../dialog/secret-quick-form/secret-quick-form.component'; +import {MatDialog} from '@angular/material/dialog'; @Component({ selector: 'app-custom-profile-form', @@ -72,6 +75,7 @@ export class CustomProfileFormComponent extends ChildFormAsFormControl(MenuCompo public secretStorageService: SecretStorageService, // in html public secretService: SecretService, // in html public settingStorage: SettingStorageService, + public dialog: MatDialog, ) { super(); @@ -150,4 +154,17 @@ export class CustomProfileFormComponent extends ChildFormAsFormControl(MenuCompo this.form.get('secretId')?.setValue(null); } } + + quickCreateSecret() { + this.dialog.open(SecretQuickFormComponent, { + width: '650px', + data: { + secretTypes: [SecretType.LOGIN_PASSWORD, SecretType.PASSWORD_ONLY] + } + }); + } + + filterSecret() { + return this.secretStorageService.filter(one => one.secretType == SecretType.LOGIN_PASSWORD || one.secretType == SecretType.PASSWORD_ONLY); + } } diff --git a/src/app/components/menu/profile-form/ssh-profile-form/ssh-profile-form.component.html b/src/app/components/menu/profile-form/ssh-profile-form/ssh-profile-form.component.html index e0f2bd2..0adf237 100644 --- a/src/app/components/menu/profile-form/ssh-profile-form/ssh-profile-form.component.html +++ b/src/app/components/menu/profile-form/ssh-profile-form/ssh-profile-form.component.html @@ -88,7 +88,7 @@ add Add New... - @for (oneSecret of secretStorageService.data.secrets; track oneSecret.id) { + @for (oneSecret of secretStorageService.dataCopy.secrets; track oneSecret.id) { @if (oneSecret.icon) { {{oneSecret.icon}} diff --git a/src/app/components/menu/profile-form/vnc-profile-form/vnc-profile-form.component.ts b/src/app/components/menu/profile-form/vnc-profile-form/vnc-profile-form.component.ts index a56db50..1c66c8d 100644 --- a/src/app/components/menu/profile-form/vnc-profile-form/vnc-profile-form.component.ts +++ b/src/app/components/menu/profile-form/vnc-profile-form/vnc-profile-form.component.ts @@ -156,7 +156,7 @@ export class VncProfileFormComponent extends ChildFormAsFormControl(MenuComponen } filterSecret() { - return this.secretStorageService.data.secrets?.filter(one => one.secretType == SecretType.PASSWORD_ONLY); + return this.secretStorageService.filter(one => one.secretType == SecretType.PASSWORD_ONLY); } } diff --git a/src/app/components/menu/profiles-menu/profiles-menu.component.html b/src/app/components/menu/profiles-menu/profiles-menu.component.html index df66685..1c657a8 100644 --- a/src/app/components/menu/profiles-menu/profiles-menu.component.html +++ b/src/app/components/menu/profiles-menu/profiles-menu.component.html @@ -42,7 +42,7 @@

Profiles

+ (click)="onTabChange(node.profile)" (dblclick)="onTabConnect(node.profile)"> @if (node.profile.icon) { {{node.profile.icon}} } @@ -78,12 +78,12 @@

Profiles

} - @else { + @else { // in list mode @for (profile of profilesCopy.profiles | filterKeyword:keywordsProviders:filter; track profile.id) {