Skip to content

Commit

Permalink
refactor(idle): change effect to allow handling multiple track items #…
Browse files Browse the repository at this point in the history
  • Loading branch information
johannesjo committed Dec 11, 2021
1 parent e668342 commit af43ed3
Show file tree
Hide file tree
Showing 9 changed files with 127 additions and 103 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
<mat-icon *ngIf="!isCreate">track_changes</mat-icon>
<mat-icon *ngIf="isCreate">add</mat-icon>
<!-- <mat-icon style="margin-left: -4px;">free_breakfast</mat-icon>-->
{{T.F.TIME_TRACKING.D_IDLE.TASK_BREAK|translate}}
{{T.F.TIME_TRACKING.D_IDLE.TASK_AND_BREAK|translate}}
<mat-icon>free_breakfast</mat-icon>
</button>
</div>
Expand Down
73 changes: 19 additions & 54 deletions src/app/features/idle/dialog-idle/dialog-idle.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand Down Expand Up @@ -73,8 +71,6 @@ export class DialogIdleComponent implements OnInit, OnDestroy {
isWasEnabledBefore: isOn,
} as SimpleCounterIdleBtn),
);
console.log(this.simpleCounterToggleBtns);

_matDialogRef.disableClose = true;
}

Expand Down Expand Up @@ -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<void> {
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 }),
},
],
});
}
}
13 changes: 10 additions & 3 deletions src/app/features/idle/dialog-idle/dialog-idle.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<mat-button-toggle value="BREAK">
<mat-icon>free_breakfast</mat-icon>
</mat-button-toggle>
<mat-button-toggle value="TASK_BREAK">
<mat-button-toggle value="TASK_AND_BREAK">
<mat-icon>free_breakfast</mat-icon>
+
<mat-icon>track_changes</mat-icon>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand All @@ -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();
Expand Down Expand Up @@ -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;
Expand Down
8 changes: 3 additions & 5 deletions src/app/features/idle/store/idle.actions.ts
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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[];
}>(),
);

Expand Down
114 changes: 88 additions & 26 deletions src/app/features/idle/store/idle.effects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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(
Expand Down Expand Up @@ -175,47 +178,92 @@ 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)),
),
);

onIdleDialogResult$ = createEffect(() =>
this.actions$.pipe(
ofType(idleDialogResult),
tap(({ timeSpent, selectedTaskOrTitle, isResetBreakTimer, isTrackAsBreak }) => {
if (isResetBreakTimer || isTrackAsBreak) {
this._store.dispatch(triggerResetBreakTimer());
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;
}

if (isTrackAsBreak) {
this._workContextService.addToBreakTimeForActiveContext(undefined, timeSpent);
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 (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()),
Expand Down Expand Up @@ -258,4 +306,18 @@ export class IdleEffects {
}
this._isFrontEndIdlePollRunning = false;
}

private async _updateSimpleCounterValues(
simpleCounterToggleBtns: SimpleCounterIdleBtn[],
idleTime: number,
): Promise<void> {
simpleCounterToggleBtns.forEach((tglBtn) => {
if (tglBtn.isTrackTo) {
this._simpleCounterService.increaseCounterToday(tglBtn.id, idleTime);
if (tglBtn.isWasEnabledBefore) {
this._simpleCounterService.toggleCounter(tglBtn.id);
}
}
});
}
}
2 changes: 1 addition & 1 deletion src/app/t.const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand Down
2 changes: 1 addition & 1 deletion src/assets/i18n/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down

0 comments on commit af43ed3

Please sign in to comment.