UNPKG

@adaptabletools/adaptable

Version:

Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements

147 lines (146 loc) 7.57 kB
import { ArrayExtensions } from '../Extensions/ArrayExtensions'; import StringExtensions from '../Extensions/StringExtensions'; import { AlertModuleId } from '../Constants/ModuleConstants'; import { SERVER_VALIDATION_HEADER, SERVER_VALIDATION_MESSAGE_TYPE, } from '../Constants/GeneralConstants'; import { errorOnce } from '../../agGrid/AdaptableLogger'; export class ValidationService { constructor(adaptableApi) { this.adaptableApi = adaptableApi; this.adaptableApi = adaptableApi; } // Not sure where to put this: was in the Module but might be better here until I can work out a way of having an event with a callback... getValidationRulesForDataChange(cellDataChangedInfo) { // if the new value is the same as the old value then we can get out as we dont see it as an edit? if (cellDataChangedInfo.oldValue == cellDataChangedInfo.newValue) { return []; } let editingRules = this.adaptableApi.alertApi.internalApi .getAlertDefinitionsWithPreventEdit() .filter((v) => this.adaptableApi.columnScopeApi.isColumnInScope(cellDataChangedInfo.column, v.Scope)); let failedValidations = []; if (ArrayExtensions.IsNotEmpty(editingRules)) { editingRules.forEach((alertDefinition) => { if (alertDefinition.Rule.BooleanExpression) { let isSatisfiedExpression = false; try { isSatisfiedExpression = cellDataChangedInfo.rowNode != null && this.adaptableApi.internalApi .getQueryLanguageService() .evaluateBooleanExpression(alertDefinition.Rule.BooleanExpression, AlertModuleId, cellDataChangedInfo.rowNode); } catch (error) { isSatisfiedExpression = false; errorOnce(error.message); } if (isSatisfiedExpression) { failedValidations.push(alertDefinition); } } else { if (this.IsAlertDefinitionTriggered(alertDefinition, cellDataChangedInfo)) { failedValidations.push(alertDefinition); } } }); } return failedValidations; } performValidation(cellDataChangedInfo) { const failedRules = this.getValidationRulesForDataChange(cellDataChangedInfo); if (failedRules.length > 0) { let alert = { alertType: 'cellChanged', header: 'Alert', message: 'Perform Edit Alert Fired', alertDefinition: failedRules[0], cellDataChangedInfo: cellDataChangedInfo, }; this.adaptableApi.eventApi.internalApi.fireAlertFiredEvent(alert); // This is not needed because the change event is triggered regardless // if the edit is succesful. This is because (I think) Adaptable uses a non-standard way ot detecting data changes. // https://github.com/AdaptableTools/adaptable/issues/2197 // failedRules.forEach((alertDefinition) => { // const alert: AdaptableAlert = ObjectFactory.CreateCellChangedAlert( // cellDataChangedInfo.column.friendlyName, // this.adaptableApi.alertApi.internalApi.getAlertDescription( // alertDefinition, // cellDataChangedInfo // ), // alertDefinition, // cellDataChangedInfo // ); // this.adaptableApi.alertApi.showAdaptableAlert(alert); // }); return false; } return true; } IsAlertDefinitionTriggered(alertDefinition, dataChangedEvent) { const displayValue = this.adaptableApi.gridApi.getDisplayValueFromRowNode(dataChangedEvent.rowNode, dataChangedEvent.column.columnId); const predicateDefHandlerContext = { value: dataChangedEvent.newValue, oldValue: dataChangedEvent.oldValue, displayValue, node: dataChangedEvent.rowNode, column: dataChangedEvent.column, ...this.adaptableApi.internalApi.buildBaseContext(), }; return this.adaptableApi.predicateApi.handlePredicates(alertDefinition.Rule?.Predicates, predicateDefHandlerContext, false); } performServerValidation(cellDataChangedInfo, config) { const serverValidationContext = { cellDataChangedInfo: cellDataChangedInfo, ...this.adaptableApi.internalApi.buildBaseContext(), }; return () => { this.adaptableApi.optionsApi .getEditOptions() .validateOnServer(serverValidationContext) .then((validationResult) => { if (validationResult.newCellValue === undefined) { validationResult.newCellValue = cellDataChangedInfo.newValue; } // If they have changed the return value then we should update the grid, log the function change // otherwise the value will persist if (validationResult.newCellValue !== cellDataChangedInfo.newValue) { cellDataChangedInfo.newValue = validationResult.newCellValue; // this.adaptable.setValue(cellDataChangedInfo, false); const row = cellDataChangedInfo.rowNode?.data; if (!row) { return; } row[this.adaptableApi.columnApi.internalApi.getAgGridColumnFieldForAdaptableColumn(cellDataChangedInfo.column.columnId) ?? cellDataChangedInfo.column.columnId] = validationResult.newCellValue; this.adaptableApi.gridApi.updateGridData([row]); if (StringExtensions.IsNotNullOrEmpty(validationResult.validationMessage) && this.adaptableApi.optionsApi.getEditOptions().displayServerValidationMessages) { const validationHeader = validationResult.validationHeader ? validationResult.validationHeader : SERVER_VALIDATION_HEADER; const messageType = validationResult.messageType ? validationResult.messageType : SERVER_VALIDATION_MESSAGE_TYPE; this.adaptableApi.alertApi.showAlert(validationHeader, validationResult.validationMessage, messageType); } } config.onServerValidationCompleted(); }); return false; }; } createValidationDescription(alertDefinition) { return (this.adaptableApi.columnScopeApi.getScopeDescription(alertDefinition.Scope) + ' ' + alertDefinition.Rule?.Predicates?.map((predicate) => this.adaptableApi.predicateApi.predicateToString(predicate)).join(' AND ')); } createValidationMessage(alertDefinition) { let returnMessage = this.createValidationDescription(alertDefinition); if (alertDefinition.Rule.BooleanExpression) { returnMessage += ' when ' + alertDefinition.Rule.BooleanExpression; } return returnMessage; } destroy() { // TO DO } }