diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts index 320423770..1b51da9b4 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts +++ b/src/app/modules/shared/components/details-fields/details-fields.component.spec.ts @@ -45,7 +45,7 @@ describe('DetailsFieldsComponent', () => { projects: { projects: [{ id: 'id', name: 'name', project_type_id: '', customer: { name: 'Juan', description: 'sadsa' } }], customerProjects: [{ id: 'id', name: 'name', description: 'description', project_type_id: '123' }], - recentProjects: [{ id: 'id', name: 'name', customer: { name: 'Juan'} }], + recentProjects: [{ id: 'id', name: 'name', customer: { name: 'Juan' } }], isLoading: false, message: '', projectToEdit: undefined, @@ -104,6 +104,19 @@ describe('DetailsFieldsComponent', () => { const mockCurrentDate = '2020-12-01T12:00:00'; + const entryWithoutRequiredFields = { + project_id: 'p1', + project_name: 'ioet inc.', + activity_id: 'a1', + uri: '', + start_date: '2020-02-05', + end_date: '2020-02-05', + start_hour: '00:00', + end_hour: '00:01', + description: '', + technology: '', + }; + beforeEach( waitForAsync(() => { TestBed.configureTestingModule({ @@ -156,7 +169,7 @@ describe('DetailsFieldsComponent', () => { }); it('onClearedComponent project id and name are set to empty', () => { - const search = {term: ''}; + const search = { term: '' }; component.onClearedComponent(search); expect(component.project_id.value).toBe(''); @@ -164,7 +177,7 @@ describe('DetailsFieldsComponent', () => { }); it('should change the listProjectsShowed to listProjects if search is not empty on onClearedComponent', () => { - const search = {term: 'Ioet Inc.'}; + const search = { term: 'Ioet Inc.' }; const listProjects: Project[] = [{ id: '1', name: 'abc', status: 'active' }]; component.listProjects = listProjects; component.onClearedComponent(search); @@ -708,14 +721,65 @@ describe('DetailsFieldsComponent', () => { expect(toastrServiceStub.warning).toHaveBeenCalled(); }); - it('if entry is set to project_name search_fiend is assigned in entryForm', () => { - const listProjects: Project[] = [{ id: 'id', name: 'abc', status: 'active', search_field: 'name'}]; + it('if entry is set to project_name search_field is assigned in entryForm', () => { + const listProjects: Project[] = [{ id: 'id', name: 'abc', status: 'active', search_field: 'name' }]; component.listProjects = listProjects; component.entryToEdit = { ...entryToEdit }; component.ngOnChanges(); expect(component.entryForm.value.project_name).toBe('name'); }); + it('should display a warning message when trying to save time entry of internal app without required fields', () => { + component.entryForm.setValue(entryWithoutRequiredFields); + spyOn(toastrServiceStub, 'warning'); + + component.onSubmit(); + expect(toastrServiceStub.warning).toHaveBeenCalled(); + }); + + it('should not display a warning message when trying to save time entry of internal app with uri and save', () => { + component.entryForm.setValue({ ...entryWithoutRequiredFields, uri: 'TTL-886' }); + spyOn(toastrServiceStub, 'warning'); + spyOn(component.saveEntry, 'emit'); + + component.onSubmit(); + expect(toastrServiceStub.warning).not.toHaveBeenCalled(); + expect(component.saveEntry.emit).toHaveBeenCalled(); + }); + + it('should not display a warning message when trying to save time entry of external customer without required fields and save', () => { + component.entryForm.setValue({ ...entryWithoutRequiredFields, project_name: 'Warby Parker' }); + spyOn(component.saveEntry, 'emit'); + spyOn(toastrServiceStub, 'warning'); + + component.onSubmit(); + expect(toastrServiceStub.warning).not.toHaveBeenCalled(); + + expect(component.saveEntry.emit).toHaveBeenCalled(); + }); + + it('should not display a warning message when trying to save time entry of internal app with description and save', () => { + component.entryForm.setValue({ ...entryWithoutRequiredFields, description: 'Description' }); + spyOn(component.saveEntry, 'emit'); + spyOn(toastrServiceStub, 'warning'); + + component.onSubmit(); + expect(toastrServiceStub.warning).not.toHaveBeenCalled(); + expect(component.saveEntry.emit).toHaveBeenCalled(); + }); + + /* We allow saving time entries with empty fields in uri and description for safari books and english lessons */ + it('should not display a warning message when trying to save time entry of English Lessons without description and save', () => { + component.entryForm.setValue({ ...entryWithoutRequiredFields, project_name: 'ioet inc. - English Lessons' }); + spyOn(toastrServiceStub, 'warning'); + spyOn(component.saveEntry, 'emit'); + + component.onSubmit(); + expect(toastrServiceStub.warning).not.toHaveBeenCalled(); + + expect(component.saveEntry.emit).toHaveBeenCalled(); + }); + /* TODO As part of https://github.com/ioet/time-tracker-ui/issues/424 a new parameter was added to the details-field-component, and now these couple of tests are failing. A solution to this error might be generate a Test Wrapper Component. More details here: diff --git a/src/app/modules/shared/components/details-fields/details-fields.component.ts b/src/app/modules/shared/components/details-fields/details-fields.component.ts index 84b07a576..ca66f7cbf 100644 --- a/src/app/modules/shared/components/details-fields/details-fields.component.ts +++ b/src/app/modules/shared/components/details-fields/details-fields.component.ts @@ -27,6 +27,8 @@ import { DATE_FORMAT, DATE_FORMAT_YEAR } from 'src/environments/environment'; import { TechnologiesComponent } from '../technologies/technologies.component'; import { MatDatepicker } from '@angular/material/datepicker'; import { Observable } from 'rxjs'; +import { EMPTY_FIELDS_ERROR_MESSAGE } from '../../messages'; +import { INTERNAL_APP_STRING, PROJECT_NAME_TO_SKIP } from 'src/app/modules/shared/internal-app-constants'; type Merged = TechnologyState & ProjectState & ActivityState & EntryState; @Component({ @@ -118,8 +120,8 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { }); } - onClearedComponent({term}) { - const isSearchEmpty = (term === ''); + onClearedComponent({ term }) { + const isSearchEmpty = term === ''; if (isSearchEmpty) { this.isTechnologiesDisabled = true; this.entryForm.patchValue({ @@ -168,7 +170,7 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { projectWithSearchField.search_field = `${project.customer.name} - ${project.name}`; this.listRecentProjects.push(projectWithSearchField); }); - }else{ + } else { this.listRecentProjects = this.listProjects; } this.listProjectsShowed = this.listRecentProjects; @@ -331,6 +333,15 @@ export class DetailsFieldsComponent implements OnChanges, OnInit { } onSubmit() { + const emptyValue = ''; + const { project_name, uri, description } = this.entryForm.value; + const areEmptyValues = [uri, description].every(item => item === emptyValue); + const canSkipDescriptionAndURI = PROJECT_NAME_TO_SKIP.some(projectNameItem => project_name.includes(projectNameItem)); + if (project_name.includes(INTERNAL_APP_STRING) && areEmptyValues && !canSkipDescriptionAndURI) { + this.toastrService.warning(EMPTY_FIELDS_ERROR_MESSAGE); + return; + } + if (this.entryForm.invalid) { this.toastrService.warning('Make sure to select a project and activity'); return; diff --git a/src/app/modules/shared/internal-app-constants.ts b/src/app/modules/shared/internal-app-constants.ts new file mode 100644 index 000000000..a5ee3227c --- /dev/null +++ b/src/app/modules/shared/internal-app-constants.ts @@ -0,0 +1,2 @@ +export const INTERNAL_APP_STRING = 'ioet'; +export const PROJECT_NAME_TO_SKIP = ['English Lessons', 'Safari Books']; diff --git a/src/app/modules/shared/messages.ts b/src/app/modules/shared/messages.ts index 472813996..066a280d3 100644 --- a/src/app/modules/shared/messages.ts +++ b/src/app/modules/shared/messages.ts @@ -2,3 +2,4 @@ export const INFO_SAVED_SUCCESSFULLY = 'The data has been saved successfully'; export const INFO_DELETE_SUCCESSFULLY = 'The data has been deleted successfully'; export const UNEXPECTED_ERROR = 'An unexpected error happened, please try again later'; export const PROJECT_DEACTIVATED_SUCCESSFULLY = 'The project has been inactivated successfully'; +export const EMPTY_FIELDS_ERROR_MESSAGE = 'Make sure to add a description and/or ticket number when working on an internal app.'; diff --git a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts index b9ded1ecb..6f0bef903 100644 --- a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts +++ b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.spec.ts @@ -26,8 +26,8 @@ describe('EntryFieldsComponent', () => { let entryForm; const actionSub: ActionsSubject = new ActionsSubject(); const toastrServiceStub = { - error: (message?: string, title?: string, override?: Partial) => { }, - warning: (message?: string, title?: string, override?: Partial) => { } + error: (message?: string, title?: string, override?: Partial) => {}, + warning: (message?: string, title?: string, override?: Partial) => {}, }; const mockDate = '2020-12-01T12:00:00'; const lastDate = moment(mockDate).format(DATE_FORMAT_YEAR); @@ -77,6 +77,8 @@ describe('EntryFieldsComponent', () => { uri: 'abc', start_date: moment().toISOString(), end_date: moment().toISOString(), + project_name: 'project_name', + customer_name: 'customer_name', }, { activity_id: 'xyz', @@ -87,9 +89,11 @@ describe('EntryFieldsComponent', () => { uri: 'abc', start_date: lastStartHourEntryEntered, end_date: lastEndHourEntryEntered, - } - ] - } + project_name: 'project_name', + customer_name: 'customer name', + }, + ], + }, }, }; @@ -100,28 +104,31 @@ describe('EntryFieldsComponent', () => { description: 'description for active entry', uri: 'abc', start_date: moment(mockDate).format(DATE_FORMAT_YEAR), - start_hour: moment(mockDate).format('HH:mm') + start_hour: moment(mockDate).format('HH:mm'), + customer_name: 'ioet', }; const mockEntryOverlap = { - update_last_entry_if_overlap: true + update_last_entry_if_overlap: true, }; - beforeEach(waitForAsync(() => { - TestBed.configureTestingModule({ - declarations: [EntryFieldsComponent], - providers: [ - provideMockStore({ initialState: state }), - { provide: ActionsSubject, useValue: actionSub }, - { provide: ToastrService, useValue: toastrServiceStub } - ], - imports: [FormsModule, ReactiveFormsModule, NgxMaterialTimepickerModule], - }).compileComponents(); - store = TestBed.inject(MockStore); - entryForm = TestBed.inject(FormBuilder); - mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies); - mockProjectsSelector = store.overrideSelector(getCustomerProjects, state.projects); - })); + beforeEach( + waitForAsync(() => { + TestBed.configureTestingModule({ + declarations: [EntryFieldsComponent], + providers: [ + provideMockStore({ initialState: state }), + { provide: ActionsSubject, useValue: actionSub }, + { provide: ToastrService, useValue: toastrServiceStub }, + ], + imports: [FormsModule, ReactiveFormsModule, NgxMaterialTimepickerModule], + }).compileComponents(); + store = TestBed.inject(MockStore); + entryForm = TestBed.inject(FormBuilder); + mockTechnologySelector = store.overrideSelector(allTechnologies, state.technologies); + mockProjectsSelector = store.overrideSelector(getCustomerProjects, state.projects); + }) + ); beforeEach(() => { fixture = TestBed.createComponent(EntryFieldsComponent); @@ -144,15 +151,13 @@ describe('EntryFieldsComponent', () => { spyOn(component.entryForm, 'patchValue'); component.setDataToUpdate(entry); expect(component.entryForm.patchValue).toHaveBeenCalledTimes(1); - expect(component.entryForm.patchValue).toHaveBeenCalledWith( - { - description: entryDataForm.description, - uri: entryDataForm.uri, - activity_id: entryDataForm.activity_id, - start_hour: formatDate(entry.start_date, 'HH:mm', 'en'), - start_date: moment(mockDate).format(DATE_FORMAT_YEAR), - } - ); + expect(component.entryForm.patchValue).toHaveBeenCalledWith({ + description: entryDataForm.description, + uri: entryDataForm.uri, + activity_id: entryDataForm.activity_id, + start_hour: formatDate(entry.start_date, 'HH:mm', 'en'), + start_date: moment(mockDate).format(DATE_FORMAT_YEAR), + }); expect(component.selectedTechnologies).toEqual([]); }); @@ -164,7 +169,7 @@ describe('EntryFieldsComponent', () => { const mockEntry = { ...entry, start_date: startMoment.format(DATE_FORMAT_YEAR), - start_hour: startMoment.format('HH:mm') + start_hour: startMoment.format('HH:mm'), }; component.newData = mockEntry; @@ -210,11 +215,9 @@ describe('EntryFieldsComponent', () => { component.cancelTimeInUpdate(); expect(component.showTimeInbuttons).toEqual(false); - expect(component.entryForm.patchValue).toHaveBeenCalledWith( - { - start_hour: component.newData.start_hour - } - ); + expect(component.entryForm.patchValue).toHaveBeenCalledWith({ + start_hour: component.newData.start_hour, + }); }); it('should reset to current start_date when start_date has an error', () => { @@ -228,11 +231,9 @@ describe('EntryFieldsComponent', () => { spyOn(component.entryForm, 'patchValue'); component.onUpdateStartHour(); - expect(component.entryForm.patchValue).toHaveBeenCalledWith( - { - start_hour: component.newData.start_hour - } - ); + expect(component.entryForm.patchValue).toHaveBeenCalledWith({ + start_hour: component.newData.start_hour, + }); expect(component.showTimeInbuttons).toEqual(false); }); @@ -244,7 +245,7 @@ describe('EntryFieldsComponent', () => { const mockEntry = { ...entry, start_date: startMoment.format(DATE_FORMAT_YEAR), - start_hour: startMoment.format('HH:mm') + start_hour: startMoment.format('HH:mm'), }; component.newData = mockEntry; component.activeEntry = mockEntry; @@ -256,11 +257,9 @@ describe('EntryFieldsComponent', () => { spyOn(component.entryForm, 'patchValue'); component.onUpdateStartHour(); - expect(component.entryForm.patchValue).toHaveBeenCalledWith( - { - start_hour: component.newData.start_hour - } - ); + expect(component.entryForm.patchValue).toHaveBeenCalledWith({ + start_hour: component.newData.start_hour, + }); expect(component.showTimeInbuttons).toEqual(false); }); @@ -279,17 +278,20 @@ describe('EntryFieldsComponent', () => { expect(component.showTimeInbuttons).toEqual(false); }); - it('When start_time is updated, component.last_entry is equal to time entry in the position 1', waitForAsync(() => { - component.newData = mockEntryOverlap; - component.activeEntry = entry; - component.setDataToUpdate(entry); - const updatedTime = moment(mockDate).format('HH:mm'); + it( + 'When start_time is updated, component.last_entry is equal to time entry in the position 1', + waitForAsync(() => { + component.newData = mockEntryOverlap; + component.activeEntry = entry; + component.setDataToUpdate(entry); + const updatedTime = moment(mockDate).format('HH:mm'); - component.entryForm.patchValue({ start_hour: updatedTime }); - component.onUpdateStartHour(); + component.entryForm.patchValue({ start_hour: updatedTime }); + component.onUpdateStartHour(); - expect(component.lastEntry).toBe(state.entries.timeEntriesDataSource.data[1]); - })); + expect(component.lastEntry).toBe(state.entries.timeEntriesDataSource.data[1]); + }) + ); it('When start_time is updated for a time entry. UpdateCurrentOrLastEntry action is dispatched', () => { component.newData = mockEntryOverlap; @@ -310,10 +312,10 @@ describe('EntryFieldsComponent', () => { component.onTechnologyUpdated(addedTechnologies); expect(store.dispatch).toHaveBeenCalled(); - }); it('uses the form to check if is valid or not', () => { + component.activeEntry = entry; entryForm.valid = false; const result = component.entryFormIsValidate(); @@ -339,7 +341,6 @@ describe('EntryFieldsComponent', () => { expect(store.dispatch).toHaveBeenCalled(); }); - it('sets the technologies on the class when entry has technologies', () => { const entryData = { ...entry, technologies: ['foo'] }; @@ -348,7 +349,6 @@ describe('EntryFieldsComponent', () => { expect(component.selectedTechnologies).toEqual(entryData.technologies); }); - it('activites are populated using the payload of the action', () => { const actionSubject = TestBed.inject(ActionsSubject) as ActionsSubject; const action = { @@ -366,17 +366,17 @@ describe('EntryFieldsComponent', () => { { id: '004', name: 'Meeting', - description: 'Some description' + description: 'Some description', }, { id: '005', name: 'ABCD', - description: 'Some description' + description: 'Some description', }, { id: '006', name: 'XYZA', - description: 'Some description' + description: 'Some description', }, ]; @@ -384,17 +384,17 @@ describe('EntryFieldsComponent', () => { { id: '005', name: 'ABCD', - description: 'Some description' + description: 'Some description', }, { id: '004', name: 'Meeting', - description: 'Some description' + description: 'Some description', }, { id: '006', name: 'XYZA', - description: 'Some description' + description: 'Some description', }, ]; @@ -488,17 +488,19 @@ describe('EntryFieldsComponent', () => { }); it('when a activity is not register in DB should show activatefocus in select activity', () => { - const activitiesMock = [{ - id: 'xyz', - name: 'test', - description: 'test1' - }]; + const activitiesMock = [ + { + id: 'xyz', + name: 'test', + description: 'test1', + }, + ]; const data = { activity_id: 'xyz', description: '', start_date: moment().format(DATE_FORMAT_YEAR), start_hour: moment().format('HH:mm'), - uri: '' + uri: '', }; component.activities = activitiesMock; component.entryForm.patchValue({ @@ -517,6 +519,26 @@ describe('EntryFieldsComponent', () => { expect(autofocus).toHaveBeenCalled(); }); }); -}); + it('should show an error message if description and ticket fields are empty for internal apps', () => { + spyOn(toastrServiceStub, 'error'); + const result = component.requiredFieldsForInternalAppExist('ioet', 'project name'); + expect(toastrServiceStub.error).toHaveBeenCalled(); + expect(result).toBe(false); + }); + + it('should return true if customer name does not contain ioet ', () => { + spyOn(toastrServiceStub, 'error'); + const result = component.requiredFieldsForInternalAppExist('customer', 'Project Name'); + expect(toastrServiceStub.error).not.toHaveBeenCalled(); + expect(result).toBe(true); + }); + + it('should return true if customer name contain ioet and project name contain Safari Books', () => { + spyOn(toastrServiceStub, 'error'); + const result = component.requiredFieldsForInternalAppExist('customer', 'Safari Books'); + expect(toastrServiceStub.error).not.toHaveBeenCalled(); + expect(result).toBe(true); + }); +}); diff --git a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts index fd7530868..93f1c0c68 100644 --- a/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts +++ b/src/app/modules/time-clock/components/entry-fields/entry-fields.component.ts @@ -1,6 +1,6 @@ import { ActivityManagementActionTypes } from './../../../activities-management/store/activity-management.actions'; import { EntryActionTypes, LoadActiveEntry } from './../../store/entry.actions'; -import { filter} from 'rxjs/operators'; +import { filter } from 'rxjs/operators'; import { Component, OnDestroy, OnInit, ElementRef, ViewChild } from '@angular/core'; import { FormBuilder, FormGroup } from '@angular/forms'; import { Store, ActionsSubject, select } from '@ngrx/store'; @@ -15,7 +15,9 @@ import { ToastrService } from 'ngx-toastr'; import { formatDate } from '@angular/common'; import { getTimeEntriesDataSource } from '../../store/entry.selectors'; import { DATE_FORMAT } from 'src/environments/environment'; -import { Subscription, } from 'rxjs'; +import { Subscription } from 'rxjs'; +import { EMPTY_FIELDS_ERROR_MESSAGE } from 'src/app/modules/shared/messages'; +import { INTERNAL_APP_STRING, PROJECT_NAME_TO_SKIP } from 'src/app/modules/shared/internal-app-constants'; type Merged = TechnologyState & ProjectState & ActivityState; @@ -25,7 +27,6 @@ type Merged = TechnologyState & ProjectState & ActivityState; styleUrls: ['./entry-fields.component.scss'], }) export class EntryFieldsComponent implements OnInit, OnDestroy { - @ViewChild('autofocus') autofocus!: ElementRef; entryForm: FormGroup; @@ -44,7 +45,7 @@ export class EntryFieldsComponent implements OnInit, OnDestroy { private formBuilder: FormBuilder, private store: Store, private actionsSubject$: ActionsSubject, - private toastrService: ToastrService, + private toastrService: ToastrService ) { this.entryForm = this.formBuilder.group({ description: '', @@ -58,12 +59,14 @@ export class EntryFieldsComponent implements OnInit, OnDestroy { ngOnInit(): void { this.store.dispatch(new LoadActivities()); this.store.dispatch(new entryActions.LoadEntries(new Date().getMonth() + 1, new Date().getFullYear())); - this.loadActivitiesSubscription = this.actionsSubject$ + this.loadActivitiesSubscription = this.actionsSubject$ .pipe(filter((action: any) => action.type === ActivityManagementActionTypes.LOAD_ACTIVITIES_SUCCESS)) .subscribe((action) => { - this.activities = action.payload.filter((item) => item.status !== 'inactive').sort((a, b) => { - return (a.name).localeCompare(b.name); - }); + this.activities = action.payload + .filter((item) => item.status !== 'inactive') + .sort((a, b) => { + return a.name.localeCompare(b.name); + }); this.store.dispatch(new LoadActiveEntry()); }); @@ -96,7 +99,7 @@ export class EntryFieldsComponent implements OnInit, OnDestroy { uri: this.activeEntry.uri, activity_id: this.activeEntry.activity_id, start_date: this.activeEntry.start_date, - start_hour: formatDate(this.activeEntry.start_date, 'HH:mm', 'en') + start_hour: formatDate(this.activeEntry.start_date, 'HH:mm', 'en'), }; this.activateFocus(); }); @@ -108,8 +111,8 @@ export class EntryFieldsComponent implements OnInit, OnDestroy { return this.entryForm.get('start_hour'); } - activateFocus(){ - if ((this.activities.length > 0) && (this.entryForm.value.activity_id === head(this.activities).id)){ + activateFocus() { + if (this.activities.length > 0 && this.entryForm.value.activity_id === head(this.activities).id) { this.autofocus.nativeElement.focus(); } } @@ -132,11 +135,21 @@ export class EntryFieldsComponent implements OnInit, OnDestroy { } entryFormIsValidate() { - return this.entryForm.valid; + let customerName = ''; + let projectName = ''; + this.store.pipe(select(getTimeEntriesDataSource)).subscribe((ds) => { + const dataToUse = ds.data.find((item) => item.project_id === this.activeEntry.project_id); + customerName = dataToUse.customer_name; + projectName = dataToUse.project_name; + }); + if (!this.entryForm.valid) { + this.toastrService.error('Activity is required'); + } + return this.requiredFieldsForInternalAppExist(customerName, projectName) && this.entryForm.valid; } onSubmit() { - if (this.entryFormIsValidate()){ + if (this.entryFormIsValidate()) { this.store.dispatch(new entryActions.UpdateEntryRunning({ ...this.newData, ...this.entryForm.value })); } } @@ -192,4 +205,22 @@ export class EntryFieldsComponent implements OnInit, OnDestroy { this.loadActiveEntrySubscription.unsubscribe(); this.actionSetDateSubscription.unsubscribe(); } + + requiredFieldsForInternalAppExist(customerName, projectName) { + const emptyValue = ''; + const areEmptyValues = [this.entryForm.value.uri, this.entryForm.value.description].every( + (item) => item === emptyValue + ); + + const isInternalApp = customerName.includes(INTERNAL_APP_STRING); + const canSkipDescriptionAndURI = PROJECT_NAME_TO_SKIP.some((projectNameItem) => + projectName.includes(projectNameItem) + ); + + if (isInternalApp && areEmptyValues && !canSkipDescriptionAndURI) { + this.toastrService.error(EMPTY_FIELDS_ERROR_MESSAGE); + return false; + } + return true; + } } diff --git a/src/app/modules/time-clock/pages/time-clock.component.ts b/src/app/modules/time-clock/pages/time-clock.component.ts index 42078d5f3..4a215f15a 100644 --- a/src/app/modules/time-clock/pages/time-clock.component.ts +++ b/src/app/modules/time-clock/pages/time-clock.component.ts @@ -77,7 +77,6 @@ export class TimeClockComponent implements OnInit, OnDestroy { this.stopEntry(); } else { this.entryFieldsComponent.entryForm.get('activity_id').markAsTouched(); - this.toastrService.error('Activity is required'); } }