mirror of
https://github.com/Eugeny/tabby
synced 2024-11-16 09:48:05 +00:00
Organize the connections in folders.
Filter connections in quick connect. Need more custom CSS to handle long connection list. See also #403
This commit is contained in:
parent
f367ea6c74
commit
0eaf857b02
7 changed files with 172 additions and 6 deletions
|
@ -12,6 +12,7 @@ export interface SSHConnection {
|
|||
user: string
|
||||
password?: string
|
||||
privateKey?: string
|
||||
path?: string
|
||||
scripts?: LoginScript[]
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
label Name
|
||||
input.form-control(
|
||||
type='text',
|
||||
autofocus,
|
||||
[(ngModel)]='connection.name',
|
||||
)
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
.modal-body
|
||||
input.form-control(
|
||||
[type]='password ? "password" : "text"',
|
||||
autofocus,
|
||||
[(ngModel)]='value',
|
||||
#input,
|
||||
[placeholder]='prompt',
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
[(ngModel)]='quickTarget',
|
||||
autofocus,
|
||||
placeholder='Quick connect: [user@]host[:port]',
|
||||
(ngModelChange)='filter()',
|
||||
(keyup.enter)='quickConnect()'
|
||||
)
|
||||
|
||||
|
@ -13,7 +14,10 @@
|
|||
span {{lastConnection.name}}
|
||||
|
||||
.list-group.mt-3
|
||||
a.list-group-item.list-group-item-action(*ngFor='let connection of connections', (click)='connect(connection)')
|
||||
a.list-group-item.list-group-item-action(*ngFor='let folder of childFolders', (click)='cd(folder)')
|
||||
i.fa.fa-fw.fa-folder
|
||||
span {{folder}}
|
||||
a.list-group-item.list-group-item-action(*ngFor='let connection of childConnections', (click)='connect(connection)')
|
||||
i.fa.fa-fw.fa-globe
|
||||
span {{connection.name}}
|
||||
a.list-group-item.list-group-item-action((click)='manageConnections()')
|
||||
|
|
|
@ -14,6 +14,9 @@ export class SSHModalComponent {
|
|||
connections: SSHConnection[]
|
||||
quickTarget: string
|
||||
lastConnection: SSHConnection
|
||||
currentPath: string
|
||||
childFolders: string[]
|
||||
childConnections: SSHConnection[]
|
||||
|
||||
constructor (
|
||||
public modalInstance: NgbActiveModal,
|
||||
|
@ -28,6 +31,19 @@ export class SSHModalComponent {
|
|||
if (window.localStorage.lastConnection) {
|
||||
this.lastConnection = JSON.parse(window.localStorage.lastConnection)
|
||||
}
|
||||
this.currentPath = "/"
|
||||
this.findChildren()
|
||||
}
|
||||
|
||||
filter () {
|
||||
if (!this.quickTarget) {
|
||||
this.findChildren()
|
||||
}
|
||||
else
|
||||
{
|
||||
this.childFolders = [];
|
||||
this.childConnections = this.connections.filter(connection => connection.name.toLowerCase().indexOf(this.quickTarget) >= 0)
|
||||
}
|
||||
}
|
||||
|
||||
quickConnect () {
|
||||
|
@ -65,4 +81,38 @@ export class SSHModalComponent {
|
|||
close () {
|
||||
this.modalInstance.close()
|
||||
}
|
||||
|
||||
findChildren () {
|
||||
this.childFolders = []
|
||||
this.childConnections = []
|
||||
|
||||
if (this.currentPath != "/")
|
||||
this.childFolders.push("..")
|
||||
|
||||
for (let connection of this.connections) {
|
||||
if (!connection.path)
|
||||
connection.path = "/"
|
||||
if (connection.path.startsWith(this.currentPath)) {
|
||||
let folder = connection.path.substr(this.currentPath.length, connection.path.indexOf("/", this.currentPath.length) - this.currentPath.length)
|
||||
if (folder.length == 0) {
|
||||
this.childConnections.push(connection)
|
||||
}
|
||||
else if (this.childFolders.indexOf(folder) < 0) {
|
||||
this.childFolders.push(folder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cd (path: string) {
|
||||
if (path == "..") {
|
||||
path = this.currentPath.substr(0, this.currentPath.lastIndexOf("/", this.currentPath.length - 2) + 1)
|
||||
}
|
||||
else {
|
||||
path = this.currentPath + path + '/'
|
||||
}
|
||||
|
||||
this.currentPath = path
|
||||
this.findChildren()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,33 @@
|
|||
h3 Connections
|
||||
h3 Connections ({{currentPath}})
|
||||
|
||||
.list-group.mt-3.mb-3
|
||||
.list-group-item(*ngFor='let connection of connections')
|
||||
.list-group-item(*ngFor='let folder of childFolders')
|
||||
.d-flex.w-100
|
||||
a.mr-auto.list-group-item-action((click)='cd(folder)')
|
||||
div.fa.fa-fw.fa-folder
|
||||
span.ml-2 {{folder}}
|
||||
button.btn.btn-outline-info.ml-2(*ngIf='folder != ".."', (click)='editFolder(folder)')
|
||||
i.fa.fa-pencil
|
||||
button.btn.btn-outline-info.disabled.ml-2(*ngIf='folder == ".."')
|
||||
i.fa.fa-pencil
|
||||
button.btn.btn-outline-danger.ml-1(*ngIf='folder != ".."', (click)='deleteFolder(folder)')
|
||||
i.fa.fa-trash-o
|
||||
button.btn.btn-outline-danger.disabled.ml-1(*ngIf='folder == ".."')
|
||||
i.fa.fa-trash-o
|
||||
.list-group-item(*ngFor='let connection of childConnections')
|
||||
.d-flex.w-100
|
||||
.mr-auto
|
||||
div
|
||||
span {{connection.name}}
|
||||
div.fa.fa-fw.fa-globe
|
||||
span.ml-2 {{connection.name}}
|
||||
.text-muted {{connection.host}}
|
||||
button.btn.btn-outline-info.ml-2((click)='editConnection(connection)')
|
||||
i.fa.fa-pencil
|
||||
button.btn.btn-outline-danger.ml-1((click)='deleteConnection(connection)')
|
||||
i.fa.fa-trash-o
|
||||
|
||||
button.btn.btn-outline-primary((click)='createConnection()') Add connection
|
||||
button.btn.btn-outline-primary((click)='createFolder()')
|
||||
div.fa.fa-fw.fa-folder
|
||||
span.ml-2 Add Folder
|
||||
button.btn.btn-outline-primary.ml-2((click)='createConnection()')
|
||||
div.fa.fa-fw.fa-globe
|
||||
span.ml-2 Add connection
|
||||
|
|
|
@ -3,18 +3,24 @@ import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
|
|||
import { ConfigService } from 'terminus-core'
|
||||
import { SSHConnection } from '../api'
|
||||
import { EditConnectionModalComponent } from './editConnectionModal.component'
|
||||
import { PromptModalComponent } from './promptModal.component'
|
||||
|
||||
@Component({
|
||||
template: require('./sshSettingsTab.component.pug'),
|
||||
})
|
||||
export class SSHSettingsTabComponent {
|
||||
connections: SSHConnection[]
|
||||
currentPath: string
|
||||
childFolders: string[]
|
||||
childConnections: SSHConnection[]
|
||||
|
||||
constructor (
|
||||
public config: ConfigService,
|
||||
private ngbModal: NgbModal,
|
||||
) {
|
||||
this.connections = this.config.store.ssh.connections
|
||||
this.currentPath = "/"
|
||||
this.findChildren()
|
||||
}
|
||||
|
||||
createConnection () {
|
||||
|
@ -23,6 +29,7 @@ export class SSHSettingsTabComponent {
|
|||
host: '',
|
||||
port: 22,
|
||||
user: 'root',
|
||||
path: this.currentPath
|
||||
}
|
||||
|
||||
let modal = this.ngbModal.open(EditConnectionModalComponent)
|
||||
|
@ -31,6 +38,7 @@ export class SSHSettingsTabComponent {
|
|||
this.connections.push(result)
|
||||
this.config.store.ssh.connections = this.connections
|
||||
this.config.save()
|
||||
this.childConnections.push(result)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -48,6 +56,89 @@ export class SSHSettingsTabComponent {
|
|||
this.connections = this.connections.filter(x => x !== connection)
|
||||
this.config.store.ssh.connections = this.connections
|
||||
this.config.save()
|
||||
this.childConnections = this.connections.filter(x => x !== connection)
|
||||
}
|
||||
}
|
||||
|
||||
createFolder () {
|
||||
let modal = this.ngbModal.open(PromptModalComponent)
|
||||
modal.componentInstance.prompt = 'folder name'
|
||||
modal.componentInstance.password = false
|
||||
modal.result.then(result => {
|
||||
if (result) {
|
||||
if (!this.childFolders.includes(result)) {
|
||||
this.childFolders.push(result)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
editFolder (folder: string) {
|
||||
let modal = this.ngbModal.open(PromptModalComponent)
|
||||
modal.componentInstance.prompt = 'folder name'
|
||||
modal.componentInstance.password = false
|
||||
modal.componentInstance.value = folder
|
||||
modal.result.then(result => {
|
||||
if (result) {
|
||||
let oldPath = this.currentPath + folder + "/"
|
||||
let newPath = this.currentPath + result + "/"
|
||||
for (let connection of this.connections) {
|
||||
connection.path = connection.path.replace(oldPath, newPath)
|
||||
}
|
||||
let i = this.childFolders.indexOf(folder)
|
||||
if (this.childFolders.includes(result)) {
|
||||
this.childFolders.splice(i, 1)
|
||||
}
|
||||
else {
|
||||
this.childFolders.splice(i, 1, result)
|
||||
}
|
||||
this.config.save()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
deleteFolder (folder: string) {
|
||||
if (confirm(`Delete "${folder}"?`)) {
|
||||
let oldPath = this.currentPath + folder + "/"
|
||||
for (let connection of this.connections) {
|
||||
connection.path = connection.path.replace(oldPath, this.currentPath)
|
||||
}
|
||||
this.config.save()
|
||||
this.findChildren()
|
||||
}
|
||||
}
|
||||
|
||||
findChildren () {
|
||||
this.childFolders = []
|
||||
this.childConnections = []
|
||||
|
||||
if (this.currentPath != "/")
|
||||
this.childFolders.push("..")
|
||||
|
||||
for (let connection of this.connections) {
|
||||
if (!connection.path)
|
||||
connection.path = "/"
|
||||
if (connection.path.startsWith(this.currentPath)) {
|
||||
let folder = connection.path.substr(this.currentPath.length, connection.path.indexOf("/", this.currentPath.length) - this.currentPath.length)
|
||||
if (folder.length == 0) {
|
||||
this.childConnections.push(connection)
|
||||
}
|
||||
else if (this.childFolders.indexOf(folder) < 0) {
|
||||
this.childFolders.push(folder)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cd (path: string) {
|
||||
if (path == "..") {
|
||||
path = this.currentPath.substr(0, this.currentPath.lastIndexOf("/", this.currentPath.length - 2) + 1)
|
||||
}
|
||||
else {
|
||||
path = this.currentPath + path + '/'
|
||||
}
|
||||
|
||||
this.currentPath = path
|
||||
this.findChildren()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue