-
Notifications
You must be signed in to change notification settings - Fork 44
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(clipboard): a task storage center
user want to copy, move or delete item, the source item will storage clipboard service temporarily. for copy and move operation, until user click paste button on destination dir, the real tasks are commit to rclone server. For delete operation, until user click confirm button, the remove tasks are post to remote.
- Loading branch information
Showing
10 changed files
with
380 additions
and
26 deletions.
There are no files selected for viewing
27 changes: 27 additions & 0 deletions
27
...pages/manager/clipboard/clipboard-remotes-table/clipboard-remotes-table.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* tslint:disable:no-unused-variable */ | ||
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { By } from '@angular/platform-browser'; | ||
import { DebugElement } from '@angular/core'; | ||
|
||
import { ClipboardRemotesTableComponent } from './clipboard-remotes-table.component'; | ||
|
||
describe('ClipboardRemotesTableComponent', () => { | ||
let component: ClipboardRemotesTableComponent; | ||
let fixture: ComponentFixture<ClipboardRemotesTableComponent>; | ||
|
||
beforeEach(async(() => { | ||
TestBed.configureTestingModule({ | ||
declarations: [ClipboardRemotesTableComponent], | ||
}).compileComponents(); | ||
})); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(ClipboardRemotesTableComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
95 changes: 95 additions & 0 deletions
95
src/app/pages/manager/clipboard/clipboard-remotes-table/clipboard-remotes-table.component.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import { Component, OnInit, Input, ViewChild } from '@angular/core'; | ||
import { IManipulate, ClipboardService } from '../clipboard.service'; | ||
import { Config, Columns, DefaultConfig, APIDefinition, API } from 'ngx-easy-table'; | ||
|
||
type IRemotesTableItem = { | ||
remote: string; | ||
children: string[]; | ||
}; | ||
|
||
@Component({ | ||
selector: 'clipboard-remotes-table', | ||
template: ` | ||
<ngx-table | ||
#remotesTable | ||
[configuration]="configuration" | ||
[data]="data" | ||
[id]="'remotes-tab-' + oper" | ||
[detailsTemplate]="detailsTemplate" | ||
[columns]="columns" | ||
> | ||
<ng-template let-row let-rowIdx="index"> | ||
<td>{{ row.remote }}</td> | ||
<td>{{ row.children.length }}</td> | ||
<td> | ||
<button nbButton (click)="toggleDatail($event, rowIdx)">Detail</button> | ||
</td> | ||
</ng-template> | ||
</ngx-table> | ||
<ng-template #detailsTemplate let-row let-index="index"> | ||
<ngx-table | ||
[configuration]="detailConfiguration" | ||
[data]="row.children" | ||
[detailsTemplate]="detailsTemplate" | ||
[columns]="detailColumns" | ||
> | ||
<ng-template let-row> | ||
<td>{{ row }}</td> | ||
</ng-template> | ||
</ngx-table> | ||
</ng-template> | ||
`, | ||
styles: [], | ||
}) | ||
export class ClipboardRemotesTableComponent implements OnInit { | ||
@Input() oper: IManipulate; | ||
constructor(private service: ClipboardService) {} | ||
public configuration: Config; | ||
public columns: Columns[] = [ | ||
{ key: 'remote', title: 'Remote', width: '80%' }, | ||
{ key: 'length', title: 'Total', width: '10%' }, | ||
{ key: '', title: 'Action', width: '10%' }, | ||
]; | ||
|
||
data: IRemotesTableItem[] = []; | ||
ngOnInit() { | ||
this.service.update$.getOutput().subscribe((node) => { | ||
if (node[1].length !== 0) return; | ||
this.data = this.transformData(node[0][this.oper]); | ||
}); | ||
|
||
this.configuration = { ...DefaultConfig }; | ||
this.configuration.detailsTemplate = true; | ||
this.configuration.tableLayout.hover = true; | ||
|
||
this.detailConfiguration = { ...DefaultConfig }; | ||
this.detailConfiguration.rows = 5; | ||
this.detailConfiguration.threeWaySort = true; | ||
} | ||
|
||
private transformData(pool: Set<string>): IRemotesTableItem[] { | ||
const internal = new Map<string, string[]>(); | ||
pool.forEach((x) => { | ||
const item = JSON.parse(x); | ||
if (!internal.has(item.remote)) internal.set(item.remote, []); | ||
internal.get(item.remote).push(item.path); | ||
}); | ||
const ans: IRemotesTableItem[] = []; | ||
internal.forEach((v, k) => { | ||
ans.push({ remote: k, children: v }); | ||
}); | ||
return ans; | ||
} | ||
|
||
@ViewChild('remotesTable') table: APIDefinition; | ||
toggleDatail($event: MouseEvent, rowidx: number) { | ||
$event.preventDefault(); | ||
this.table.apiEvent({ | ||
type: API.toggleRowIndex, | ||
value: rowidx, | ||
}); | ||
} | ||
|
||
public detailConfiguration: Config; | ||
public detailColumns: Columns[] = [{ key: '', title: 'Path', width: '85%' }]; | ||
} |
27 changes: 27 additions & 0 deletions
27
src/app/pages/manager/clipboard/clipboard.component.spec.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
/* tslint:disable:no-unused-variable */ | ||
import { async, ComponentFixture, TestBed } from '@angular/core/testing'; | ||
import { By } from '@angular/platform-browser'; | ||
import { DebugElement } from '@angular/core'; | ||
|
||
import { ClipboardComponent } from './clipboard.component'; | ||
|
||
describe('ClipboardComponent', () => { | ||
let component: ClipboardComponent; | ||
let fixture: ComponentFixture<ClipboardComponent>; | ||
|
||
beforeEach(async(() => { | ||
TestBed.configureTestingModule({ | ||
declarations: [ClipboardComponent], | ||
}).compileComponents(); | ||
})); | ||
|
||
beforeEach(() => { | ||
fixture = TestBed.createComponent(ClipboardComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
import { Component, OnInit } from '@angular/core'; | ||
import { ClipboardService, IManipulate } from './clipboard.service'; | ||
|
||
@Component({ | ||
selector: 'manager-clipboard', | ||
template: ` | ||
<nb-tabset fullWidth> | ||
<nb-tab | ||
*ngFor="let tab of data; index as tabIdx" | ||
[tabTitle]="tab.title" | ||
[tabIcon]="tab.icon" | ||
[badgeText]="tab.len" | ||
badgeStatus="primary" | ||
> | ||
<clipboard-remotes-table [oper]="tab.oper"> </clipboard-remotes-table> | ||
</nb-tab> | ||
</nb-tabset> | ||
`, | ||
styles: [], | ||
}) | ||
export class ClipboardComponent implements OnInit { | ||
data: { oper: IManipulate; title: string; icon: string; len: number }[] = [ | ||
{ oper: 'copy', title: 'Copy', icon: 'copy', len: 0 }, | ||
{ oper: 'move', title: 'Move', icon: 'move', len: 0 }, | ||
{ oper: 'del', title: 'Delete', icon: 'trash-2', len: 0 }, | ||
]; | ||
constructor(private service: ClipboardService) {} | ||
|
||
ngOnInit() { | ||
this.service.update$.getOutput().subscribe((node) => { | ||
if (node[1].length !== 0) return; | ||
this.data[ClipboardService.mapper['copy']].len = node[0].copy.size; | ||
this.data[ClipboardService.mapper['move']].len = node[0].move.size; | ||
this.data[ClipboardService.mapper['del']].len = node[0].del.size; | ||
}); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
/* tslint:disable:no-unused-variable */ | ||
|
||
import { TestBed, async, inject } from '@angular/core/testing'; | ||
import { ClipboardService } from './clipboard.service'; | ||
|
||
describe('Service: Clipboard', () => { | ||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
providers: [ClipboardService], | ||
}); | ||
}); | ||
|
||
it('should ...', inject([ClipboardService], (service: ClipboardService) => { | ||
expect(service).toBeTruthy(); | ||
})); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
import { Injectable } from '@angular/core'; | ||
import { Subject } from 'rxjs'; | ||
import { NothingFlow, CombErr } from 'src/app/@dataflow/core'; | ||
import { map } from 'rxjs/operators'; | ||
|
||
export type IManipulate = 'copy' | 'move' | 'del'; | ||
|
||
export interface ClipboardNode { | ||
copy: Set<string>; | ||
move: Set<string>; | ||
del: Set<string>; | ||
} | ||
|
||
@Injectable({ | ||
providedIn: 'root', | ||
}) | ||
export class ClipboardService { | ||
private sourcePool = [1, 2, 3].map(() => new Set<string>()); | ||
static readonly mapper: { [index: string]: number } = { | ||
copy: 0, | ||
move: 1, | ||
del: 2, | ||
}; | ||
|
||
static query(pools: ClipboardNode, remote: string, path: string): IManipulate { | ||
const item = JSON.stringify({ remote: remote, path: path }); | ||
if (pools.copy.has(item)) return 'copy'; | ||
if (pools.move.has(item)) return 'move'; | ||
if (pools.del.has(item)) return 'del'; | ||
} | ||
|
||
private excusiveAdd(pool: number, remote: string, path: string) { | ||
const item = JSON.stringify({ remote: remote, path: path }); | ||
this.sourcePool[pool].add(item); | ||
this.sourcePool.forEach((x, i) => { | ||
if (i === pool) return; | ||
if (x.has(item)) x.delete(item); | ||
}); | ||
} | ||
public manipulate(o: IManipulate, remote: string, path: string) { | ||
const idx = ClipboardService.mapper[o]; | ||
if (typeof idx !== 'undefined') this.excusiveAdd(idx, remote, path); | ||
} | ||
|
||
private trigger = new Subject<number>(); | ||
update$: NothingFlow<ClipboardNode>; | ||
public commit() { | ||
this.trigger.next(1); | ||
} | ||
|
||
constructor() { | ||
const outer = this; | ||
this.update$ = new (class extends NothingFlow<ClipboardNode> { | ||
public prerequest$ = outer.trigger.pipe( | ||
map( | ||
(): CombErr<ClipboardNode> => [ | ||
{ | ||
copy: outer.sourcePool[ClipboardService.mapper.copy], | ||
move: outer.sourcePool[ClipboardService.mapper.move], | ||
del: outer.sourcePool[ClipboardService.mapper.del], | ||
}, | ||
[], | ||
] | ||
) | ||
); | ||
})(); | ||
this.update$.deploy(); | ||
this.update$.getOutput().subscribe(); | ||
this.trigger.next(1); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.