diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 2072b462a..626955fd8 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -11,10 +11,10 @@ import { StoreModule } from '@ngrx/store'; import { EffectsModule } from '@ngrx/effects'; import { StoreDevtoolsModule } from '@ngrx/store-devtools'; import { DragDropModule } from '@angular/cdk/drag-drop'; +import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatInputModule } from '@angular/material/input'; import { MatIconModule } from '@angular/material/icon'; -import { MatCheckboxModule } from '@angular/material/checkbox'; import { MatListModule } from '@angular/material/list'; import { MatMomentDateModule } from '@angular/material-moment-adapter'; import { NgxPaginationModule } from 'ngx-pagination'; @@ -159,6 +159,7 @@ const maskConfig: Partial = { ], imports: [ NgxMaskModule.forRoot(maskConfig), + MatCheckboxModule, MatInputModule, MatDatepickerModule, MatMomentDateModule, @@ -176,7 +177,6 @@ const maskConfig: Partial = { UiSwitchModule, DragDropModule, MatIconModule, - MatCheckboxModule, MatListModule, StoreModule.forRoot(reducers, { metaReducers, diff --git a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.html b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.html index 4b509a983..e5809d4b9 100644 --- a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.html +++ b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.html @@ -4,6 +4,7 @@ + @@ -23,6 +24,8 @@ +
Selected ID User email Date
{{ entry.id }} {{ entry.owner_email }} @@ -57,4 +60,5 @@
-
Total: {{this.resultSum.hours}} hours, {{this.resultSum.minutes}} minutes
\ No newline at end of file +
Total: {{this.resultSum.hours}} hours, {{this.resultSum.minutes}} minutes, +
Total hours entries selected: {{resultSumEntriesSelected.hours}} hours, {{resultSumEntriesSelected.minutes}} minutes
diff --git a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts index 5444a818c..510634060 100644 --- a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts +++ b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.spec.ts @@ -4,7 +4,7 @@ import { DataTablesModule } from 'angular-datatables'; import { NgxPaginationModule } from 'ngx-pagination'; import { Entry } from 'src/app/modules/shared/models'; import { SubstractDatePipe } from 'src/app/modules/shared/pipes/substract-date/substract-date.pipe'; -import { getReportDataSource } from 'src/app/modules/time-clock/store/entry.selectors'; +import { getReportDataSource, getResultSumEntriesSelected } from 'src/app/modules/time-clock/store/entry.selectors'; import { EntryState } from '../../../time-clock/store/entry.reducer'; import { TimeEntriesTableComponent } from './time-entries-table.component'; import { TotalHours } from '../../models/total-hours-report'; @@ -61,6 +61,7 @@ describe('Reports Page', () => { const state: EntryState = { active: timeEntry, isLoading: false, + resultSumEntriesSelected: new TotalHours(), message: '', createError: false, updateError: false, @@ -94,7 +95,8 @@ describe('Reports Page', () => { component = fixture.componentInstance; store = TestBed.inject(MockStore); store.setState(state); - getReportDataSourceSelectorMock = store.overrideSelector(getReportDataSource, state.reportDataSource); + getReportDataSourceSelectorMock = (store.overrideSelector(getReportDataSource, state.reportDataSource), + store.overrideSelector(getResultSumEntriesSelected, state.resultSumEntriesSelected)); fixture.detectChanges(); } ); @@ -207,6 +209,14 @@ describe('Reports Page', () => { expect({ hours, minutes, seconds }).toEqual({ hours: 3, minutes: 20, seconds: 0 }); }); + it('the sume of hours of entries selected is equal to {hours:0, minutes:0, seconds:0}', () => { + let checked = true; + let {hours, minutes, seconds}:TotalHours = component.sumHoursEntriesSelected(timeEntryList[0], checked); + checked = false; + ({hours, minutes,seconds} = component.sumHoursEntriesSelected(timeEntryList[0], checked)); + expect({hours, minutes, seconds}).toEqual({hours:0, minutes:0, seconds:0}); + }); + afterEach(() => { fixture.destroy(); }); diff --git a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.ts b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.ts index 9949a7ce9..9b2fbff84 100644 --- a/src/app/modules/reports/components/time-entries-table/time-entries-table.component.ts +++ b/src/app/modules/reports/components/time-entries-table/time-entries-table.component.ts @@ -8,7 +8,7 @@ import { filter } from 'rxjs/operators'; import { Entry } from 'src/app/modules/shared/models'; import { DataSource } from 'src/app/modules/shared/models/data-source.model'; import { EntryState } from '../../../time-clock/store/entry.reducer'; -import { getReportDataSource } from '../../../time-clock/store/entry.selectors'; +import { getReportDataSource, getResultSumEntriesSelected } from '../../../time-clock/store/entry.selectors'; import { TotalHours } from '../../models/total-hours-report'; import { User } from 'src/app/modules/users/models/users'; import { LoadUsers, UserActionTypes } from 'src/app/modules/users/store/user.actions'; @@ -24,7 +24,9 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn selectOptionValues = [15, 30, 50, 100, -1]; selectOptionNames = [15, 30, 50, 100, 'All']; + totalTimeSelected: moment.Duration; users: User[] = []; + dtOptions: any = { scrollY: '590px', dom: '<"d-flex justify-content-between"B<"d-flex"<"mr-5"l>f>>rtip', @@ -60,8 +62,8 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn filename: `time-entries-${formatDate(new Date(), 'MM_dd_yyyy-HH_mm', 'en')}` }, ], - columnDefs: [{ type: 'date', targets: 2 }], - order: [[1, 'asc'], [2, 'desc'], [4, 'desc']] + columnDefs: [{ type: 'date', targets: 2}, {orderable: false, targets: [0]}], + order: [[1,'asc'],[2,'desc'],[4,'desc']] }; dtTrigger: Subject = new Subject(); @ViewChild(DataTableDirective, { static: false }) @@ -70,11 +72,17 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn reportDataSource$: Observable>; rerenderTableSubscription: Subscription; resultSum: TotalHours; + resultSumEntriesSelected: TotalHours; + resultSumEntriesSelected$:Observable; + totalHoursSubscription: Subscription; dateTimeOffset: ParseDateTimeOffset; - constructor(private store: Store, private actionsSubject$: ActionsSubject, private storeUser: Store) { - this.reportDataSource$ = this.store.pipe(select(getReportDataSource)); - this.dateTimeOffset = new ParseDateTimeOffset(); + + constructor(private store: Store, private actionsSubject$: ActionsSubject, private storeUser: Store ) { + this.reportDataSource$ = this.store.pipe(select(getReportDataSource)); + this.resultSumEntriesSelected$ = this.store.pipe(select(getResultSumEntriesSelected)); + this.dateTimeOffset = new ParseDateTimeOffset(); + this.resultSumEntriesSelected = new TotalHours(); } uploadUsers(): void { @@ -88,6 +96,10 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn ngOnInit(): void { this.rerenderTableSubscription = this.reportDataSource$.subscribe((ds) => { + this.totalHoursSubscription = this.resultSumEntriesSelected$.subscribe((actTotalHours) => { + this.resultSumEntriesSelected = actTotalHours ; + this.totalTimeSelected = moment.duration(0); + }); this.sumDates(ds.data); this.rerenderDataTable(); }); @@ -153,5 +165,15 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn this.selectedUserId.emit(userId); } + sumHoursEntriesSelected(entry: Entry, checked: boolean){ + this.resultSumEntriesSelected = new TotalHours(); + const duration = moment.duration(moment(entry.end_date).diff(moment(entry.start_date))); + this.totalTimeSelected = checked ? this.totalTimeSelected.add(duration) : this.totalTimeSelected.subtract(duration); + const daysTotalInHours = this.totalTimeSelected.days() * 24; + this.resultSumEntriesSelected.hours = this.totalTimeSelected.hours() + daysTotalInHours; + this.resultSumEntriesSelected.minutes = this.totalTimeSelected.minutes(); + this.resultSumEntriesSelected.seconds = this.totalTimeSelected.seconds(); + return this.resultSumEntriesSelected; + } } diff --git a/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts b/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts index 7ac3c117d..b93b5d033 100644 --- a/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts +++ b/src/app/modules/time-clock/components/time-entries-summary/time-entries-summary.component.spec.ts @@ -2,6 +2,7 @@ import { waitForAsync, ComponentFixture, discardPeriodicTasks, fakeAsync, TestBe import { ActionsSubject } from '@ngrx/store'; import { MockStore, provideMockStore } from '@ngrx/store/testing'; import { interval } from 'rxjs'; +import { TotalHours } from 'src/app/modules/reports/models/total-hours-report'; import { Entry } from 'src/app/modules/shared/models/entry.model'; import { TimeDetails, TimeEntriesSummary } from './../../models/time.entry.summary'; import { TimeDetailsPipe } from './../../pipes/time-details.pipe'; @@ -36,6 +37,7 @@ describe('TimeEntriesSummaryComponent', () => { const state: EntryState = { active: timeEntry, isLoading: false, + resultSumEntriesSelected: new TotalHours(), message: '', createError: false, updateError: false, diff --git a/src/app/modules/time-clock/store/entry.reducer.spec.ts b/src/app/modules/time-clock/store/entry.reducer.spec.ts index 447ca1312..eb0f1a7a5 100644 --- a/src/app/modules/time-clock/store/entry.reducer.spec.ts +++ b/src/app/modules/time-clock/store/entry.reducer.spec.ts @@ -1,3 +1,4 @@ +import { TotalHours } from '../../reports/models/total-hours-report'; import { TimeDetails, TimeEntriesSummary } from '../models/time.entry.summary'; import { Entry, NewEntry } from './../../shared/models'; import * as actions from './entry.actions'; @@ -15,6 +16,7 @@ describe('entryReducer', () => { message: '', createError: null, updateError: null, + resultSumEntriesSelected: new TotalHours(), timeEntriesSummary: emptyTimeEntriesSummary, timeEntriesDataSource: { data: [], diff --git a/src/app/modules/time-clock/store/entry.reducer.ts b/src/app/modules/time-clock/store/entry.reducer.ts index 1fa6e3171..d3af715f8 100644 --- a/src/app/modules/time-clock/store/entry.reducer.ts +++ b/src/app/modules/time-clock/store/entry.reducer.ts @@ -2,10 +2,12 @@ import { Entry } from '../../shared/models'; import { DataSource } from '../../shared/models/data-source.model'; import { TimeDetails, TimeEntriesSummary } from '../models/time.entry.summary'; import { EntryActions, EntryActionTypes } from './entry.actions'; +import { TotalHours } from '../../reports/models/total-hours-report'; export interface EntryState { active: Entry; isLoading: boolean; + resultSumEntriesSelected: TotalHours; message: string; createError: boolean; updateError: boolean; @@ -20,6 +22,7 @@ const emptyTimeEntriesSummary: TimeEntriesSummary = { day: emptyTimeDetails, wee export const initialState = { active: null, isLoading: false, + resultSumEntriesSelected: new TotalHours(), message: '', createError: null, updateError: null, @@ -263,6 +266,7 @@ export const entryReducer = (state: EntryState = initialState, action: EntryActi return { ...state, isLoading: true, + resultSumEntriesSelected:{hours:0, minutes:0, seconds:0}, reportDataSource: { data: [], isLoading: true diff --git a/src/app/modules/time-clock/store/entry.selectors.spec.ts b/src/app/modules/time-clock/store/entry.selectors.spec.ts index d3fa7c708..06c3c02e2 100644 --- a/src/app/modules/time-clock/store/entry.selectors.spec.ts +++ b/src/app/modules/time-clock/store/entry.selectors.spec.ts @@ -1,3 +1,4 @@ +import { TotalHours } from '../../reports/models/total-hours-report'; import { Entry } from '../../shared/models'; import { TimeDetails, TimeEntriesSummary } from '../models/time.entry.summary'; import * as selectors from './entry.selectors'; @@ -52,4 +53,11 @@ describe('Entry selectors', () => { expect(selectors.getUpdateError.projector(entryState)).toEqual(error); }); + + it('should select resultSumEntriesSelected', () => { + const resultSumEntriesSelected:TotalHours = { hours:0, minutes:0, seconds:0 }; + const entryState = { resultSumEntriesSelected }; + + expect(selectors.getResultSumEntriesSelected.projector(entryState)).toEqual(resultSumEntriesSelected); + }); }); diff --git a/src/app/modules/time-clock/store/entry.selectors.ts b/src/app/modules/time-clock/store/entry.selectors.ts index 2655ac3e8..fb29e8e8a 100644 --- a/src/app/modules/time-clock/store/entry.selectors.ts +++ b/src/app/modules/time-clock/store/entry.selectors.ts @@ -16,3 +16,5 @@ export const getStatusMessage = createSelector(getEntryState, (state: EntryState export const getReportDataSource = createSelector(getEntryState, (state: EntryState) => state?.reportDataSource); export const getTimeEntriesDataSource = createSelector(getEntryState, (state: EntryState) => state?.timeEntriesDataSource); + +export const getResultSumEntriesSelected = createSelector(getEntryState, (state: EntryState) => state?.resultSumEntriesSelected); diff --git a/src/app/modules/time-entries/pages/time-entries.component.spec.ts b/src/app/modules/time-entries/pages/time-entries.component.spec.ts index 7c1afcde4..0533ccd1c 100644 --- a/src/app/modules/time-entries/pages/time-entries.component.spec.ts +++ b/src/app/modules/time-entries/pages/time-entries.component.spec.ts @@ -23,6 +23,7 @@ import { DebugElement } from '@angular/core'; import { FeatureToggle } from './../../../../environments/enum'; import { CalendarView } from 'angular-calendar'; import * as moment from 'moment'; +import { TotalHours } from '../../reports/models/total-hours-report'; describe('TimeEntriesComponent', () => { type Merged = TechnologyState & ProjectState & EntryState; @@ -74,6 +75,7 @@ describe('TimeEntriesComponent', () => { createError: false, updateError: false, isLoading: false, + resultSumEntriesSelected: new TotalHours(), message: 'any-message', active: { start_date: new Date('2019-01-01T15:36:15.887Z'),