import { Component, Input, OnInit } from '@angular/core'; import { Validators } from '@angular/forms'; import { SpinnerService } from '@core/services/spinner.service'; import { ClientSettingsService } from '@features/client-settings/client-settings.service'; import { FileService, OrganizedError, 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 { CustomDataTablesService, DependentPicklistOptionImport, PicklistOptionImport } from '../custom-data-table.service'; import { CustomDataTable, CustomDataTableExternalContext, CustomDataTableModalPages, PicklistDataType, UpdatePicklistPayload } from '../custom-data-tables.typing'; @Component({ selector: 'gc-add-custom-data-table-modal', templateUrl: './add-custom-data-table-modal.component.html', styleUrls: ['./add-custom-data-table-modal.component.scss'] }) export class AddCustomDataTableModalComponent extends YCModalComponent implements OnInit { @Input() importOnly = false; @Input() id: number; @Input() parentPicklistId: number; showImportRules = false; formGroup: TypeSafeFormGroup<{ tableName: string; defaultLang: string; parentDataTable: CustomDataTable; dataType: PicklistDataType; }>; CustomDataTableModalPages = CustomDataTableModalPages; page = CustomDataTableModalPages.NAME; primaryDisabled: boolean; selectedFile: Blob; importValid = false; externalContext: CustomDataTableExternalContext = { dynamicType: 'string', requiresParentListValidation: false, parentListKeys: null, picklistId: null }; secondaryDisabled: boolean; langKeys: string[]; hasInternational = this.clientSettingsService.clientSettings.hasInternational; dataTableTypeOptions: TypeaheadSelectOption[] = this.customDataTablesService.getDataTypeOptions(); parentDataTableTypeaheadOptions: TypeaheadSelectOption[]; parentDataTable: CustomDataTable; importOnlyText = this.i18n.translate( 'common:textStep2ImportItems4', {}, 'Click the button below to select your completed template. After selecting your template file, we will confirm that the data conforms to the template structure. Once validated click \'Import data\'.' ); importAndCreateText = this.i18n.translate( 'common:textStep2ImportItemsDesc3', {}, 'Click the button below to select your completed template. After selecting your template file, we will confirm that the data conforms to the template structure. Once validated click \'Create and import data\'.' ); parentDataTableText = this.i18n.translate( 'FORMS:textParentCustomDataTableText', {}, 'Select a parent custom data table if the values of your new custom data table are dependent upon the values selected from another custom data table' ); importRulesLinkText = this.i18n.translate( 'FORMS:textClickHeretoViewImportRules', {}, 'Click here to view import rules' ); errors: OrganizedError[]; ValidationClass = PicklistOptionImport; ChildPicklistValidationClass = DependentPicklistOptionImport; constructor ( private fileService: FileService, private customDataTablesService: CustomDataTablesService, private formBuilder: TypeSafeFormBuilder, private spinnerService: SpinnerService, private clientSettingsService: ClientSettingsService, private i18n: I18nService, private analyticsService: AnalyticsService ) { super(); } get isName () { return this.page === CustomDataTableModalPages.NAME; } async ngOnInit () { if (this.hasInternational) { let langKeys = this.clientSettingsService.get('selectedLanguages'); if (langKeys.length === 0) { langKeys = [this.clientSettingsService.defaultLanguage]; } this.langKeys = langKeys; } this.parentDataTableTypeaheadOptions = this.customDataTablesService.pickListTypeaheadOptions; this.page = this.importOnly ? CustomDataTableModalPages.IMPORT : CustomDataTableModalPages.NAME; this.parentDataTable = await this.customDataTablesService.prepParentCDTData( this.id, this.parentPicklistId ); this.formGroup = this.formBuilder.group({ tableName: ['', Validators.required], dataType: PicklistDataType.Text as PicklistDataType, defaultLang: this.clientSettingsService.defaultLanguage, parentDataTable: this.parentDataTable }); await this.handleParentListChange(!!this.parentDataTable); this.setIsDisabled(); } setExternalContextType (type: PicklistDataType) { this.externalContext = { ...this.externalContext, dynamicType: type === PicklistDataType.Numeric ? 'number' : 'string' }; } goToImport () { this.page = CustomDataTableModalPages.IMPORT; this.setIsDisabled(); this.analyticsService.emitEvent({ eventName: 'Go to import', eventType: EventType.Click, extras: null }); } goToName () { this.page = CustomDataTableModalPages.NAME; this.setIsDisabled(); this.analyticsService.emitEvent({ eventName: 'Go to CDT name', eventType: EventType.Click, extras: null }); } handleUpdateValidation (valid: boolean) { this.importValid = valid; this.setIsDisabled(); } setIsDisabled () { if (this.isName) { this.primaryDisabled = this.formGroup.invalid; this.secondaryDisabled = this.formGroup.invalid; } else { this.primaryDisabled = !this.importValid || !this.selectedFile; } } downloadTemplate () { // only include parent key if ID is passed in from formGroup const includeParentKeysColumn = !!this.formGroup.value.parentDataTable; this.customDataTablesService.getTemplateForDownload( this.id, includeParentKeysColumn ); } async handleParentListChange (requiresPicklist: boolean) { // if picklist is selected, update csv validation this.ValidationClass = requiresPicklist ? DependentPicklistOptionImport : PicklistOptionImport; this.externalContext = await this.customDataTablesService.returnExternalContextForCDTValidator( this.formGroup.value.parentDataTable?.guid, this.formGroup.value.parentDataTable?.defaultLanguageId, requiresPicklist, +this.id ); } async createTableOnly () { this.spinnerService.startSpinner(); const parentPickListId = this.formGroup.value.parentDataTable ? this.formGroup.value.parentDataTable.id : null; const id = await this.customDataTablesService.createTable( this.formGroup.value.tableName, this.formGroup.value.defaultLang, this.formGroup.value.dataType, false, parentPickListId ); if (id) { await this.customDataTablesService.resetCustomDataTables(); this.closeModal.emit(); } else { this.closeModal.emit(); } this.spinnerService.stopSpinner(); this.analyticsService.emitEvent({ eventName: 'Add custom data table save', eventType: EventType.Click, extras: null }); } async import () { this.primaryDisabled = true; this.spinnerService.startSpinner(); const id = await this.customDataTablesService.importData( this.id, this.selectedFile ); if (id) { this.closeModal.emit( '/management/program-setup/forms/data-table/' + id ); } else { this.closeModal.emit(); } this.spinnerService.stopSpinner(); this.analyticsService.emitEvent({ eventName: 'Import custom data table', eventType: EventType.Click, extras: null }); } async createAndImport () { this.spinnerService.startSpinner(); const parentPickListId = this.formGroup.value.parentDataTable ? this.formGroup.value.parentDataTable.id : null; const id = await this.customDataTablesService.createAndImportData( this.formGroup.value.tableName, this.selectedFile, this.formGroup.value.defaultLang, this.formGroup.value.dataType, parentPickListId ); if (id) { await this.customDataTablesService.resetCustomDataTables(); this.closeModal.emit( '/management/program-setup/forms/data-table/' + id ); } else { this.closeModal.emit(); } this.spinnerService.stopSpinner(); this.analyticsService.emitEvent({ eventName: 'Create and import', eventType: EventType.Click, extras: null }); } async updateAndImport () { this.spinnerService.startSpinner(); const parentPicklistId = this.formGroup.value.parentDataTable ? this.formGroup.value.parentDataTable.id : null; const payload: UpdatePicklistPayload = { id: this.id, name: this.formGroup.value.tableName, file: this.selectedFile, defaultLanguageId: this.formGroup.value.defaultLang, parentPicklistId }; await this.customDataTablesService.updatePicklist( payload, false ); this.closeModal.emit( '/management/program-setup/forms/data-table/' + this.id ); this.spinnerService.stopSpinner(); } handleContentsChange ( contents: PicklistOptionImport[]|DependentPicklistOptionImport[] ) { contents = this.customDataTablesService.handleSortOrder(contents); const csvString = this.fileService.convertObjectArrayToCSVString(contents); this.selectedFile = new Blob([csvString], { type: 'text/csv' }); } downloadErrors () { const csv = this.fileService.convertObjectArrayToCSVString(this.errors); this.fileService.downloadString(csv, 'text/csv', 'Import_Picklist_Errors.csv'); } onCancel () { if (this.isName) { this.closeModal.emit(); } else { if (this.showImportRules) { this.showImportRules = false; } else { this.page = CustomDataTableModalPages.NAME; } } } }