import { Component, OnInit } from '@angular/core'; import { ActivatedRoute } from '@angular/router'; import { SequenceModalComponent } from '@core/components/sequence-modal/sequence-modal.component'; import { SpinnerService } from '@core/services/spinner.service'; import { ClientSettingsService } from '@features/client-settings/client-settings.service'; import { AutoTableRepository, AutoTableRepositoryFactory, TopLevelCustomLink, TopLevelFilter, ValueComparisonService } from '@yourcause/common'; import { I18nService } from '@yourcause/common/i18n'; import { ModalFactory } from '@yourcause/common/modals'; import { NotifierService } from '@yourcause/common/notifier'; import { maxBy } from 'lodash'; import { AddCustomDataTableModalComponent } from '../add-custom-data-table-modal/add-custom-data-table-modal.component'; import { AddEditCustomOptionModalComponent } from '../add-edit-custom-option-modal/add-edit-custom-option-modal.component'; import { CustomDataTablesService } from '../custom-data-table.service'; import { CustomDataTable, CustomDataTableDetailViewOption, CustomDataTableOption } from '../custom-data-tables.typing'; import { MergeOptionsModalComponent } from '../merge-options-modal/merge-options-modal.component'; @Component({ selector: 'gc-custom-data-table-detail', templateUrl: './custom-data-table-detail.component.html', styleUrls: ['./custom-data-table-detail.component.scss'] }) export class CustomDataTableDetailComponent implements OnInit { id: number; tableName: string; customDataTable: CustomDataTable; repository: AutoTableRepository; defaultLang: string; parentPicklist: CustomDataTable; topLevelFilters: TopLevelFilter[] = []; topLevelCustomLinks: TopLevelCustomLink[] = []; activeText = this.i18n.translate( 'common:textActive', {}, 'Active' ); inactiveText = this.i18n.translate( 'common:textInactive', {}, 'Inactive' ); constructor ( private customDataTablesService: CustomDataTablesService, private activatedRoute: ActivatedRoute, private modalFactory: ModalFactory, private autoTableFactory: AutoTableRepositoryFactory, private notifierService: NotifierService, private valueComparisonService: ValueComparisonService, private spinnerService: SpinnerService, private i18n: I18nService, private clientSettingsService: ClientSettingsService ) { } get customDataTableMap () { return this.customDataTablesService.customDataTableMap; } get allCustomDataTableMap () { return this.customDataTablesService.allCustomDataTableMap; } get customDataTables () { return this.customDataTablesService.customDataTables; } get options () { return this.customDataTableMap[this.id] || []; } get allOptions () { return this.allCustomDataTableMap[this.id] || []; } get isRootZone () { return this.clientSettingsService.clientSettings.isRootClient; } get descriptionText (): string { if (this.parentPicklist) { return this.i18n.translate( 'FORMS:textParentDescriptionForPickListUpdated', { parentName: this.parentPicklist.name }, 'Parent: __parentName__' ); } else { return null; } } get isParentPicklist (): boolean { if (this.options) { return this.options.some((option) => { return option.picklistOptionDependentPicklists.some((dependency) => { return dependency.parentPicklistId === this.customDataTable.id; }); }); } else { return false; } } async ngOnInit () { this.id = this.activatedRoute.snapshot.params.tableId; this.customDataTable = this.customDataTables.find((table) => { return +table.id === + this.id; }); this.setTopLevelFilters(); this.tableName = this.customDataTable.name; this.parentPicklist = await this.customDataTablesService.prepParentCDTData( this.id, this.customDataTable.parentPicklistId ); this.defaultLang = this.customDataTable.defaultLanguageId; const rows = this.getRows(); this.repository = this.autoTableFactory.create({ key: 'CUSTOM_DATA_TABLE' + this.id, columns: [], notifier: this.notifierService, valueComparisonService: this.valueComparisonService, rowsPerPage: 15, rows }); } setTopLevelFilters () { this.topLevelFilters = [ new TopLevelFilter( 'text', 'valueOrKey', '', this.i18n.translate( 'common:textSearchByKeyOrValue', {}, 'Search by key or value' ), undefined, undefined, [{ column: 'value', filterType: 'cn' }, { column: 'key', filterType: 'cn' }] ) ]; const tooltip = this.i18n.translate( 'common:textSetSortOrder', {}, 'Set sort order' ); const item = { name: tooltip, tooltip, icon: 'sort-numeric-down', isIcon: true, onClick: () => { this.setSortOrder(); } }; this.topLevelCustomLinks = [item]; } getRows (): CustomDataTableDetailViewOption[] { return this.customDataTablesService.getOptionsForCustomDataTableDetail(this.id); } async changeInUse (row: CustomDataTableOption) { this.spinnerService.startSpinner(); if (row.inUse) { await this.customDataTablesService.deactivatePicklistOption(row.id); } else if (row.inUse === false) { await this.customDataTablesService.activatePicklistOption(row.id); } await this.resetTableData(); this.spinnerService.stopSpinner(); } async addOrEditItem (option?: CustomDataTableDetailViewOption) { const sortOrder = option?.sortOrder || this.getNextAvailableSortOrder(); const existingSortOrders = this.getRows() .filter(row => row.key !== option?.key) // don't include the current options sortOrder .map(row => row.sortOrder); const response = await this.modalFactory.open( AddEditCustomOptionModalComponent, { dataType: this.customDataTable.dataType, value: option?.value, key: option?.key, sortOrder, parentPicklistId: this.customDataTable.parentPicklistId, parentKeys: option?.parentKeys || [], defaultLang: this.defaultLang, existingSortOrders, existingKeys: this.getRows() .filter(row => row.key !== option?.key) .map(row => row.key.toLowerCase()) } ); if (response) { this.spinnerService.startSpinner(); await this.customDataTablesService.handleAddOrEditOption( this.customDataTable.id, sortOrder, existingSortOrders, response, option, this.defaultLang ); this.repository.rows = this.getRows(); this.repository.reset(); this.spinnerService.stopSpinner(); } } getNextAvailableSortOrder () { const max = maxBy(this.getRows(), 'sortOrder'); return max?.sortOrder ? max.sortOrder + 1 : undefined; } async resetTableData () { await this.customDataTablesService.resetCustomDataTableMap(this.id); this.repository.rows = this.getRows(); this.repository.reset(); } export () { this.customDataTablesService.exportData( this.id, this.defaultLang, !!this.customDataTable.parentPicklistId ); } async import () { const response = await this.modalFactory.open( AddCustomDataTableModalComponent, { importOnly: true, id: this.id, parentPicklistId: this.customDataTable.parentPicklistId } ); if (response) { await this.resetTableData(); } } async merge (option: CustomDataTableDetailViewOption) { const payload = await this.modalFactory.open( MergeOptionsModalComponent, { picklistId: this.id, option, allOptions: this.getRows() } ); if (payload) { this.spinnerService.startSpinner(); await this.customDataTablesService.mergeOptions( payload ); await this.resetTableData(); this.spinnerService.stopSpinner(); } } async setSortOrder () { const items = await this.modalFactory.open( SequenceModalComponent, { modalHeader: this.i18n.translate( 'common:hdrSortOrder', {}, 'Sort Order' ), modalSubHeader: this.i18n.translate( 'common:textTheOrderOptionsShowToTheUser', {}, 'The order options show to the user' ), nameHeader: this.i18n.translate( 'common:textDisplayValue', {}, 'Display value' ), items: this.getRows().map((row) => { return { id: row.id, sequence: row.sortOrder, name: row.value, isDisabledOrInActive: !row.inUse }; }), supportsAlphaSort: true } ); if (items) { this.spinnerService.startSpinner(); await this.customDataTablesService.updateSortOrder(this.id, items); await this.resetTableData(); this.spinnerService.stopSpinner(); } } }