diff --git a/.gitignore b/.gitignore index 2312832f4..64fbbec7d 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ testem.log /typings debug.log *.vscode +.hintrc # System Files .DS_Store diff --git a/src/app/app.module.ts b/src/app/app.module.ts index 04e1ad0d7..d01a28969 100644 --- a/src/app/app.module.ts +++ b/src/app/app.module.ts @@ -72,6 +72,7 @@ import { UserEffects } from './modules/user/store/user.effects'; import { EntryEffects } from './modules/time-clock/store/entry.effects'; import { InjectTokenInterceptor } from './modules/shared/interceptors/inject.token.interceptor'; import { SubstractDatePipe } from './modules/shared/pipes/substract-date/substract-date.pipe'; +import { SubstractDatePipeDisplayAsFloat } from './modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe'; import { TechnologiesComponent } from './modules/shared/components/technologies/technologies.component'; import { TimeEntriesSummaryComponent } from './modules/time-clock/components/time-entries-summary/time-entries-summary.component'; import { TimeDetailsPipe } from './modules/time-clock/pipes/time-details.pipe'; @@ -138,6 +139,7 @@ const maskConfig: Partial = { CreateProjectTypeComponent, EntryFieldsComponent, SubstractDatePipe, + SubstractDatePipeDisplayAsFloat, TechnologiesComponent, SearchUserComponent, TimeEntriesSummaryComponent, 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 e5809d4b9..256ab28bc 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 @@ -1,64 +1,74 @@
- + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + +
SelectedIDUser emailDateDurationTime inTime outProjectProject IDCustomerCustomer IDActivityTicketDescriptionTechnologies
{{ entry.id }}{{ entry.owner_email }} - {{ entry.start_date | date: 'MM/dd/yyyy' }} - - {{ entry.end_date | substractDate: entry.start_date }} - {{ dateTimeOffset.parseDateTimeOffset(entry.start_date,entry.timezone_offset) }}{{ dateTimeOffset.parseDateTimeOffset(entry.end_date , entry.timezone_offset) }}{{ entry.project_name }}{{ entry.project_id }}{{ entry.customer_name }}{{ entry.customer_id }}{{ entry.activity_name }} - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - -
SelectedIDUser emailDateDurationTime inTime outProjectProject IDCustomerCustomer IDActivityTicketDescriptionTechnologies
+ + {{ entry.id }}{{ entry.owner_email }} + {{ entry.start_date | date: 'MM/dd/yyyy' }} + + {{ entry.end_date | substractDateDisplayAsFloat: entry.start_date }} + {{ dateTimeOffset.parseDateTimeOffset(entry.start_date, entry.timezone_offset) }}{{ dateTimeOffset.parseDateTimeOffset(entry.end_date, entry.timezone_offset) }}{{ entry.project_name }}{{ entry.project_id }}{{ entry.customer_name }}{{ entry.customer_id }}{{ entry.activity_name }} + + {{ entry.uri }} - - {{ entry.description }} - -
- {{ technology }} -
-
-
+
+
{{ entry.description }} + +
+ {{ technology }} +
+
+
+
+
+ Total: {{ this.resultSum.hours }} hours, {{ this.resultSum.minutes }} minutes,
+ Total hours entries selected: {{ resultSumEntriesSelected.hours }} hours, + {{ resultSumEntriesSelected.minutes }} minutes
-
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 30c2d7882..6f312ff81 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,6 +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 { SubstractDatePipeDisplayAsFloat } from 'src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe'; 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'; @@ -80,7 +81,7 @@ describe('Reports Page', () => { waitForAsync(() => { TestBed.configureTestingModule({ imports: [NgxPaginationModule, DataTablesModule], - declarations: [TimeEntriesTableComponent, SubstractDatePipe], + declarations: [TimeEntriesTableComponent, SubstractDatePipe, SubstractDatePipeDisplayAsFloat], providers: [provideMockStore({ initialState: state }), { provide: ActionsSubject, useValue: actionSub }], }).compileComponents(); 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 502d6a7cc..8b4d5ab87 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 @@ -183,4 +183,3 @@ export class TimeEntriesTableComponent implements OnInit, OnDestroy, AfterViewIn return this.resultSumEntriesSelected; } } - diff --git a/src/app/modules/shared/interceptors/spinner.interceptor.spec.ts b/src/app/modules/shared/interceptors/spinner.interceptor.spec.ts index aa7d28bb1..b34ec1ed3 100644 --- a/src/app/modules/shared/interceptors/spinner.interceptor.spec.ts +++ b/src/app/modules/shared/interceptors/spinner.interceptor.spec.ts @@ -16,11 +16,11 @@ describe('SpinnerInterceptorService test', () => { ], }); - class MockHttpHandler implements HttpHandler { - handle(req: HttpRequest): Observable> { - return of(new HttpResponse()); - } + class MockHttpHandler implements HttpHandler { + handle(req: HttpRequest): Observable> { + return of(new HttpResponse()); } + } let overlay: Overlay; let httpHandler: HttpHandler; diff --git a/src/app/modules/shared/interceptors/spinner.interceptor.ts b/src/app/modules/shared/interceptors/spinner.interceptor.ts index 200628271..a69234141 100644 --- a/src/app/modules/shared/interceptors/spinner.interceptor.ts +++ b/src/app/modules/shared/interceptors/spinner.interceptor.ts @@ -17,14 +17,13 @@ export class SpinnerInterceptor implements HttpInterceptor { req: HttpRequest, next: HttpHandler ): Observable> { - if(req.url.endsWith('recent')){ + if (req.url.endsWith('recent')) { const spinnerSubscription: Subscription = this.spinnerOverlayService.spinner$.subscribe(); - return next + return next .handle(req) .pipe(finalize(() => spinnerSubscription.unsubscribe())); - }else{ + } else { return next.handle(req); } - } } diff --git a/src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe.spec.ts b/src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe.spec.ts new file mode 100644 index 000000000..fb5ea1cb0 --- /dev/null +++ b/src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe.spec.ts @@ -0,0 +1,46 @@ +import { SubstractDatePipeDisplayAsFloat } from './substract-date-return-float.pipe'; + +describe('SubstractDatePipeDisplayAsFloat', () => { + it('create an instance', () => { + const pipe = new SubstractDatePipeDisplayAsFloat(); + expect(pipe).toBeTruthy(); + }); + + /*TODO: tests will be more robust if they take into account FIXED_POINT_DIGITS*/ + it('returns the date diff as float hours (xx.xx)', () => { + [ + { endDate: '2021-04-11T10:20:00Z', startDate: '2021-04-11T08:00:00Z', expectedDiff: '2.33' }, + { endDate: '2021-04-11T17:40:00Z', startDate: '2021-04-11T17:10:00Z', expectedDiff: '0.50' }, + { endDate: '2021-04-11T18:18:00Z', startDate: '2021-04-11T18:00:00Z', expectedDiff: '0.30' }, + { endDate: '2021-04-12T12:18:00Z', startDate: '2021-04-11T10:00:00Z', expectedDiff: '26.30' }, + { endDate: '2021-04-12T10:01:00Z', startDate: '2021-04-12T10:00:00Z', expectedDiff: '0.02' }, + { endDate: '2021-04-11T11:27:00Z', startDate: '2021-04-11T10:03:45Z', expectedDiff: '1.39' }, + ].forEach(({ startDate, endDate, expectedDiff }) => { + const fromDate = new Date(endDate); + const substractDate = new Date(startDate); + + const diff = new SubstractDatePipeDisplayAsFloat().transform(fromDate, substractDate); + + expect(diff).toBe(expectedDiff); + }); + }); + + it('returns -.- if fromDate is null', () => { + const fromDate = null; + const substractDate = new Date('2011-04-11T08:00:30Z'); + + const diff = new SubstractDatePipeDisplayAsFloat().transform(fromDate, substractDate); + + expect(diff).toBe('-.-'); + }); + + it('returns -.- if substractDate is null', () => { + const fromDate = new Date('2011-04-11T08:00:30Z'); + const substractDate = null; + + const diff = new SubstractDatePipeDisplayAsFloat().transform(fromDate, substractDate); + + expect(diff).toBe('-.-'); + }); + +}); diff --git a/src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe.ts b/src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe.ts new file mode 100644 index 000000000..318dae1d3 --- /dev/null +++ b/src/app/modules/shared/pipes/substract-date-return-float/substract-date-return-float.pipe.ts @@ -0,0 +1,26 @@ +import { Pipe, PipeTransform } from '@angular/core'; +import * as moment from 'moment'; + +const FIXED_POINT_DIGITS = 2; +@Pipe({ + name: 'substractDateDisplayAsFloat' +}) +export class SubstractDatePipeDisplayAsFloat implements PipeTransform { + + transform(fromDate: Date, substractDate: Date): string { + + if (fromDate === null || substractDate === null) { + return '-.-'; + } + + const startDate = moment(substractDate); + const endDate = moment(fromDate); + const duration = this.getTimeDifference(startDate, endDate); + return duration.asHours().toFixed(FIXED_POINT_DIGITS).toString(); + } + + getTimeDifference(substractDate: moment.Moment, fromDate: moment.Moment): moment.Duration { + return moment.duration(fromDate.diff(substractDate)); + } + +} diff --git a/src/app/modules/shared/services/spinner-overlay.service.ts b/src/app/modules/shared/services/spinner-overlay.service.ts index 1b74a6f27..dc00becfe 100644 --- a/src/app/modules/shared/services/spinner-overlay.service.ts +++ b/src/app/modules/shared/services/spinner-overlay.service.ts @@ -9,8 +9,8 @@ import { SpinnerOverlayComponent } from './../components/spinner-overlay/spinner providedIn: 'root', }) export class SpinnerOverlayService { - public overlayRef: OverlayRef = undefined; static spinner$: any; + public overlayRef: OverlayRef = undefined; constructor(private readonly overlay: Overlay) {}