diff --git a/tabby-ssh/src/components/sftpCreateDirectoryModal.component.pug b/tabby-ssh/src/components/sftpCreateDirectoryModal.component.pug new file mode 100644 index 00000000..a559641c --- /dev/null +++ b/tabby-ssh/src/components/sftpCreateDirectoryModal.component.pug @@ -0,0 +1,12 @@ +.modal-body + label(translate) Name for the new directory + .form-group.w-100.mr-2 + input.form-control( + type='text', + [(ngModel)]='directoryName', + ) + + +.modal-footer + button.btn.btn-success((click)='create()', translate) Create + button.btn.btn-danger((click)='cancel()', translate) Cancel diff --git a/tabby-ssh/src/components/sftpCreateDirectoryModal.component.ts b/tabby-ssh/src/components/sftpCreateDirectoryModal.component.ts new file mode 100644 index 00000000..85b02b0b --- /dev/null +++ b/tabby-ssh/src/components/sftpCreateDirectoryModal.component.ts @@ -0,0 +1,24 @@ +import { Component } from '@angular/core' +import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap' +import { BaseComponent } from 'tabby-core' + +/** @hidden */ +@Component({ + template: require('./sftpCreateDirectoryModal.component.pug'), +}) +export class SFTPCreateDirectoryModalComponent extends BaseComponent { + directoryName: string + + constructor ( + private modalInstance: NgbActiveModal, + ) { + super() + } + + create (): void { + this.modalInstance.close(this.directoryName) + } + cancel (): void { + this.modalInstance.close('') + } +} diff --git a/tabby-ssh/src/components/sftpPanel.component.pug b/tabby-ssh/src/components/sftpPanel.component.pug index 7007b5f5..cbfa705d 100644 --- a/tabby-ssh/src/components/sftpPanel.component.pug +++ b/tabby-ssh/src/components/sftpPanel.component.pug @@ -6,6 +6,10 @@ (click)='navigate(segment.path)' ) {{segment.name}} + button.btn.btn-link.btn-sm.d-flex((click)='openCreateDirectoryModal()') + i.fas.fa-plus.mr-1 + div(translate) Create directory + button.btn.btn-link.btn-sm.d-flex((click)='upload()') i.fas.fa-upload.mr-1 div(translate) Upload diff --git a/tabby-ssh/src/components/sftpPanel.component.ts b/tabby-ssh/src/components/sftpPanel.component.ts index 96ba5ee0..5a792d4a 100644 --- a/tabby-ssh/src/components/sftpPanel.component.ts +++ b/tabby-ssh/src/components/sftpPanel.component.ts @@ -5,6 +5,8 @@ import { FileUpload, MenuItemOptions, NotificationsService, PlatformService } fr import { SFTPSession, SFTPFile } from '../session/sftp' import { SSHSession } from '../session/ssh' import { SFTPContextMenuItemProvider } from '../api' +import { NgbModal } from '@ng-bootstrap/ng-bootstrap' +import { SFTPCreateDirectoryModalComponent } from './sftpCreateDirectoryModal.component' interface PathSegment { name: string @@ -26,6 +28,7 @@ export class SFTPPanelComponent { pathSegments: PathSegment[] = [] constructor ( + private ngbModal: NgbModal, private platform: PlatformService, private notifications: NotificationsService, @Optional() @Inject(SFTPContextMenuItemProvider) protected contextMenuProviders: SFTPContextMenuItemProvider[], @@ -106,6 +109,19 @@ export class SFTPPanelComponent { } } + async openCreateDirectoryModal (): Promise { + const modal = this.ngbModal.open(SFTPCreateDirectoryModalComponent) + const directoryName = await modal.result + if (directoryName !== '') { + this.sftp.mkdir(path.join(this.path, directoryName)).then(() => { + this.notifications.notice('The directory was created successfully') + this.navigate(path.join(this.path, directoryName)) + }).catch(() => { + this.notifications.error('The directory could not be created') + }) + } + } + async upload (): Promise { const transfers = await this.platform.startUpload({ multiple: true }) await Promise.all(transfers.map(t => this.uploadOne(t))) diff --git a/tabby-ssh/src/index.ts b/tabby-ssh/src/index.ts index 750838e5..e970b8f3 100644 --- a/tabby-ssh/src/index.ts +++ b/tabby-ssh/src/index.ts @@ -26,6 +26,7 @@ import { SFTPContextMenu } from './tabContextMenu' import { SSHProfilesService } from './profiles' import { SFTPContextMenuItemProvider } from './api/contextMenu' import { CommonSFTPContextMenu } from './sftpContextMenu' +import { SFTPCreateDirectoryModalComponent } from './components/sftpCreateDirectoryModal.component' /** @hidden */ @NgModule({ @@ -50,6 +51,7 @@ import { CommonSFTPContextMenu } from './sftpContextMenu' entryComponents: [ SSHProfileSettingsComponent, SFTPDeleteModalComponent, + SFTPCreateDirectoryModalComponent, SSHPortForwardingModalComponent, SSHSettingsTabComponent, SSHTabComponent, @@ -58,6 +60,7 @@ import { CommonSFTPContextMenu } from './sftpContextMenu' declarations: [ SSHProfileSettingsComponent, SFTPDeleteModalComponent, + SFTPCreateDirectoryModalComponent, SSHPortForwardingModalComponent, SSHPortForwardingConfigComponent, SSHSettingsTabComponent, diff --git a/tabby-ssh/src/session/sftp.ts b/tabby-ssh/src/session/sftp.ts index 4c85e70c..b85a41a5 100644 --- a/tabby-ssh/src/session/sftp.ts +++ b/tabby-ssh/src/session/sftp.ts @@ -123,6 +123,11 @@ export class SFTPSession { await promisify((f: any) => this.sftp.rmdir(p, f))() } + async mkdir (p: string): Promise { + this.logger.debug('mkdir', p) + await promisify((f: any) => this.sftp.mkdir(p, f))() + } + async rename (oldPath: string, newPath: string): Promise { this.logger.debug('rename', oldPath, newPath) await promisify((f: any) => this.sftp.rename(oldPath, newPath, f))() diff --git a/tabby-ssh/src/sftpContextMenu.ts b/tabby-ssh/src/sftpContextMenu.ts index b1e0cff9..5a3a8213 100644 --- a/tabby-ssh/src/sftpContextMenu.ts +++ b/tabby-ssh/src/sftpContextMenu.ts @@ -22,6 +22,12 @@ export class CommonSFTPContextMenu extends SFTPContextMenuItemProvider { async getItems (item: SFTPFile, panel: SFTPPanelComponent): Promise { return [ + { + click: async () => { + await panel.openCreateDirectoryModal() + }, + label: this.translate.instant('Create directory'), + }, { click: async () => { if ((await this.platform.showMessageBox({