import { Component , OnInit , OnDestroy } from '@angular/core' ; import { UntilDestroy , untilDestroyed } from '@ngneat/until-destroy' ; import { NbDialogService } from '@nebular/theme' ; import { debounceTime , filter , tap } from 'rxjs/operators' ; import { combineLatest , Subject } from 'rxjs' ; import * as moment from 'moment' ; import * as _ from 'underscore' ; import { NgxPermissionsService } from 'ngx-permissions' ; import { IGetTimeLogInput , IOrganization , ITimeLog , IOrganizationProject , ITimeLogFilters , OrganizationPermissionsEnum } from '@gauzy/contracts' ; import { toUTC } from '@gauzy/common-angular' ; import { Store } from './../../../../../@core/services' ; import { TimesheetService , TimesheetFilterService } from './../../../../../@shared/timesheet' ; import { EditTimeLogModalComponent , ViewTimeLogComponent } from './../../../../../@shared/timesheet' ; interface WeeklyDayData { project ? : IOrganizationProject ; dates : any ; } @ UntilDestroy ( { checkProperties : true } ) @ Component ( { selector : 'ngx-weekly' , templateUrl : './weekly.component.html' , styleUrls : [ './weekly.component.scss' ] } ) export class WeeklyComponent implements OnInit , OnDestroy { OrganizationPermissionsEnum = OrganizationPermissionsEnum ; today : Date = new Date ( ) ; logRequest : ITimeLogFilters = { } ; updateLogs$ : Subject < any > = new Subject ( ) ; organization : IOrganization ; weekData : WeeklyDayData [ ] = [ ] ; weekDayList : string [ ] = [ ] ; loading : boolean ; viewTimeLogComponent = ViewTimeLogComponent ; futureDateAllowed : boolean ; selectedEmployeeId : string | null = null ; projectId : string | null = null ; constructor ( private readonly timesheetService , private readonly nbDialogService , private readonly timesheetFilterService , private readonly ngxPermissionsService , private readonly store ) { } addTimeCallback = ( data ) => { if ( data ) { this . updateLogs$ . next ( true ) ; } } ; ngOnInit ( ) { this . logRequest . startDate = moment ( this . today ) . startOf ( 'week' ) . toDate ( ) ; this . logRequest . endDate = moment ( this . today ) . endOf ( 'week' ) . toDate ( ) ; this . updateWeekDayList ( ) ; const storeOrganization$ = this . store . selectedOrganization$ ; const storeEmployee$ = this . store . selectedEmployee$ ; const storeProject$ = this . store . selectedProject$ ; combineLatest ( [ storeOrganization$ , storeEmployee$ , storeProject$ ] ) . pipe ( filter ( ( [ organization ] ) => ! ! organization ) , tap ( ( [ organization , employee , project ] ) => { if ( organization ) { this . organization = organization ; this . selectedEmployeeId = employee ? employee . id : null ; this . projectId = project ? project . id : null ; this . updateLogs$ . next ( true ) ; } } ) , untilDestroyed ( this ) ) . subscribe ( ) ; this . updateLogs$ . pipe ( debounceTime ( 800 ) , tap ( ( ) => this . getLogs ( ) ) , untilDestroyed ( this ) ) . subscribe ( ) ; this . timesheetService . updateLog$ . pipe ( filter ( ( val ) => val === true ) , tap ( ( ) => this . getLogs ( ) ) , untilDestroyed ( this ) ) . subscribe ( ) ; this . ngxPermissionsService . permissions$ . pipe ( untilDestroyed ( this ) ) . subscribe ( async ( ) => { this . futureDateAllowed = await this . ngxPermissionsService . hasPermission ( OrganizationPermissionsEnum . ALLOW_FUTURE_DATE ) ; } ) ; } updateWeekDayList ( ) { const range = { } ; let i = 0 ; const start = moment ( this . logRequest . startDate ) ; while ( start . isSameOrBefore ( this . logRequest . endDate ) && i < 7 ) { const date = start . format ( 'YYYY-MM-DD' ) ; range [ date ] = null ; start . add ( 1 , 'day' ) ; i ++ ; } this . weekDayList = Object . keys ( range ) ; } filtersChange ( $event ) { this . logRequest = $event ; this . updateWeekDayList ( ) ; this . timesheetFilterService . filter = $event ; this . updateLogs$ . next ( true ) ; } async getLogs ( ) { if ( ! this . organization || ! this . logRequest ) { return ; } const { id : organizationId } = this . organization ; const { tenantId } = this . store . user ; const { startDate , endDate } = this . logRequest ; const appliedFilter = _ . pick ( this . logRequest , 'source' , 'activityLevel' , 'logType' ) ; const employeeIds = [ ] ; if ( this . selectedEmployeeId ) { employeeIds . push ( this . selectedEmployeeId ) ; } const projectIds = [ ] ; if ( this . projectId ) { projectIds . push ( this . projectId ) ; } const request = { ... appliedFilter , startDate : toUTC ( startDate ) . format ( 'YYYY-MM-DD HH:mm:ss' ) , endDate : toUTC ( endDate ) . format ( 'YYYY-MM-DD HH:mm:ss' ) , ... ( employeeIds . length > 0 ? { employeeIds } : { } ) , ... ( projectIds . length > 0 ? { projectIds } : { } ) , organizationId , tenantId } ; this . loading = true ; this . timesheetService . getTimeLogs ( request ) . then ( ( logs ) => { this . weekData = _ . chain ( logs ) . groupBy ( 'projectId' ) . map ( ( innerLogs , _projectId ) => { const byDate = _ . chain ( innerLogs ) . groupBy ( ( log ) => moment ( log . startedAt ) . format ( 'YYYY-MM-DD' ) ) . mapObject ( ( res ) => { const sum = res . reduce ( ( iteratee , log ) => { return iteratee + log . duration ; } , 0 ) ; return { sum , logs : res } ; } ) . value ( ) ; const project = innerLogs . length > 0 ? innerLogs [ 0 ] . project : null ; const dates = { } ; this . weekDayList . forEach ( ( date ) => { dates [ date ] = byDate [ date ] || 0 ; } ) ; return { project , dates } ; } ) . value ( ) ; } ) . finally ( ( ) => ( this . loading = false ) ) ; } openAddEdit ( timeLog ? ) { this . nbDialogService . open ( EditTimeLogModalComponent , { context : { timeLog } } ) . onClose . pipe ( untilDestroyed ( this ) ) . subscribe ( ( data ) => { if ( data ) { this . updateLogs$ . next ( true ) ; } } ) ; } openAddByDateProject ( date , project ) { const minutes = moment ( ) . minutes ( ) ; const stoppedAt = new Date ( moment ( date ) . format ( 'YYYY-MM-DD' ) + ' ' + moment ( ) . set ( 'minutes' , minutes - ( minutes % 10 ) ) . format ( 'HH:mm' ) ) ; const startedAt = moment ( stoppedAt ) . subtract ( '1' , 'hour' ) . toDate ( ) ; this . nbDialogService . open ( EditTimeLogModalComponent , { context : { timeLog : { startedAt , stoppedAt , organizationContactId : project ? project . organizationContactId : null , projectId : project ? project . id : null , ... ( this . logRequest . employeeIds ? { employeeId : this . logRequest . employeeIds [ 0 ] } : { } ) } } } ) . onClose . pipe ( untilDestroyed ( this ) ) . subscribe ( ( data ) => { if ( data ) { this . updateLogs$ . next ( true ) ; } } ) ; } allowAdd ( date ) { return this . futureDateAllowed ? true : moment ( date ) . isSameOrBefore ( moment ( ) ) ; } ngOnDestroy ( ) { } }