import { Component, Input, OnInit } from '@angular/core'; import { AbstractControl, Validators } from '@angular/forms'; import { ComponentHelperService } from '@features/formio/services/component-helper/component-helper.service'; import { FormLogicService } from '@features/formio/services/form-logic/form-logic.service'; import { StandardProductConfigurationService } from '@features/platform-admin/standard-product-configuration/standard-product-configuration.service'; import { ArrayHelpersService, TypeaheadSelectOption, TypeSafeFormBuilder, TypeSafeFormGroup } from '@yourcause/common'; import { AnalyticsService, EventType } from '@yourcause/common/analytics'; import { I18nService } from '@yourcause/common/i18n'; import { YCModalComponent } from '@yourcause/common/modals'; import { FormAudience, FormDefinitionComponent, FormTypes } from '../form.typing'; import { FormsService } from '../services/forms/forms.service'; interface AddEditTabFormGroup { tabName: string; formId: number; pageTemplateId: string; startFromTemplate: boolean; } interface AddEditFormTabModalResponse { formGroup: AddEditTabFormGroup; openQuickAdd: boolean; } @Component({ selector: 'gc-add-edit-form-tab-modal', templateUrl: './add-edit-form-tab-modal.component.html', styleUrls: ['./add-edit-form-tab-modal.component.scss'] }) export class AddEditFormTabModalComponent extends YCModalComponent< AddEditFormTabModalResponse > implements OnInit { @Input() tabName: string; @Input() currentFormId: number; @Input() currentFormType: FormTypes; @Input() existingFormComps: FormDefinitionComponent[]; formOptionsForPages: TypeaheadSelectOption[]; pageOptions: TypeaheadSelectOption[]; formGroup: TypeSafeFormGroup; saveDisabled = false; errorMessage: string; loadingTabOptions = false; constructor ( private formBuilder: TypeSafeFormBuilder, private formService: FormsService, private i18n: I18nService, private standardProductService: StandardProductConfigurationService, private arrayHelper: ArrayHelpersService, private analyticsService: AnalyticsService, private formLogicService: FormLogicService, private componentHelper: ComponentHelperService ) { super(); } ngOnInit () { this.setFormOptions(); this.formGroup = this.formBuilder.group({ tabName: [this.tabName || '', Validators.required], formId: null, pageTemplateId: null, startFromTemplate: false }, { validators: this.checkPageSelection() }); } setFormOptions () { const formAudience = this.formService.getAudienceFromFormType(this.currentFormType); const clientOptions = formAudience === FormAudience.MANAGER ? this.formService.managerFormOptions : this.formService.applicantFormOptions; const standardOptions = formAudience === FormAudience.MANAGER ? this.standardProductService.standardManagerFormOptions : this.standardProductService.standardApplicantFormOptions; const allOptions = clientOptions.concat(standardOptions); this.formOptionsForPages = this.arrayHelper.sort( allOptions.filter((formOption) => { return formOption.value !== this.currentFormId; }), 'label' ); } async updatePageOptions () { this.formGroup.get('pageTemplateId').setValue(null); this.loadingTabOptions = true; const formId = this.formGroup.value.formId; this.pageOptions = await this.formLogicService.getPageTemplateOptions( formId, this.formService.getLatestRevisionId(formId, true) ); this.loadingTabOptions = false; } resetTemplateOptions () { this.formGroup.get('formId').setValue(null); this.formGroup.get('pageTemplateId').setValue(null); this.loadingTabOptions = false; this.checkTabComponents(); } checkTabComponents () { if (this.formGroup.value.formId && this.formGroup.value.pageTemplateId) { const formDetail = this.formLogicService.getFormDetail( this.formGroup.value.formId, this.formService.getLatestRevisionId(this.formGroup.value.formId, true) ); const { duplicateFields, duplicateKeys } = this.componentHelper.getDuplicateKeysAndFields( formDetail, this.formGroup.value.pageTemplateId, this.existingFormComps ); const valid = duplicateFields.length === 0 && duplicateKeys.length === 0; this.saveDisabled = !valid; if (!valid) { this.errorMessage = this.getErrorMessageForDuplicates( duplicateFields, duplicateKeys ); } else { this.errorMessage = null; } } else { this.errorMessage = null; this.saveDisabled = false; } } getErrorMessageForDuplicates ( duplicateFields: FormDefinitionComponent[], duplicateKeys: FormDefinitionComponent[] ): string { if (duplicateFields.length > 0) { let errorMessage = `${this.i18n.translate( 'common:textPageTempCannotBeUsedDupeField', {}, 'This template cannot be used because the following field(s) already exist on the form' )}:
`; duplicateFields.forEach((field) => { errorMessage = errorMessage + `
  • ${field.label}
  • `; }); return errorMessage; } else { let errorMessage = `${this.i18n.translate( 'common:textPageTempCannotBeUsedDupeKey', {}, 'This template cannot be used because the following field(s) share the same key as a field on the template. Keys must be unique' )}.
    `; duplicateKeys.forEach((field) => { errorMessage = errorMessage + `
  • ${field.label}
  • `; }); return errorMessage; } } checkPageSelection () { return (group: AbstractControl) => { const formGroupVal = group.value; if (formGroupVal.startFromTemplate && !formGroupVal.pageTemplateId) { return { mustSelectAPage: { pageTemplate: { i18nKey: 'FORMS:textMustSelectATemplateToStartFrom', defaultValue: 'Must select a template to start from' } } }; } return null; }; } handlePrimaryClick () { this.formGroup.value.startFromTemplate ? (this.closeModal.emit({formGroup: this.formGroup.value, openQuickAdd: false})) : (this.closeModal.emit({formGroup: this.formGroup.value, openQuickAdd: true})); this.analyticsService.emitEvent({ eventName: 'Create form', eventType: EventType.Click, extras: null }); } handleSecondaryClick () { this.closeModal.emit({formGroup: this.formGroup.value, openQuickAdd: false}); this.analyticsService.emitEvent({ eventName: 'Create form from template', eventType: EventType.Click, extras: null }); } }