diff --git a/src/app/features/idle/dialog-idle/dialog-idle.component.html b/src/app/features/idle/dialog-idle/dialog-idle.component.html index c811956478..6936a6576a 100644 --- a/src/app/features/idle/dialog-idle/dialog-idle.component.html +++ b/src/app/features/idle/dialog-idle/dialog-idle.component.html @@ -83,7 +83,7 @@ track_changes add - {{T.F.TIME_TRACKING.D_IDLE.TASK_BREAK|translate}} + {{T.F.TIME_TRACKING.D_IDLE.TASK_AND_BREAK|translate}} free_breakfast diff --git a/src/app/features/idle/dialog-idle/dialog-idle.component.ts b/src/app/features/idle/dialog-idle/dialog-idle.component.ts index 8516e66989..9bede989ed 100644 --- a/src/app/features/idle/dialog-idle/dialog-idle.component.ts +++ b/src/app/features/idle/dialog-idle/dialog-idle.component.ts @@ -14,8 +14,6 @@ import { T } from '../../../t.const'; import { ipcRenderer } from 'electron'; import { IPC } from '../../../../../electron/ipc-events.const'; import { SimpleCounterService } from '../../simple-counter/simple-counter.service'; -import { first } from 'rxjs/operators'; -import { DialogConfirmComponent } from '../../../ui/dialog-confirm/dialog-confirm.component'; import { ElectronService } from '../../../core/electron/electron.service'; import { IS_ELECTRON } from '../../../app.constants'; import { SimpleCounter } from '../../simple-counter/simple-counter.model'; @@ -73,8 +71,6 @@ export class DialogIdleComponent implements OnInit, OnDestroy { isWasEnabledBefore: isOn, } as SimpleCounterIdleBtn), ); - console.log(this.simpleCounterToggleBtns); - _matDialogRef.disableClose = true; } @@ -109,67 +105,36 @@ export class DialogIdleComponent implements OnInit, OnDestroy { } skipTrack(): void { - const activatedItemNr = this.simpleCounterToggleBtns.filter( - (btn) => btn.isTrackTo, - ).length; - if (activatedItemNr > 0) { - this._matDialog - .open(DialogConfirmComponent, { - restoreFocus: true, - data: { - cancelTxt: T.F.TIME_TRACKING.D_IDLE.SIMPLE_CONFIRM_COUNTER_CANCEL, - okTxt: T.F.TIME_TRACKING.D_IDLE.SIMPLE_CONFIRM_COUNTER_OK, - message: T.F.TIME_TRACKING.D_IDLE.SIMPLE_COUNTER_CONFIRM_TXT, - translateParams: { - nr: activatedItemNr, - }, - }, - }) - .afterClosed() - .subscribe((isConfirm: boolean) => { - if (isConfirm) { - this._updateSimpleCounterValues(); - } - }); - } - this._matDialogRef.close({ - task: null, - isResetBreakTimer: true, - isTrackAsBreak: false, + trackItems: [], + simpleCounterToggleBtnsWhenNoTrackItems: this.simpleCounterToggleBtns, }); } trackAsBreak(): void { - this._updateSimpleCounterValues(); - this._matDialogRef.close({ - task: null, - isResetBreakTimer: true, - isTrackAsBreak: true, + trackItems: [ + { + type: 'BREAK', + time: 'IDLE_TIME', + simpleCounterToggleBtns: this.simpleCounterToggleBtns, + }, + ], }); } track(isTrackAsBreak: boolean = false): void { - this._updateSimpleCounterValues(); - this._matDialogRef.close({ - task: this.selectedTask || this.newTaskTitle, - isTrackAsBreak, - isResetBreakTimer: isTrackAsBreak, - }); - } - - private async _updateSimpleCounterValues(): Promise { - const idleTime = await this.idleTime$.pipe(first()).toPromise(); - - this.simpleCounterToggleBtns.forEach((tglBtn) => { - if (tglBtn.isTrackTo) { - this._simpleCounterService.increaseCounterToday(tglBtn.id, idleTime); - if (tglBtn.isWasEnabledBefore) { - this._simpleCounterService.toggleCounter(tglBtn.id); - } - } + trackItems: [ + { + type: isTrackAsBreak ? 'TASK_AND_BREAK' : 'TASK', + time: 'IDLE_TIME', + simpleCounterToggleBtns: this.simpleCounterToggleBtns, + ...(this.isCreate + ? { title: this.newTaskTitle as string } + : { task: this.selectedTask as Task }), + }, + ], }); } } diff --git a/src/app/features/idle/dialog-idle/dialog-idle.model.ts b/src/app/features/idle/dialog-idle/dialog-idle.model.ts index 39585ee5a4..84947b353b 100644 --- a/src/app/features/idle/dialog-idle/dialog-idle.model.ts +++ b/src/app/features/idle/dialog-idle/dialog-idle.model.ts @@ -10,12 +10,19 @@ export interface SimpleCounterIdleBtn { } export interface DialogIdleReturnData { - task: null | Task | string | undefined; - isResetBreakTimer: boolean; - isTrackAsBreak: boolean; + trackItems: IdleTrackItem[]; + simpleCounterToggleBtnsWhenNoTrackItems?: SimpleCounterIdleBtn[]; } export interface DialogIdlePassedData { enabledSimpleStopWatchCounters: SimpleCounter[]; lastCurrentTaskId: string | null; } + +export interface IdleTrackItem { + type: 'BREAK' | 'TASK' | 'TASK_AND_BREAK'; + time: number | 'IDLE_TIME'; + simpleCounterToggleBtns: SimpleCounterIdleBtn[]; + task?: Task; + title?: string; +} diff --git a/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.html b/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.html index 96a079cc31..2fa7be8f31 100644 --- a/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.html +++ b/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.html @@ -9,7 +9,7 @@ free_breakfast - + free_breakfast + track_changes diff --git a/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.ts b/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.ts index 4b5d3036f9..674b8458d5 100644 --- a/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.ts +++ b/src/app/features/idle/dialog-idle/idle-split-mode/idle-split-mode.component.ts @@ -12,17 +12,9 @@ import { Store } from '@ngrx/store'; import { SimpleCounterService } from '../../../simple-counter/simple-counter.service'; import { first } from 'rxjs/operators'; import { T } from 'src/app/t.const'; -import { SimpleCounterIdleBtn } from '../dialog-idle.model'; +import { SimpleCounterIdleBtn, IdleTrackItem } from '../dialog-idle.model'; import { dirtyDeepCopy } from '../../../../util/dirtyDeepCopy'; -interface TrackToItem { - type: 'BREAK' | 'TASK' | 'TASK_BREAK'; - time: number; - simpleCounterToggleBtns: SimpleCounterIdleBtn[]; - task?: Task; - title?: string; -} - @Component({ selector: 'idle-split-mode', templateUrl: './idle-split-mode.component.html', @@ -36,7 +28,7 @@ export class IdleSplitModeComponent implements OnInit { @Input() prevSelectedTask: Task | null = null; idleTime$ = this._store.select(selectIdleTime); - trackToItems: TrackToItem[] = []; + trackToItems: IdleTrackItem[] = []; @Output() cancel = new EventEmitter(); @Output() save = new EventEmitter(); @@ -78,7 +70,7 @@ export class IdleSplitModeComponent implements OnInit { ]; } - onTaskChange(item: TrackToItem, taskOrTaskTitle: Task | string): void { + onTaskChange(item: IdleTrackItem, taskOrTaskTitle: Task | string): void { const isCreate = typeof taskOrTaskTitle === 'string'; if (isCreate) { item.title = taskOrTaskTitle as string; diff --git a/src/app/features/idle/store/idle.actions.ts b/src/app/features/idle/store/idle.actions.ts index d6fb78ec9d..e24ed779fa 100644 --- a/src/app/features/idle/store/idle.actions.ts +++ b/src/app/features/idle/store/idle.actions.ts @@ -1,6 +1,6 @@ import { createAction, props } from '@ngrx/store'; import { SimpleCounter } from '../../simple-counter/simple-counter.model'; -import { Task } from '../../tasks/task.model'; +import { IdleTrackItem, SimpleCounterIdleBtn } from '../dialog-idle/dialog-idle.model'; export const triggerIdle = createAction( '[Idle] Trigger Idle', @@ -24,10 +24,8 @@ export const setIdleTime = createAction( export const idleDialogResult = createAction( '[Idle] Dialog result', props<{ - timeSpent: number; - selectedTaskOrTitle: Task | string; - isResetBreakTimer: boolean; - isTrackAsBreak: boolean; + trackItems: IdleTrackItem[]; + simpleCounterToggleBtnsWhenNoTrackItems?: SimpleCounterIdleBtn[]; }>(), ); diff --git a/src/app/features/idle/store/idle.effects.ts b/src/app/features/idle/store/idle.effects.ts index 2b608c97f1..8bbf0229eb 100644 --- a/src/app/features/idle/store/idle.effects.ts +++ b/src/app/features/idle/store/idle.effects.ts @@ -43,8 +43,12 @@ import { devError } from '../../../util/dev-error'; import { DialogIdlePassedData, DialogIdleReturnData, + IdleTrackItem, + SimpleCounterIdleBtn, } from '../dialog-idle/dialog-idle.model'; import { isNotNullOrUndefined } from '../../../util/is-not-null-or-undefined'; +import { DialogConfirmComponent } from '../../../ui/dialog-confirm/dialog-confirm.component'; +import { T } from '../../../t.const'; const DEFAULT_MIN_IDLE_TIME = 60000; const IDLE_POLL_INTERVAL = 1000; @@ -57,7 +61,6 @@ export class IdleEffects { private _triggerIdleApis$ = IS_ELECTRON ? fromEvent(this._electronService.ipcRenderer as IpcRenderer, IPC.IDLE_TIME).pipe( - tap((v) => console.log('IIIIIIIIII', v)), map(([ev, idleTimeInMs]: any) => idleTimeInMs as number), ) : this._chromeExtensionInterfaceService.onReady$.pipe( @@ -175,15 +178,7 @@ export class IdleEffects { } }), isNotNullOrUndefined(), - withLatestFrom(this._store.select(selectIdleTime)), - map(([{ task, isResetBreakTimer, isTrackAsBreak }, idleTimeI]) => - idleDialogResult({ - timeSpent: idleTimeI, - selectedTaskOrTitle: task as any, - isResetBreakTimer, - isTrackAsBreak, - }), - ), + map((dialogRes) => idleDialogResult(dialogRes)), tap(() => (this._isDialogOpen = false)), ), ); @@ -191,31 +186,84 @@ export class IdleEffects { onIdleDialogResult$ = createEffect(() => this.actions$.pipe( ofType(idleDialogResult), - tap(({ timeSpent, selectedTaskOrTitle, isResetBreakTimer, isTrackAsBreak }) => { - if (isResetBreakTimer || isTrackAsBreak) { + withLatestFrom(this._store.select(selectIdleTime)), + tap(([{ trackItems, simpleCounterToggleBtnsWhenNoTrackItems }, idleTime]) => { + this._cancelIdlePoll(); + + if (trackItems.length === 0 && simpleCounterToggleBtnsWhenNoTrackItems) { + const activatedItemNr = simpleCounterToggleBtnsWhenNoTrackItems.filter( + (btn) => btn.isTrackTo, + ).length; + + // TODO maybe move to effect + if (activatedItemNr > 0) { + this._matDialog + .open(DialogConfirmComponent, { + restoreFocus: true, + data: { + cancelTxt: T.F.TIME_TRACKING.D_IDLE.SIMPLE_CONFIRM_COUNTER_CANCEL, + okTxt: T.F.TIME_TRACKING.D_IDLE.SIMPLE_CONFIRM_COUNTER_OK, + message: T.F.TIME_TRACKING.D_IDLE.SIMPLE_COUNTER_CONFIRM_TXT, + translateParams: { + nr: activatedItemNr, + }, + }, + }) + .afterClosed() + .subscribe((isConfirm: boolean) => { + if (isConfirm) { + // TODO maybe move to effect + this._updateSimpleCounterValues( + simpleCounterToggleBtnsWhenNoTrackItems, + idleTime, + ); + } + }); + } + return; + } + + const itemsWithMappedIdleTime = trackItems.map((trackItem) => ({ + ...trackItem, + time: trackItem.time === 'IDLE_TIME' ? idleTime : trackItem.time, + })); + + itemsWithMappedIdleTime.forEach((item) => { + this._updateSimpleCounterValues(item.simpleCounterToggleBtns, item.time); + }); + + const breakItems = itemsWithMappedIdleTime.filter( + (item: IdleTrackItem) => + item.type === 'BREAK' || item.type === 'TASK_AND_BREAK', + ); + if (breakItems.length) { this._store.dispatch(triggerResetBreakTimer()); + breakItems.forEach((item) => { + this._workContextService.addToBreakTimeForActiveContext(undefined, item.time); + }); } - if (isTrackAsBreak) { - this._workContextService.addToBreakTimeForActiveContext(undefined, timeSpent); - } - - if (selectedTaskOrTitle) { - if (typeof selectedTaskOrTitle === 'string') { - const currId = this._taskService.add(selectedTaskOrTitle, false, { - timeSpent, + const taskItems = itemsWithMappedIdleTime.filter( + (item: IdleTrackItem) => item.type === 'TASK' || item.type === 'TASK_AND_BREAK', + ); + let taskItemId: string | undefined; + taskItems.forEach((taskItem) => { + if (typeof taskItem.title === 'string') { + taskItemId = this._taskService.add(taskItem.title, false, { + timeSpent: taskItem.time, timeSpentOnDay: { - [getWorklogStr()]: timeSpent, + [getWorklogStr()]: taskItem.time, }, }); - this._taskService.setCurrentId(currId); - } else { - this._taskService.addTimeSpent(selectedTaskOrTitle, timeSpent); - this._taskService.setCurrentId(selectedTaskOrTitle.id); + } else if (taskItem.task) { + taskItemId = taskItem.task.id; + this._taskService.addTimeSpent(taskItem.task, taskItem.time); } - } + }); - this._cancelIdlePoll(); + if (taskItems.length === 1 && taskItemId) { + this._taskService.setCurrentId(taskItemId); + } }), // unset idle at the end mapTo(resetIdle()), @@ -258,4 +306,18 @@ export class IdleEffects { } this._isFrontEndIdlePollRunning = false; } + + private async _updateSimpleCounterValues( + simpleCounterToggleBtns: SimpleCounterIdleBtn[], + idleTime: number, + ): Promise { + simpleCounterToggleBtns.forEach((tglBtn) => { + if (tglBtn.isTrackTo) { + this._simpleCounterService.increaseCounterToday(tglBtn.id, idleTime); + if (tglBtn.isWasEnabledBefore) { + this._simpleCounterService.toggleCounter(tglBtn.id); + } + } + }); + } } diff --git a/src/app/t.const.ts b/src/app/t.const.ts index ebb0caeede..93bcf2acf5 100644 --- a/src/app/t.const.ts +++ b/src/app/t.const.ts @@ -923,7 +923,7 @@ const T = { 'F.TIME_TRACKING.D_IDLE.SIMPLE_COUNTER_TOOLTIP_DISABLE', SKIP: 'F.TIME_TRACKING.D_IDLE.SKIP', TASK: 'F.TIME_TRACKING.D_IDLE.TASK', - TASK_BREAK: 'F.TIME_TRACKING.D_IDLE.TASK_BREAK', + TASK_AND_BREAK: 'F.TIME_TRACKING.D_IDLE.TASK_BREAK', TRACK_TO: 'F.TIME_TRACKING.D_IDLE.TRACK_TO', }, D_TRACKING_REMINDER: { diff --git a/src/assets/i18n/en.json b/src/assets/i18n/en.json index 9e158f799a..cf43a8e193 100644 --- a/src/assets/i18n/en.json +++ b/src/assets/i18n/en.json @@ -905,7 +905,7 @@ "IDLE_FOR": "You have been idle for:", "SIMPLE_CONFIRM_COUNTER_CANCEL": "Skip", "SIMPLE_CONFIRM_COUNTER_OK": "Track", - "SIMPLE_COUNTER_CONFIRM_TXT": "You selected skip, but activated {{nr}1} simple counter button(s). Do you want to track the idle time to them?", + "SIMPLE_COUNTER_CONFIRM_TXT": "You selected skip, but activated {{nr}} simple counter button(s). Do you want to track the idle time to them?", "SIMPLE_COUNTER_TOOLTIP": "Click to track to {{title}}", "SIMPLE_COUNTER_TOOLTIP_DISABLE": "Click to NOT track to {{title}}", "SKIP": "Skip",