import { Component, EventEmitter, Input, OnDestroy, OnInit, Output } from '@angular/core'; import { ReferenceFieldAPI } from '@core/typings/api/reference-fields.typing'; import { BaseApplication } from '@core/typings/application.typing'; import { ReferenceFieldsUI } from '@core/typings/ui/reference-fields.typing'; import { FormDefinitionComponent } from '@features/configure-forms/form.typing'; import { ReferenceFieldsService } from '@features/reference-fields/services/reference-fields.service'; import { TypeToken } from '@yourcause/common'; import { I18nService } from '@yourcause/common/i18n'; import { cloneDeep } from 'lodash'; import { Subscription } from 'rxjs'; @Component({ selector: 'gc-data-set-field', templateUrl: './gc-data-set-field.component.html', styleUrls: ['./gc-data-set-field.component.scss'] }) export class GCDataSetComponent implements OnInit, OnDestroy { @Input() data: ReferenceFieldsUI.TableResponseRowForUi[]; @Input() hideLabel: boolean; @Input() disabled: boolean; @Input() tabIndex: number; @Input() label: string; @Input() description: string; @Input() rowsPerPage: number; @Input() parentFields: Partial; @Input() maxNumberOfResponses: number; @Input() itemsShownBeforeScroll: number; @Input() tooltipText: string; @Input() srOnlyLabel: boolean; @Input() field: ReferenceFieldAPI.ReferenceFieldDisplayModel; @Input() translations: Record; @Input() component: FormDefinitionComponent; @Output() onDataChanged = new EventEmitter(); dataColumnHeader: string; DataSetCollectionType = ReferenceFieldAPI.DataSetCollectionType; rowsForTable: ReferenceFieldsUI.DataPointForUI[] = []; rows: ReferenceFieldsUI.TableResponseRowForUi[]; sub = new Subscription(); totalIcon: string; scrollSetting: Record; afterInit = false; $string = new TypeToken(); $number = new TypeToken(); constructor ( private referenceFieldService: ReferenceFieldsService, private i18n: I18nService ) { this.sub.add( this.referenceFieldService.changesTo$('applicationFormTableRowsMap') .subscribe((value) => { if ( this.component && this.field ) { if ( this.parentFields?.applicationFormId || this.parentFields?.revisionId ) { const key = this.referenceFieldService.getTableFormKey( this.parentFields.applicationFormId || this.parentFields.revisionId, this.field.referenceFieldId ); const updatedRows = value[key]; const rowId = updatedRows[0]?.rowId; if (rowId !== this.rows[0]?.rowId) { this.rows[0].rowId = rowId; } } } }) ); } async ngOnInit () { if (this.field?.referenceFieldId) { await this.prepDataPoints(); this.setRowsFromData(); this.adaptToCollectionType(); } this.scrollSetting = this.getScrollClassFromConfig( this.itemsShownBeforeScroll ); this.afterInit = true; } getScrollClassFromConfig (itemCount: number) { const styleObj = { 'max-height': '' + (48 + (itemCount || 5) * 70) + 'px' }; return styleObj; } async prepDataPoints () { await this.referenceFieldService.setDataPointsForSubset( this.field.referenceFieldId ); } setRowsFromData (data = this.data) { const rows = cloneDeep(data || []); const { rowsForTable, dataRows, dataRowsWereUpdated } = this.referenceFieldService.mapRowsForSubset( rows, this.field.referenceFieldId, this.field.subsetCollectionType === ReferenceFieldAPI.DataSetCollectionType.YesOrNo ); this.rows = dataRows; this.rowsForTable = rowsForTable; if (dataRowsWereUpdated) { this.emitRows(); } } adaptToCollectionType () { switch (this.field.subsetCollectionType) { case ReferenceFieldAPI.DataSetCollectionType.Number: this.dataColumnHeader = this.i18n.translate( 'common:textNumber', {}, 'Number' ); break; case ReferenceFieldAPI.DataSetCollectionType.Percent: this.dataColumnHeader = this.i18n.translate( 'common:textPercentage', {}, 'Percentage' ); this.totalIcon = 'percent'; break; default: case ReferenceFieldAPI.DataSetCollectionType.YesOrNo: this.dataColumnHeader = this.i18n.translate( 'common:textSelectIfApplicable', {}, 'Select if applicable' ); break; } } handleOnChange ( response: number|boolean, row: ReferenceFieldsUI.DataPointForUI, dataPointIndex: number, isCheckbox: boolean ) { row.value = response; const value = (isCheckbox && typeof(response) === 'boolean') ? this.referenceFieldService.convertCheckboxValueToNumber(response) : response as number; const rowIndex = 0; // Subsets only have 1 row this.rows = [ ...this.rows.slice(0, rowIndex), { ...this.rows[rowIndex], columns: [ ...this.rows[rowIndex].columns.slice(0, dataPointIndex), { ...this.rows[rowIndex].columns[dataPointIndex], value }, ...this.rows[rowIndex].columns.slice(dataPointIndex + 1) ] }, ...this.rows.slice(rowIndex + 1) ]; this.emitRows(); } emitRows () { this.onDataChanged.emit(this.rows); } ngOnDestroy () { this.sub.unsubscribe(); } }