diff --git a/src/app/completion.ts b/src/app/completion.ts index 686ab57b5..a52f19c5c 100644 --- a/src/app/completion.ts +++ b/src/app/completion.ts @@ -3,4 +3,5 @@ export interface Completion { globalBytes: number; needBytes: number; needDeletes: number; + needItems: number; } \ No newline at end of file diff --git a/src/app/device.ts b/src/app/device.ts index 4a285b069..a7de61273 100644 --- a/src/app/device.ts +++ b/src/app/device.ts @@ -1,4 +1,6 @@ import { colors } from './style'; +import Folder from './folder'; +import { Completion } from './completion'; interface Device { deviceID: string; @@ -7,8 +9,9 @@ interface Device { state: string; paused: boolean; connected: boolean; - completion: number; + completion: Completion; used: boolean; // indicates if a folder is using the device + folders: Folder[]; } namespace Device { @@ -80,7 +83,7 @@ namespace Device { } if (d.connected) { - if (d.completion === 100) { + if (d.completion.completion === 100) { return d.used ? StateType.Insync : StateType.UnusedInsync; } else { return StateType.Syncing; @@ -89,5 +92,35 @@ namespace Device { return d.used ? StateType.Disconnected : StateType.UnusedDisconnected; } + + export function recalcCompletion(d: Device) { + if (!d || !d.completion || !d.folders) { + return + } + var total = 0, needed = 0, deletes = 0, items = 0; + d.folders.forEach(folder => { + if (!folder || !folder.completion) + return + needed += folder.completion.needBytes; + items += folder.completion.needItems; + deletes += folder.completion.needDeletes; + }); + if (total == 0) { + d.completion.completion = 100; + d.completion.needBytes = 0; + d.completion.needItems = 0; + } else { + d.completion.completion = Math.floor(100 * (1 - needed / total)); + d.completion.needBytes = needed; + d.completion.needItems = items + deletes; + } + + if (needed == 0 && deletes > 0) { + // We don't need any data, but we have deletes that we need + // to do. Drop down the completion percentage to indicate + // that we have stuff to do. + d.completion.completion = 95; + } + } } export default Device; \ No newline at end of file diff --git a/src/app/folder.ts b/src/app/folder.ts index c3330f0ff..ca10c3486 100644 --- a/src/app/folder.ts +++ b/src/app/folder.ts @@ -1,5 +1,6 @@ import Device from './device'; import { colors } from './style'; +import { Completion } from './completion'; interface Folder { id: string; @@ -9,7 +10,7 @@ interface Folder { stateType: Folder.StateType; state: string; paused: boolean; - completion: number; + completion: Completion; path: string; } @@ -144,18 +145,13 @@ namespace Folder { return StateType.Unknown; } - const needTotalItems = fs.needDeletes + fs.needDirectories + - fs.needFiles + fs.needSymlinks; - const receiveOnlyTotalItems = fs.receiveOnlyChangedDeletes + fs.receiveOnlyChangedDirectories + - fs.receiveOnlyChangedFiles + fs.receiveOnlyChangedSymlinks; - - if (needTotalItems > 0) { + if (fs.needTotalItems > 0) { return StateType.OutOfSync; } - if (f.status.pullErrors > 0) { + if (fs.pullErrors > 0) { return StateType.FailedItems; } - if (receiveOnlyTotalItems > 0) { + if (fs.receiveOnlyTotalItems > 0) { return StateType.LocalAdditions; } if (f.devices.length <= 1) { @@ -172,6 +168,7 @@ namespace Folder { globalDirectories: number; globalFiles: number; globalSymlinks: number; + globalTotalItems: number; ignorePatterns: boolean; inSyncBytes: number; inSyncFiles: number; @@ -186,12 +183,14 @@ namespace Folder { needDirectories: number; needFiles: number; needSymlinks: number; + needTotalItems: number; pullErrors: number; receiveOnlyChangedBytes: number; receiveOnlyChangedDeletes: number; receiveOnlyChangedDirectories: number; receiveOnlyChangedFiles: number; receiveOnlyChangedSymlinks: number; + receiveOnlyTotalItems: number; sequence: number; state: string; stateChanged: string; diff --git a/src/app/mocks/mock-db-completion.ts b/src/app/mocks/mock-db-completion.ts index 7ef778d61..a0fd65480 100644 --- a/src/app/mocks/mock-db-completion.ts +++ b/src/app/mocks/mock-db-completion.ts @@ -5,13 +5,15 @@ export const dbCompletion = "completion": 100, "globalBytes": 156793013575, "needBytes": 0, - "needDeletes": 0 + "needDeletes": 0, + "needItems": 0 }, { "completion": 80, "globalBytes": 3013575, "needBytes": 100, - "needDeletes": 0 + "needDeletes": 0, + "needItems": 0 } ] /* diff --git a/src/app/mocks/mock-db-status.ts b/src/app/mocks/mock-db-status.ts index 0779bbe42..03c5a51c6 100644 --- a/src/app/mocks/mock-db-status.ts +++ b/src/app/mocks/mock-db-status.ts @@ -16,6 +16,7 @@ export const dbStatus = "globalDirectories": 0, "globalFiles": 0, "globalSymlinks": 0, + "globalTotalItems": 0, "ignorePatterns": false, "inSyncBytes": 0, "inSyncFiles": 0, @@ -25,11 +26,13 @@ export const dbStatus = "localDirectories": 0, "localFiles": 0, "localSymlinks": 0, + "localTotalItems": 0, "needBytes": 0, "needDeletes": 0, "needDirectories": 0, "needFiles": 0, "needSymlinks": 0, + "needTotalItems": 0, "pullErrors": 0, "receiveOnlyChangedBytes": 0, "receiveOnlyChangedDeletes": 0, diff --git a/src/app/services/db-completion.service.ts b/src/app/services/db-completion.service.ts index 00cb4f36c..174481308 100644 --- a/src/app/services/db-completion.service.ts +++ b/src/app/services/db-completion.service.ts @@ -5,6 +5,7 @@ import { apiURL, apiRetry } from '../api-utils'; import { Completion } from '../completion'; import { retry, map } from 'rxjs/operators'; import { Observable } from 'rxjs'; +import { StType } from '../type'; @Injectable({ providedIn: 'root' @@ -14,12 +15,21 @@ export class DbCompletionService { constructor(private http: HttpClient) { } - getDeviceCompletion(id: string): Observable { + getCompletion(type: StType, id: string): Observable { let httpOptions: { params: HttpParams }; if (id) { - httpOptions = { - params: new HttpParams().set('device', id) - }; + switch (type) { + case StType.Device: + httpOptions = { + params: new HttpParams().set('device', id) + }; + break; + case StType.Folder: + httpOptions = { + params: new HttpParams().set('folder', id) + }; + break; + } } else { } return this.http @@ -38,6 +48,5 @@ export class DbCompletionService { return res; }) ); - } } \ No newline at end of file diff --git a/src/app/services/device.service.ts b/src/app/services/device.service.ts index 657a35f16..c3c6ac741 100644 --- a/src/app/services/device.service.ts +++ b/src/app/services/device.service.ts @@ -7,6 +7,7 @@ import { DbCompletionService } from './db-completion.service'; import { SystemConnections } from '../connections'; import { SystemStatusService } from './system-status.service'; import { ProgressService } from './progress.service'; +import { StType } from '../type'; @Injectable({ providedIn: 'root' @@ -48,16 +49,17 @@ export class DeviceService { } } - this.dbCompletionService.getDeviceCompletion(device.deviceID).subscribe( + this.dbCompletionService.getCompletion(StType.Device, device.deviceID).subscribe( c => { - device.completion = c.completion; + device.completion = c; + Device.recalcCompletion(device); device.stateType = Device.getStateType(device); device.state = Device.stateTypeToString(device.stateType); observer.next(device); this.progressService.addToProgress(1); - // recursively get the status of the next folder + // recursively get the status of the next device this.getDeviceStatusInOrder(observer, startIndex); }); } @@ -75,22 +77,29 @@ export class DeviceService { status => { this.devices.forEach(device => { if (device.deviceID === status.myID) { - console.log("found thisDevice!", device); + // TODO Determine if it should ignore thisDevice this.thisDevice = device; } }); - // TODO Determine if it should ignore thisDevice - // Check folder devices to see if the device is used this.systemConfigService.getFolders().subscribe( folders => { // Loop through all folder devices to see if the device is used this.devices.forEach(device => { + // Alloc array if needed + if (!device.folders) { + device.folders = []; + } + folders.forEach(folder => { folder.devices.forEach(fdevice => { if (device.deviceID === fdevice.deviceID) { + // The device is used by a folder device.used = true; + + // Add a reference to the folder to the device + device.folders.push(folder); } }); }); diff --git a/src/app/services/folder.service.ts b/src/app/services/folder.service.ts index c208b432e..c70b2c8e6 100644 --- a/src/app/services/folder.service.ts +++ b/src/app/services/folder.service.ts @@ -4,6 +4,8 @@ import { Observable, Subscriber } from 'rxjs'; import Folder from '../folder'; import { DbStatusService } from './db-status.service'; import { ProgressService } from './progress.service'; +import { DbCompletionService } from './db-completion.service'; +import { StType } from '../type'; @Injectable({ providedIn: 'root' @@ -14,6 +16,7 @@ export class FolderService { constructor( private systemConfigService: SystemConfigService, private dbStatusService: DbStatusService, + private dbCompletionService: DbCompletionService, private progressService: ProgressService, ) { } @@ -28,15 +31,19 @@ export class FolderService { this.dbStatusService.getFolderStatus(folder.id).subscribe( status => { folder.status = status; - folder.stateType = Folder.getStateType(folder); - folder.state = Folder.stateTypeToString(folder.stateType); - observer.next(folder); - // Add one to the progress service - this.progressService.addToProgress(1); + this.dbCompletionService.getCompletion(StType.Folder, folder.id).subscribe( + c => { + folder.completion = c; + folder.stateType = Folder.getStateType(folder); + folder.state = Folder.stateTypeToString(folder.stateType); + observer.next(folder); - // recursively get the status of the next folder - this.getFolderStatusInOrder(observer, startIndex); + this.progressService.addToProgress(1); + + // recursively get the status of the next folder + this.getFolderStatusInOrder(observer, startIndex); + }); } ); }