-
Notifications
You must be signed in to change notification settings - Fork 1
fix: #572 allow manual editing in time in when switch project #581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -27,6 +27,11 @@ describe('EntryFieldsComponent', () => { | |
| error: (message?: string, title?: string, override?: Partial<IndividualConfig>) => { }, | ||
| warning: (message?: string, title?: string, override?: Partial<IndividualConfig>) => { } | ||
| }; | ||
| const lastDate = moment().format('YYYY-MM-DD'); | ||
| const startHourTest = moment().add(-5, 'hours').format('HH:mm:ss'); | ||
| const endHourTest = moment().add(-3, 'hours').format('HH:mm:ss'); | ||
| const lastStartHourEntryEntered = new Date(`${lastDate}T${startHourTest.trim()}`).toISOString(); | ||
| const lastEndHourEntryEntered = new Date(`${lastDate}T${endHourTest.trim()}`).toISOString(); | ||
|
|
||
| const state = { | ||
| projects: { | ||
|
|
@@ -57,6 +62,28 @@ describe('EntryFieldsComponent', () => { | |
| }, | ||
| entryList: [], | ||
| message: '', | ||
| timeEntriesDataSource: { data: [ | ||
| { | ||
| activity_id: 'xyz', | ||
| activity_name: 'abc', | ||
| id: 'id-15', | ||
| project_id: 'project-id-15', | ||
| description: 'description for an entry', | ||
| uri: 'abc', | ||
| start_date : moment().toISOString(), | ||
| end_date : moment().toISOString(), | ||
| }, | ||
| { | ||
| activity_id: 'xyz', | ||
| activity_name: 'abc', | ||
| id: 'id-15', | ||
| project_id: 'project-id-15', | ||
| description: 'description for an entry', | ||
| uri: 'abc', | ||
| start_date : lastStartHourEntryEntered, | ||
| end_date : lastEndHourEntryEntered, | ||
| } | ||
| ]} | ||
| }, | ||
| }; | ||
|
|
||
|
|
@@ -134,6 +161,37 @@ describe('EntryFieldsComponent', () => { | |
| expect(toastrServiceStub.error).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('displays error message when new hour entered is in the past of other entry', () => { | ||
| component.newData = entry; | ||
| component.activeEntry = entry ; | ||
| component.setDataToUpdate(entry); | ||
| spyOn(toastrServiceStub, 'error'); | ||
|
|
||
| const hourInTheFuture = moment().add(-6, 'hour').format('HH:mm:ss'); | ||
|
||
| component.entryForm.patchValue({ start_hour : hourInTheFuture}); | ||
| component.onUpdateStartHour(); | ||
|
|
||
| expect(toastrServiceStub.error).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('If start hour is in the past of other entry, reset to initial start_date in form', () => { | ||
|
||
| component.newData = entry; | ||
| component.activeEntry = entry ; | ||
| component.setDataToUpdate(entry); | ||
|
|
||
| const newHour = moment().add(-6, 'hours').format('HH:mm:ss'); | ||
| component.entryForm.patchValue({ start_hour : newHour}); | ||
|
|
||
| spyOn(component.entryForm, 'patchValue'); | ||
| component.onUpdateStartHour(); | ||
|
|
||
| expect(component.entryForm.patchValue).toHaveBeenCalledWith( | ||
| { | ||
| start_hour: component.newData.start_hour | ||
| } | ||
| ); | ||
| }); | ||
|
|
||
| it('If start hour is in the future, reset to initial start_date in form', () => { | ||
| component.newData = entry; | ||
| component.activeEntry = entry ; | ||
|
|
@@ -155,12 +213,37 @@ describe('EntryFieldsComponent', () => { | |
| it('when a start hour is updated, then dispatch UpdateActiveEntry', () => { | ||
| component.activeEntry = entry ; | ||
| component.setDataToUpdate(entry); | ||
| const newHour = moment().format('HH:mm:ss'); | ||
|
||
| component.entryForm.patchValue({ start_hour : newHour}); | ||
| spyOn(store, 'dispatch'); | ||
|
|
||
| component.onUpdateStartHour(); | ||
| expect(store.dispatch).toHaveBeenCalled(); | ||
| }); | ||
|
|
||
| it('when a start hour is update, then select the last time entry', async(() => { | ||
|
||
| component.activeEntry = entry ; | ||
| component.setDataToUpdate(entry); | ||
| const newHour = moment().format('HH:mm:ss'); | ||
|
|
||
| component.entryForm.patchValue({ start_hour : newHour}); | ||
| component.onUpdateStartHour(); | ||
|
|
||
| expect(component.lastEntry).toBe(state.entries.timeEntriesDataSource.data[1]); | ||
| })); | ||
|
|
||
| it('when a start hour is updated in other time entry, then dispatch UpdateEntry and UpdateEntryRunning', () => { | ||
|
||
| component.activeEntry = entry ; | ||
| component.setDataToUpdate(entry); | ||
|
|
||
| const newHour = moment().add(-4, 'hours').format('HH:mm:ss'); | ||
| component.entryForm.patchValue({ start_hour : newHour}); | ||
| spyOn(store, 'dispatch'); | ||
|
|
||
| component.onUpdateStartHour(); | ||
| expect(store.dispatch).toHaveBeenCalledTimes(2); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You might want to verify here the above-mentioned actions have been dispatched.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ok, it's tested |
||
| }); | ||
|
|
||
| it('when a technology is added, then dispatch UpdateActiveEntry', () => { | ||
| const addedTechnologies = ['react']; | ||
| spyOn(store, 'dispatch'); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,8 +3,7 @@ import { EntryActionTypes, LoadActiveEntry } from './../../store/entry.actions'; | |
| import { filter } from 'rxjs/operators'; | ||
| import { Component, OnInit } from '@angular/core'; | ||
| import { FormBuilder, FormGroup } from '@angular/forms'; | ||
| import { Store, ActionsSubject } from '@ngrx/store'; | ||
|
|
||
| import { Store, ActionsSubject, select } from '@ngrx/store'; | ||
| import { Activity, NewEntry } from '../../../shared/models'; | ||
| import { ProjectState } from '../../../customer-management/components/projects/components/store/project.reducer'; | ||
| import { TechnologyState } from '../../../shared/store/technology.reducers'; | ||
|
|
@@ -15,6 +14,7 @@ import * as entryActions from '../../store/entry.actions'; | |
| import * as moment from 'moment'; | ||
| import { ToastrService } from 'ngx-toastr'; | ||
| import { formatDate } from '@angular/common'; | ||
| import { getTimeEntriesDataSource } from '../../store/entry.selectors'; | ||
|
|
||
| type Merged = TechnologyState & ProjectState & ActivityState; | ||
|
|
||
|
|
@@ -29,13 +29,15 @@ export class EntryFieldsComponent implements OnInit { | |
| activities: Activity[] = []; | ||
| activeEntry; | ||
| newData; | ||
| lastEntry; | ||
|
|
||
| constructor( | ||
| private formBuilder: FormBuilder, | ||
| private store: Store<Merged>, | ||
| private actionsSubject$: ActionsSubject, | ||
| private toastrService: ToastrService | ||
| ) { | ||
| this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1)); | ||
| this.entryForm = this.formBuilder.group({ | ||
| description: '', | ||
| uri: '', | ||
|
|
@@ -57,11 +59,13 @@ export class EntryFieldsComponent implements OnInit { | |
|
|
||
| this.actionsSubject$ | ||
| .pipe( | ||
| filter((action: any) => ( | ||
| action.type === EntryActionTypes.CREATE_ENTRY_SUCCESS || | ||
| action.type === EntryActionTypes.UPDATE_ENTRY_SUCCESS | ||
| )) | ||
| ).subscribe((action) => { | ||
| filter( | ||
| (action: any) => | ||
| action.type === EntryActionTypes.CREATE_ENTRY_SUCCESS || | ||
| action.type === EntryActionTypes.UPDATE_ENTRY_SUCCESS | ||
| ) | ||
| ) | ||
| .subscribe((action) => { | ||
| if (!action.payload.end_date) { | ||
| this.store.dispatch(new LoadActiveEntry()); | ||
| this.store.dispatch(new entryActions.LoadEntriesSummary()); | ||
|
|
@@ -126,10 +130,36 @@ export class EntryFieldsComponent implements OnInit { | |
| this.entryForm.patchValue({ start_hour: this.newData.start_hour }); | ||
| return; | ||
| } | ||
|
|
||
| this.getLastEntry(); | ||
|
|
||
| const isFirstEntry = this.lastEntry !== undefined ? this.lastEntry.start_date : moment().add(-1, 'hours'); | ||
| const isEntryDateInLastStartDate = moment(newHourEntered).isBefore(isFirstEntry); | ||
| if (isEntryDateInLastStartDate) { | ||
| this.toastrService.error('You cannot start a time-entry before another time-entry'); | ||
|
||
| this.entryForm.patchValue({ start_hour: this.newData.start_hour }); | ||
| return; | ||
| } | ||
| this.entryForm.patchValue({ start_date: newHourEntered }); | ||
| this.dispatchEntries(newHourEntered); | ||
| } | ||
|
|
||
| private dispatchEntries(newHourEntered) { | ||
| const isFirstEntry = this.lastEntry !== undefined ? this.lastEntry.end_date : moment().add(-1, 'hours'); | ||
| const isInLastEntry = moment(newHourEntered).isBefore(isFirstEntry); | ||
| if (isInLastEntry) { | ||
| this.store.dispatch(new entryActions.UpdateEntry({ id: this.lastEntry.id, end_date: newHourEntered })); | ||
| } | ||
| this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, ...this.entryForm.value })); | ||
| } | ||
|
|
||
| private getLastEntry() { | ||
| const lastEntry$ = this.store.pipe(select(getTimeEntriesDataSource)); | ||
| lastEntry$.subscribe((entry) => { | ||
| this.lastEntry = entry.data[1]; | ||
| }); | ||
| } | ||
|
|
||
| onTechnologyAdded($event: string[]) { | ||
| this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, technologies: $event })); | ||
| } | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not quite sure about what are you testing here. Correct me if I am wrong please:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes, it's the same, the name could be:
Displays an error message when new entry has start_time before end time of last entry