@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
JavaScript
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
}
}