serial plugin ui improv

This commit is contained in:
Eugene Pankov
2020-03-01 13:08:16 +01:00
parent 10b21ee085
commit 1b29797a81
13 changed files with 50 additions and 211 deletions

View File

@@ -21,7 +21,6 @@ export interface SerialConnection {
xon: boolean xon: boolean
xoff: boolean xoff: boolean
xany: boolean xany: boolean
group: string | null
scripts?: LoginScript[] scripts?: LoginScript[]
color?: string color?: string
} }

View File

@@ -11,14 +11,6 @@
[(ngModel)]='connection.name', [(ngModel)]='connection.name',
) )
.form-group
label Group
input.form-control(
type='text',
placeholder='Ungrouped',
[(ngModel)]='connection.group',
)
.form-group .form-group
label Path label Path
input.form-control( input.form-control(

View File

@@ -15,21 +15,13 @@
button.btn.btn-outline-danger.btn-sm((click)='clearLastConnection(); $event.stopPropagation()') button.btn.btn-outline-danger.btn-sm((click)='clearLastConnection(); $event.stopPropagation()')
i.fas.fa-trash i.fas.fa-trash
.list-group.mt-3.connections-list(*ngIf='childGroups.length') .list-group.mt-3.connections-list(*ngIf='connections.length')
ng-container(*ngFor='let group of childGroups') a.list-group-item.list-group-item-action.d-flex.align-items-center(
.list-group-item.list-group-item-action.d-flex.align-items-center( *ngFor='let connection of connections',
(click)='groupCollapsed[group.name] = !groupCollapsed[group.name]' (click)='connect(connection)'
) )
.fa.fa-fw.fa-chevron-right(*ngIf='groupCollapsed[group.name]') .mr-2 {{connection.name}}
.fa.fa-fw.fa-chevron-down(*ngIf='!groupCollapsed[group.name]') .text-muted {{connection.port}}
.ml-2 {{group.name || "Ungrouped"}}
ng-container(*ngIf='!groupCollapsed[group.name]')
.list-group-item.list-group-item-action.pl-5.d-flex.align-items-center(
*ngFor='let connection of group.connections',
(click)='connect(connection)'
)
.mr-2 {{connection.name}}
.text-muted {{connection.port}}
.list-group.mt-3(*ngIf='foundPorts.length') .list-group.mt-3(*ngIf='foundPorts.length')
a.list-group-item.list-group-item-action.d-flex.align-items-center( a.list-group-item.list-group-item-action.d-flex.align-items-center(

View File

@@ -4,7 +4,7 @@ import { ToastrService } from 'ngx-toastr'
import { ConfigService, AppService } from 'terminus-core' import { ConfigService, AppService } from 'terminus-core'
import { SettingsTabComponent } from 'terminus-settings' import { SettingsTabComponent } from 'terminus-settings'
import { SerialService } from '../services/serial.service' import { SerialService } from '../services/serial.service'
import { SerialConnection, SerialConnectionGroup, SerialPortInfo, BAUD_RATES } from '../api' import { SerialConnection, SerialPortInfo, BAUD_RATES } from '../api'
/** @hidden */ /** @hidden */
@Component({ @Component({
@@ -13,11 +13,8 @@ import { SerialConnection, SerialConnectionGroup, SerialPortInfo, BAUD_RATES } f
}) })
export class SerialModalComponent { export class SerialModalComponent {
connections: SerialConnection[] connections: SerialConnection[]
childFolders: SerialConnectionGroup[]
quickTarget: string quickTarget: string
lastConnection: SerialConnection|null = null lastConnection: SerialConnection|null = null
childGroups: SerialConnectionGroup[]
groupCollapsed: {[id: string]: boolean} = {}
foundPorts: SerialPortInfo[] = [] foundPorts: SerialPortInfo[] = []
constructor ( constructor (
@@ -33,8 +30,6 @@ export class SerialModalComponent {
if (window.localStorage.lastSerialConnection) { if (window.localStorage.lastSerialConnection) {
this.lastConnection = JSON.parse(window.localStorage.lastSerialConnection) this.lastConnection = JSON.parse(window.localStorage.lastSerialConnection)
} }
this.refresh()
this.foundPorts = await this.serial.listPorts() this.foundPorts = await this.serial.listPorts()
} }
@@ -47,7 +42,6 @@ export class SerialModalComponent {
} }
const connection: SerialConnection = { const connection: SerialConnection = {
name: this.quickTarget, name: this.quickTarget,
group: null,
port: path, port: path,
baudrate: baudrate, baudrate: baudrate,
databits: 8, databits: 8,
@@ -87,28 +81,6 @@ export class SerialModalComponent {
this.modalInstance.close() this.modalInstance.close()
} }
refresh () {
this.childGroups = []
let connections = this.connections
if (this.quickTarget) {
connections = connections.filter((connection: SerialConnection) => (connection.name + connection.group!).toLowerCase().includes(this.quickTarget))
}
for (const connection of connections) {
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
group = {
name: connection.group!,
connections: [],
}
this.childGroups.push(group!)
}
group.connections.push(connection)
}
}
async connectFoundPort (port: SerialPortInfo) { async connectFoundPort (port: SerialPortInfo) {
const rate = await this.app.showSelector('Baud rate', BAUD_RATES.map(x => ({ const rate = await this.app.showSelector('Baud rate', BAUD_RATES.map(x => ({
name: x.toString(), result: x, name: x.toString(), result: x,

View File

@@ -1,27 +1,15 @@
h3 Connections h3 Connections
.list-group.list-group-flush.mt-3.mb-3 .list-group.list-group-flush.mt-3.mb-3
ng-container(*ngFor='let group of childGroups') .list-group-item.list-group-item-action.d-flex.align-items-center(
.list-group-item.list-group-item-action.d-flex.align-items-center( *ngFor='let connection of connections',
(click)='groupCollapsed[group.name] = !groupCollapsed[group.name]' (click)='editConnection(connection)'
) )
.fa.fa-fw.fa-chevron-right(*ngIf='groupCollapsed[group.name]') .mr-auto
.fa.fa-fw.fa-chevron-down(*ngIf='!groupCollapsed[group.name]') div {{connection.name}}
span.ml-3.mr-auto {{group.name || "Ungrouped"}} .text-muted {{connection.port}}
button.btn.btn-outline-info.ml-2((click)='editGroup(group)') button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteConnection(connection)')
i.fas.fa-edit i.fas.fa-trash
button.btn.btn-outline-danger.ml-1((click)='deleteGroup(group)')
i.fas.fa-trash
ng-container(*ngIf='!groupCollapsed[group.name]')
.list-group-item.list-group-item-action.pl-5.d-flex.align-items-center(
*ngFor='let connection of group.connections',
(click)='editConnection(connection)'
)
.mr-auto
div {{connection.name}}
.text-muted {{connection.port}}
button.btn.btn-outline-danger.ml-1((click)='$event.stopPropagation(); deleteConnection(connection)')
i.fas.fa-trash
button.btn.btn-primary((click)='createConnection()') button.btn.btn-primary((click)='createConnection()')
i.fas.fa-fw.fa-plus i.fas.fa-fw.fa-plus

View File

@@ -1,9 +1,8 @@
import { Component } from '@angular/core' import { Component } from '@angular/core'
import { NgbModal } from '@ng-bootstrap/ng-bootstrap' import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { ConfigService, ElectronService, HostAppService } from 'terminus-core' import { ConfigService, ElectronService, HostAppService } from 'terminus-core'
import { SerialConnection, SerialConnectionGroup } from '../api' import { SerialConnection } from '../api'
import { EditConnectionModalComponent } from './editConnectionModal.component' import { EditConnectionModalComponent } from './editConnectionModal.component'
import { PromptModalComponent } from './promptModal.component'
/** @hidden */ /** @hidden */
@Component({ @Component({
@@ -11,8 +10,6 @@ import { PromptModalComponent } from './promptModal.component'
}) })
export class SerialSettingsTabComponent { export class SerialSettingsTabComponent {
connections: SerialConnection[] connections: SerialConnection[]
childGroups: SerialConnectionGroup[]
groupCollapsed: {[id: string]: boolean} = {}
constructor ( constructor (
public config: ConfigService, public config: ConfigService,
@@ -27,7 +24,6 @@ export class SerialSettingsTabComponent {
createConnection () { createConnection () {
const connection: SerialConnection = { const connection: SerialConnection = {
name: '', name: '',
group: null,
port: '', port: '',
baudrate: 115200, baudrate: 115200,
databits: 8, databits: 8,
@@ -77,55 +73,7 @@ export class SerialSettingsTabComponent {
} }
} }
editGroup (group: SerialConnectionGroup) {
const modal = this.ngbModal.open(PromptModalComponent)
modal.componentInstance.prompt = 'New group name'
modal.componentInstance.value = group.name
modal.result.then(result => {
if (result) {
for (const connection of this.connections.filter(x => x.group === group.name)) {
connection.group = result.value
}
this.config.store.serial.connections = this.connections
this.config.save()
this.refresh()
}
})
}
async deleteGroup (group: SerialConnectionGroup) {
if ((await this.electron.showMessageBox(
this.hostApp.getWindow(),
{
type: 'warning',
message: `Delete "${group}"?`,
buttons: ['Keep', 'Delete'],
defaultId: 1,
}
)).response === 1) {
for (const connection of this.connections.filter(x => x.group === group.name)) {
connection.group = null
}
this.config.save()
this.refresh()
}
}
refresh () { refresh () {
this.connections = this.config.store.serial.connections this.connections = this.config.store.serial.connections
this.childGroups = []
for (const connection of this.connections) {
connection.group = connection.group || null
let group = this.childGroups.find(x => x.name === connection.group)
if (!group) {
group = {
name: connection.group!,
connections: [],
}
this.childGroups.push(group!)
}
group.connections.push(connection)
}
} }
} }

View File

@@ -1,10 +1,15 @@
.serial-tab-toolbar .tab-toolbar
.btn.btn-outline-secondary.reveal-button .btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h i.fas.fa-ellipsis-h
.toolbar(*ngIf='session', [class.show]='!session.open') .toolbar(*ngIf='session', [class.show]='!session.open')
i.fas.fa-circle.text-success.mr-2(*ngIf='session.open') i.fas.fa-circle.text-success.mr-2(*ngIf='session.open')
i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open') i.fas.fa-circle.text-danger.mr-2(*ngIf='!session.open')
strong.mr-auto(*ngIf='session') {{session.connection.port}} ({{session.connection.baudrate}}) strong(*ngIf='session') {{session.connection.port}} ({{session.connection.baudrate}})
.mr-auto
button.btn.btn-secondary.mr-3((click)='changeBaudRate()', *ngIf='session.open')
span Change baud rate
button.btn.btn-info((click)='reconnect()', *ngIf='!session.open') button.btn.btn-info((click)='reconnect()', *ngIf='!session.open')
i.fas.fa-reload i.fas.fa-reload

View File

@@ -1,71 +1,7 @@
@import '../../../terminus-ssh/src/components/sshTab.component.scss';
:host { :host {
flex: auto; select {
display: flex; width: auto;
flex-direction: column;
overflow: hidden;
position: relative;
&> .content {
flex: auto;
position: relative;
display: block;
overflow: hidden;
margin: 15px;
}
.serial-tab-toolbar {
position: absolute;
top: 0;
left: 0;
right: 0;
z-index: 4;
pointer-events: none;
.reveal-button {
position: absolute;
top: 10px;
right: 30px;
border-radius: 50%;
width: 35px;
padding: 0;
height: 35px;
line-height: 35px;
transition: 0.125s opacity;
opacity: .5;
pointer-events: all;
}
&:hover .reveal-button {
opacity: 0;
}
&:hover .toolbar {
opacity: 1;
}
.toolbar {
opacity: 0;
background: rgba(0, 0, 0, .75);
padding: 10px 20px;
transition: 0.25s opacity;
display: flex;
align-items: center;
z-index: 1;
will-change: transform;
&>* {
pointer-events: all;
}
}
&.show {
.reveal-button {
opacity: 0;
}
.toolbar {
opacity: 1;
}
}
} }
} }

View File

@@ -1,11 +1,10 @@
import colors from 'ansi-colors' import colors from 'ansi-colors'
import { Spinner } from 'cli-spinner' import { Spinner } from 'cli-spinner'
import { Component } from '@angular/core' import { Component } from '@angular/core'
// import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
import { first } from 'rxjs/operators' import { first } from 'rxjs/operators'
import { BaseTerminalTabComponent } from 'terminus-terminal' import { BaseTerminalTabComponent } from 'terminus-terminal'
import { SerialService } from '../services/serial.service' import { SerialService } from '../services/serial.service'
import { SerialConnection, SerialSession } from '../api' import { SerialConnection, SerialSession, BAUD_RATES } from '../api'
import { Subscription } from 'rxjs' import { Subscription } from 'rxjs'
/** @hidden */ /** @hidden */
@@ -19,12 +18,10 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
connection: SerialConnection connection: SerialConnection
serial: SerialService serial: SerialService
session: SerialSession session: SerialSession
// private ngbModal: NgbModal serialPort: any
private homeEndSubscription: Subscription private homeEndSubscription: Subscription
ngOnInit () { ngOnInit () {
// this.ngbModal = this.injector.get<NgbModal>(NgbModal)
this.logger = this.log.create('terminalTab') this.logger = this.log.create('terminalTab')
this.serial = this.injector.get(SerialService) this.serial = this.injector.get(SerialService)
@@ -77,7 +74,7 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
spinner.start() spinner.start()
try { try {
await this.serial.connectSession(this.session, (message: string) => { this.serialPort = await this.serial.connectSession(this.session, (message: string) => {
spinner.stop(true) spinner.stop(true)
this.write(message + '\r\n') this.write(message + '\r\n')
spinner.start() spinner.start()
@@ -104,6 +101,14 @@ export class SerialTabComponent extends BaseTerminalTabComponent {
this.initializeSession() this.initializeSession()
} }
async changeBaudRate () {
const rate = await this.app.showSelector('Baud rate', BAUD_RATES.map(x => ({
name: x.toString(), result: x,
})))
this.serialPort.update({ baudRate: rate })
this.connection.baudrate = rate
}
ngOnDestroy () { ngOnDestroy () {
this.homeEndSubscription.unsubscribe() this.homeEndSubscription.unsubscribe()
super.ngOnDestroy() super.ngOnDestroy()

View File

@@ -7,7 +7,7 @@ import { SerialTabComponent } from './components/serialTab.component'
@Injectable() @Injectable()
export class RecoveryProvider extends TabRecoveryProvider { export class RecoveryProvider extends TabRecoveryProvider {
async recover (recoveryToken: any): Promise<RecoveredTab|null> { async recover (recoveryToken: any): Promise<RecoveredTab|null> {
if (recoveryToken && recoveryToken.type === 'app:serial-tab') { if (recoveryToken?.type === 'app:serial-tab') {
return { return {
type: SerialTabComponent, type: SerialTabComponent,
options: { options: {

View File

@@ -38,7 +38,7 @@ export class SerialService {
return session return session
} }
async connectSession (session: SerialSession, _?: (s: any) => void): Promise<void> { async connectSession (session: SerialSession, _?: (s: any) => void): Promise<SerialPort> {
const serial = new SerialPort(session.connection.port, { autoOpen: false, baudRate: session.connection.baudrate, const serial = new SerialPort(session.connection.port, { autoOpen: false, baudRate: session.connection.baudrate,
dataBits: session.connection.databits, stopBits: session.connection.stopbits, parity: session.connection.parity, dataBits: session.connection.databits, stopBits: session.connection.stopbits, parity: session.connection.parity,
rtscts: session.connection.rtscts, xon: session.connection.xon, xoff: session.connection.xoff, rtscts: session.connection.rtscts, xon: session.connection.xon, xoff: session.connection.xoff,
@@ -68,5 +68,6 @@ export class SerialService {
} }
}) })
return serial
} }
} }

View File

@@ -1,4 +1,4 @@
.ssh-tab-toolbar .tab-toolbar
.btn.btn-outline-secondary.reveal-button .btn.btn-outline-secondary.reveal-button
i.fas.fa-ellipsis-h i.fas.fa-ellipsis-h
.toolbar(*ngIf='session', [class.show]='!session.open') .toolbar(*ngIf='session', [class.show]='!session.open')

View File

@@ -13,7 +13,7 @@
margin: 15px; margin: 15px;
} }
.ssh-tab-toolbar { > .tab-toolbar {
position: absolute; position: absolute;
top: 0; top: 0;
left: 0; left: 0;
@@ -41,6 +41,7 @@
&:hover .toolbar { &:hover .toolbar {
opacity: 1; opacity: 1;
transform: translate(0, 0);
} }
.toolbar { .toolbar {
@@ -52,10 +53,9 @@
align-items: center; align-items: center;
z-index: 1; z-index: 1;
will-change: transform; will-change: transform;
transform: translate(0, -100px);
&>* { transition: 0.25s transform ease-out;
pointer-events: all; pointer-events: all;
}
} }
&.show { &.show {
@@ -65,6 +65,7 @@
.toolbar { .toolbar {
opacity: 1; opacity: 1;
transform: translate(0, 0);
} }
} }
} }