import { Component, Input, OnInit } from '@angular/core'; import { SpinnerService } from '@core/services/spinner.service'; import { ReferenceFieldAPI } from '@core/typings/api/reference-fields.typing'; import { ReferenceFieldsUI } from '@core/typings/ui/reference-fields.typing'; import { FormAudience, FormTypes } from '@features/configure-forms/form.typing'; import { CreateEditReferenceFieldModalComponent } from '@features/reference-fields/create-edit-reference-field-modal/create-edit-reference-field-modal.component'; import { ReferenceFieldsResolver } from '@features/reference-fields/reference-fields.resolver'; import { ReferenceFieldsService } from '@features/reference-fields/services/reference-fields.service'; import { AccordionStyle, TypeToken } from '@yourcause/common'; import { AnalyticsService, EventType } from '@yourcause/common/analytics'; import { I18nService } from '@yourcause/common/i18n'; import { ModalFactory, YCModalComponent } from '@yourcause/common/modals'; import { QuickAddService } from '../services/quick-add/quick-add.service'; @Component({ selector: 'gc-quick-add-modal', templateUrl: './quick-add-modal.component.html', styleUrls: ['./quick-add-modal.component.scss'] }) export class QuickAddModalComponent extends YCModalComponent<{ components: ReferenceFieldsUI.QuickAddField[]; requiredMap: Record; labelMap: Record; }> implements OnInit { @Input() pageName: string; @Input() currentFormRefFields: ReferenceFieldAPI.ReferenceFieldDisplayModel[] = []; @Input() numberOfComps: number; @Input() numberAllowed: number; @Input() formType: FormTypes; @Input() formAudience: FormAudience; hide = false; modalHeader = this.i18n.translate( 'common:hdrQuickAdd', {}, 'Quick Add' ); modalSubHeader: string; primaryDisabled: boolean; secondaryDisabled: boolean; AccordionStyle = AccordionStyle; componentBuckets: ReferenceFieldsUI.QuickAddComponentsForAccordion; componentLabelMap: Record = {}; componentRequiredMap: Record = {}; // this is the original set of component buckets and should always include all components available to add allComponents: ReferenceFieldsUI.QuickAddField[] = []; accordionGroupsForApplicant: ReferenceFieldsUI.QuickAddComponentsForAccordion; accordionGroupsForManager: ReferenceFieldsUI.QuickAddComponentsForAccordion; standardComponents: ReferenceFieldsUI.QuickAddComponentsFlatList; reportFields: ReferenceFieldsUI.QuickAddComponentsFlatList; componentsToAdd: ReferenceFieldsUI.QuickAddField[] = []; filteredComponents: ReferenceFieldsUI.QuickAddField[] = []; searchTerm: string; componentsOnPageText: string; tooltipText: string; invalidDependentPicklists: ReferenceFieldsUI.InvalidDependentPicklist[] = []; refTypesMap = this.referenceFieldsService.getReferenceFieldTypeToLabelMap(); $refType = new TypeToken(); constructor ( private i18n: I18nService, private referenceFieldsService: ReferenceFieldsService, private quickAddService: QuickAddService, private modalFactory: ModalFactory, private spinnerService: SpinnerService, private referenceFieldResolver: ReferenceFieldsResolver, private analyticsService: AnalyticsService ) { super(); } get categoryNameMap () { return this.referenceFieldsService.categoryNameMap; } async ngOnInit () { this.prepModalText(); this.prepComponentBuckets(); this.updateValidity(); } prepModalText () { this.modalSubHeader = this.pageName; this.setCompCountText(); this.tooltipText = this.i18n.translate( 'common:textMaxComponentsPerPageTooltipModal', { numberAllowed: this.numberAllowed }, `To maintain performance when creating and filling out forms, only __numberAllowed__ components can be added to one form page.` ); } setCompCountText () { this.componentsOnPageText = this.i18n.translate( 'common:textComponentsOnPage', { numberOnPage: this.componentsToAdd.length + this.numberOfComps, numberAllowed: this.numberAllowed }, 'Components on page: __numberOnPage__ of __numberAllowed__' ); } onPrimaryClick () { this.defaultLabelValues(); this.closeModal.emit({ components: this.componentsToAdd, requiredMap: this.componentRequiredMap, labelMap: this.componentLabelMap }); this.analyticsService.emitEvent({ eventName: 'Quick add modal save', eventType: EventType.Click, extras: null }); } defaultLabelValues () { this.componentsToAdd.forEach((comp) => { const name = 'referenceFieldId' in comp ? comp.name : comp.label; this.componentLabelMap[comp.key] = this.componentLabelMap[comp.key] || name; }); } setFilteredComponents () { const componentsList = this.allComponents; this.filteredComponents = componentsList.filter((comp) => { const name = 'referenceFieldId' in comp ? comp.name : comp.label; return (name.toLowerCase()).includes(this.searchTerm.toLowerCase()); }); } updateComponentBuckets () { this.prepComponentBuckets(); if (this.searchTerm) { this.setFilteredComponents(); } this.updateValidity(); this.setCompCountText(); } updateValidity () { const tooManyComponents = this.componentsToAdd.length + this.numberOfComps > this.numberAllowed; const noComponentsToAdd = this.componentsToAdd.length <= 0; this.primaryDisabled = tooManyComponents || noComponentsToAdd || this.invalidDependentPicklists.length > 0; this.secondaryDisabled = tooManyComponents; } handleRemove (index: number) { this.componentsToAdd = [ ...this.componentsToAdd.slice(0, index), ...this.componentsToAdd.slice(index + 1) ]; } handleRemoveAction ( field: ReferenceFieldAPI.ReferenceFieldDisplayModel, index: number ) { this.handleRemove(index); this.handlePicklistValidity(undefined, field); this.updateComponentBuckets(); } handleAddComponent (field: ReferenceFieldsUI.QuickAddField) { this.componentsToAdd = [ ...this.componentsToAdd, field ]; const name = 'referenceFieldId' in field ? field.name : field.label; this.componentLabelMap[field.key] = this.componentLabelMap[field.key] || name; this.handlePicklistValidity(field); this.updateComponentBuckets(); } handlePicklistValidity ( fieldToAdd?: ReferenceFieldsUI.QuickAddField, fieldToRemove?: ReferenceFieldsUI.QuickAddField ) { this.invalidDependentPicklists = this.referenceFieldsService.handleDependentPicklistValidityForQuickAdd( this.componentsToAdd, this.invalidDependentPicklists, fieldToAdd, fieldToRemove ); } prepComponentBuckets () { this.componentBuckets = this.quickAddService.getFieldsForQuickAddModal( this.formAudience, this.currentFormRefFields, this.formType, this.componentsToAdd ); this.accordionGroupsForManager = this.quickAddService.getQuickAddGroupsForManager(this.componentBuckets); this.accordionGroupsForApplicant = this.quickAddService.getQuickAddGroupsForApplicant(this.componentBuckets); this.standardComponents = this.quickAddService.findStandardComponentsForQuickAdd(this.componentBuckets); this.reportFields = this.quickAddService.getReportGroupsForQuickAdd(this.componentBuckets); this.allComponents = this.quickAddService.getAllComponentsFlatListForQuickAdd(this.componentBuckets); this.setCompCountText(); } async createNewField () { this.hide = true; const response = await this.modalFactory.open( CreateEditReferenceFieldModalComponent, { forcedAudienceSelection: this.formAudience, addingFieldToForm: true } ); if (response) { this.spinnerService.startSpinner(); const newField = await this.referenceFieldsService.handleCreateOrUpdateField( null, response.field, response.tableFields, true ); await this.referenceFieldResolver.resolve(); if (newField) { await this.referenceFieldsService.resetFieldsAndCategories(); this.prepComponentBuckets(); this.handleAddComponent(newField); } this.spinnerService.stopSpinner(); } this.hide = false; } async onSecondaryClick () { await this.createNewField(); this.analyticsService.emitEvent({ eventName: 'Create new field', eventType: EventType.Click, extras: null }); } }