From 6850ccc9e6585192f74394fd4961d8dcfba34a69 Mon Sep 17 00:00:00 2001 From: ElonH Date: Tue, 9 Jun 2020 01:12:08 +0800 Subject: [PATCH] feat(remote.detail): show remote features in fs info --- src/app/@dataflow/rclone/index.ts | 1 + .../rclone/operations-fsinfo-flow.ts | 73 +++++++++++++++ .../manager/homeMode/homeMode.component.ts | 2 + .../pages/manager/homeMode/remote.detail.ts | 89 +++++++++++++++++++ src/app/pages/manager/manager.component.ts | 8 +- src/app/pages/manager/manager.module.ts | 4 + 6 files changed, 176 insertions(+), 1 deletion(-) create mode 100644 src/app/@dataflow/rclone/operations-fsinfo-flow.ts create mode 100644 src/app/pages/manager/homeMode/remote.detail.ts diff --git a/src/app/@dataflow/rclone/index.ts b/src/app/@dataflow/rclone/index.ts index 34f0457..66e5698 100644 --- a/src/app/@dataflow/rclone/index.ts +++ b/src/app/@dataflow/rclone/index.ts @@ -18,3 +18,4 @@ export * from './core-memstats-flow'; export * from './core-bwlimit-flow'; export * from './options-get-flow'; export * from './options-set-flow'; +export * from './operations-fsinfo-flow'; diff --git a/src/app/@dataflow/rclone/operations-fsinfo-flow.ts b/src/app/@dataflow/rclone/operations-fsinfo-flow.ts new file mode 100644 index 0000000..af964b5 --- /dev/null +++ b/src/app/@dataflow/rclone/operations-fsinfo-flow.ts @@ -0,0 +1,73 @@ +import { AjaxFlowInteralNode, CombErr, FlowOutNode } from '../core'; +import { IRcloneServer, NavigationFlowOutNode } from '../extra'; +import { PostFlow } from './post-flow'; + +export interface OperationsFsinfoFlowParamsNode { + /** a remote name string eg "drive:" */ + fs: string; +} + +export interface OperationsFsinfoFlowInNode extends NavigationFlowOutNode, IRcloneServer {} + +export interface OperationsFsinfoFlowOutItemNode { + Features: { + About: boolean; + BucketBased: boolean; + CanHaveEmptyDirectories: boolean; + CaseInsensitive: boolean; + ChangeNotify: boolean; + CleanUp: boolean; + Copy: boolean; + DirCacheFlush: boolean; + DirMove: boolean; + DuplicateFiles: boolean; + GetTier: boolean; + ListR: boolean; + MergeDirs: boolean; + Move: boolean; + OpenWriterAt: boolean; + PublicLink: boolean; + Purge: boolean; + PutStream: boolean; + PutUnchecked: boolean; + ReadMimeType: boolean; + ServerSideAcrossConfigs: boolean; + SetTier: boolean; + SetWrapper: boolean; + UnWrap: boolean; + WrapFs: boolean; + WriteMimeType: boolean; + }; + // Names of hashes available + Hashes: ('MD5' | 'SHA-1' | 'DropboxHash' | 'QuickXorHash')[]; + // Name as created + Name: string; + // Precision of timestamps in ns + Precision: number; + // Path as created + Root: string; + // how the remote will appear in logs + String: string; +} +export interface OperationsFsinfoFlowOutNode extends FlowOutNode { + 'fs-info': OperationsFsinfoFlowOutItemNode; +} + +export abstract class OperationsFsinfoFlow extends PostFlow< + OperationsFsinfoFlowInNode, + OperationsFsinfoFlowOutNode, + OperationsFsinfoFlowParamsNode +> { + // public prerequest$: Observable>; + protected cmd = 'operations/fsinfo'; + protected cacheSupport = true; + protected params = (pre: CombErr): OperationsFsinfoFlowParamsNode => { + if (pre[1].length !== 0) return {} as any; + return { fs: `${pre[0].remote}:` }; + }; + protected reconstructAjaxResult(x: AjaxFlowInteralNode): CombErr { + if (x[1].length !== 0) return [{}, x[1]] as any; + const rsp = x[0].ajaxRsp.response; + return [{ 'fs-info': rsp }, []]; + } +} diff --git a/src/app/pages/manager/homeMode/homeMode.component.ts b/src/app/pages/manager/homeMode/homeMode.component.ts index 1317007..4875da8 100644 --- a/src/app/pages/manager/homeMode/homeMode.component.ts +++ b/src/app/pages/manager/homeMode/homeMode.component.ts @@ -26,6 +26,7 @@ import { ConnectionService } from '../../connection.service'; @@ -41,6 +42,7 @@ export class HomeModeComponent implements OnInit { @Input() detail: boolean; @Output() jump = new EventEmitter(); + @Output() showDetail = new EventEmitter(); remotesTrigger = new Subject(); remotes$: ListRemotesFlow; diff --git a/src/app/pages/manager/homeMode/remote.detail.ts b/src/app/pages/manager/homeMode/remote.detail.ts new file mode 100644 index 0000000..f16a14d --- /dev/null +++ b/src/app/pages/manager/homeMode/remote.detail.ts @@ -0,0 +1,89 @@ +import { Component, OnInit } from '@angular/core'; +import { combineLatest, Subject } from 'rxjs'; +import { map } from 'rxjs/operators'; +import { CombErr } from '../../../@dataflow/core'; +import { NavigationFlowOutNode } from '../../../@dataflow/extra'; +import { OperationsFsinfoFlow, OperationsFsinfoFlowInNode } from '../../../@dataflow/rclone'; +import { ConnectionService } from '../../connection.service'; + +@Component({ + selector: 'app-home-remote-detail', + template: ` +
{{ _remote }}
+ + + Feature + + + + + +
{{ item.k }}
+
+
+
+
+
+ `, + styles: [ + ` + h5 { + padding: 0 1.25rem; + } + nb-list { + margin: 0 -0.5rem; + } + nb-list-item { + padding: 0.5rem 0; + } + nb-list-item > nb-icon { + width: 1rem; + height: 1rem; + } + nb-list-item > div { + padding-left: 0.5rem; + } + `, + ], +}) +export class RemoteDetailComponent implements OnInit { + constructor(private cmdService: ConnectionService) {} + protected _remote = ''; + protected loadingFsinfo = false; + protected feature: { k: string; v: boolean }[] = []; + set remote(x: NavigationFlowOutNode) { + this._remote = x.remote || ''; + this.loadingFsinfo = true; + this.trigger.next(x.remote); + } + + private trigger = new Subject(); + fsinfo$: OperationsFsinfoFlow; + ngOnInit() { + const outer = this; + this.loadingFsinfo = false; + this.fsinfo$ = new (class extends OperationsFsinfoFlow { + public prerequest$ = combineLatest([ + outer.trigger, + outer.cmdService.listCmd$.verify(this.cmd), + ]).pipe( + map( + ([remote, cmdNode]): CombErr => { + if (cmdNode[1].length !== 0) return [{}, cmdNode[1]] as any; + return [{ ...cmdNode[0], remote }, []]; + } + ) + ); + })(); + this.fsinfo$.deploy(); + this.fsinfo$.getOutput().subscribe(x => { + this.loadingFsinfo = false; + if (x[1].length !== 0) return; + const fsinfo = x[0]['fs-info']; + this.feature = Object.keys(fsinfo.Features).map(k => ({ k, v: fsinfo.Features[k] })); + }); + } +} diff --git a/src/app/pages/manager/manager.component.ts b/src/app/pages/manager/manager.component.ts index 1da0801..eda3873 100644 --- a/src/app/pages/manager/manager.component.ts +++ b/src/app/pages/manager/manager.component.ts @@ -16,6 +16,7 @@ import { ClipboardService } from './clipboard/clipboard.service'; import { MkdirDialogComponent } from './dialogs/mkdir.dialog'; import { FileModeComponent } from './fileMode/fileMode.component'; import { HomeModeComponent } from './homeMode/homeMode.component'; +import { RemoteDetailComponent } from './homeMode/remote.detail'; import { TasksDialogComponent } from './tasks/tasks.dialog'; import { TaskService } from './tasks/tasks.service'; @@ -37,6 +38,7 @@ import { TaskService } from './tasks/tasks.service'; *ngIf="homeMode" [detail]="detailExpanded" (jump)="addrJump($event)" + (showDetail)="remoteDetail.remote = $event" > @@ -45,7 +47,7 @@ import { TaskService } from './tasks/tasks.service'; - 123 + @@ -98,6 +100,9 @@ import { TaskService } from './tasks/tasks.service'; top: calc(4.75rem * 2 + 0.05rem) !important; bottom: 65px !important; } + :host nb-sidebar ::ng-deep .scrollable { + padding: 1.25rem 0 !important; + } .subcolumn { margin-bottom: 4.75rem; margin-top: 1.5rem; @@ -154,6 +159,7 @@ export class ManagerComponent implements OnInit, OnDestroy { @ViewChild(FileModeComponent) file: FileModeComponent; @ViewChild(HomeModeComponent) home: HomeModeComponent; @ViewChild(NbSidebarComponent) detail: NbSidebarComponent; + @ViewChild(RemoteDetailComponent) remoteDetail: RemoteDetailComponent; private navTrigger = new Subject(); nav$: NavigationFlow; diff --git a/src/app/pages/manager/manager.module.ts b/src/app/pages/manager/manager.module.ts index 071a6f1..0f1da00 100644 --- a/src/app/pages/manager/manager.module.ts +++ b/src/app/pages/manager/manager.module.ts @@ -11,6 +11,7 @@ import { NbIconModule, NbInputModule, NbLayoutModule, + NbListModule, NbProgressBarModule, NbSidebarModule, NbSpinnerModule, @@ -26,6 +27,7 @@ import { FileModeComponent } from './fileMode/fileMode.component'; import { ListViewComponent } from './fileMode/listView/listView.component'; import { HomeModeComponent } from './homeMode/homeMode.component'; import { RemoteComponent } from './homeMode/remote.component'; +import { RemoteDetailComponent } from './homeMode/remote.detail'; import { ManagerRoutingModule } from './manager-routing.module'; import { ManagerComponent } from './manager.component'; import { TasksDialogComponent } from './tasks/tasks.dialog'; @@ -42,6 +44,7 @@ import { TasksDialogComponent } from './tasks/tasks.dialog'; ClipboardRemotesTableComponent, TasksDialogComponent, MkdirDialogComponent, + RemoteDetailComponent, ], imports: [ CommonModule, @@ -61,6 +64,7 @@ import { TasksDialogComponent } from './tasks/tasks.dialog'; NbTabsetModule, NbAccordionModule, NbSpinnerModule, + NbListModule, ], }) export class ManagerModule {}