UNPKG

@adaptabletools/adaptable

Version:

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

239 lines (238 loc) 12.9 kB
import * as InternalRedux from '../../Redux/ActionsReducers/InternalRedux'; import * as PopupRedux from '../../Redux/ActionsReducers/PopupRedux'; import * as AlertRedux from '../../Redux/ActionsReducers/AlertRedux'; import { ApiBase } from './ApiBase'; import * as ModuleConstants from '../../Utilities/Constants/ModuleConstants'; import ObjectFactory from '../../Utilities/ObjectFactory'; import { isAdaptableCellChangedAlert, isAdaptableRowChangedAlert, } from '../../AdaptableState/Common/AdaptableAlert'; import StringExtensions from '../../Utilities/Extensions/StringExtensions'; import { AlertInternalApi } from '../Internal/AlertInternalApi'; export class AlertApiImpl extends ApiBase { constructor(_adaptable) { super(_adaptable); this.internalApi = new AlertInternalApi(_adaptable); } getAlertState() { return this.getAdaptableState().Alert; } getAlertDefinitions(config) { return (this.handleLayoutAssociatedObjects(this.getAlertState().AlertDefinitions, 'Alert', config) ?? []); } getSuspendedAlertDefinitions(config) { return this.getAlertDefinitions(config).filter((alertDefinition) => alertDefinition.IsSuspended); } getActiveAlertDefinitions(config) { return this.getAlertDefinitions(config).filter((alertDefinition) => !alertDefinition.IsSuspended); } deleteAlertDefinition(alertDefinition) { this.dispatchAction(AlertRedux.AlertDefinitionDelete(alertDefinition)); } getAlertDefinitionById(id) { return this.getAlertDefinitions().find((alert) => alert?.Uuid === id); } addAlertDefinition(alertDefinition) { this.addUidToAdaptableObject(alertDefinition); this.dispatchAction(AlertRedux.AlertDefinitionAdd(alertDefinition)); return this.getAlertDefinitionById(alertDefinition.Uuid); } async displayAdaptableAlert(alertToShow) { // There are 3 things we always do with an alert: // 1. Dispatch the Alert (so it appears in the toolbar) this.addUidToAdaptableObject(alertToShow); this.dispatchAction(InternalRedux.AdaptableAlertAdd(alertToShow, this.getAlertOptions().maxAlertsInStore)); // 2. Publish the Alert Fired Event this.getEventApi().internalApi.fireAlertFiredEvent(alertToShow); // 3. Manage the many different possible Alert behaviours // Note: alertProperties.PreventEdit is handled separately, in the Adaptable.setupColumnValueSetter() function if (alertToShow.alertDefinition && alertToShow.alertDefinition.AlertProperties != undefined) { const alertDefinition = alertToShow.alertDefinition; const alertProperties = alertDefinition.AlertProperties; // Show a Toast Popup if (alertProperties.DisplayNotification) { this.displayAdaptableAlertNotification(alertToShow); } // Log to console if (alertProperties.LogToConsole) { this.getAdatableLogger().consoleLogByMessageType(alertToShow.header + ': ' + alertToShow.message, alertDefinition.MessageType); } // Show Alert in a Div (if one has been set) if (alertProperties.ShowInDiv) { let alertDiv; let optionsDiv = this.getContainerOptions().alertContainer; if (optionsDiv) { alertDiv = typeof optionsDiv === 'string' ? document.getElementById(optionsDiv) : optionsDiv; } if (alertDiv) { let alertString = alertToShow.header + ': ' + alertToShow.message; alertDiv.innerHTML = alertString; } } // Jump to the Cell if (alertProperties.JumpToCell && isAdaptableCellChangedAlert(alertToShow) && alertToShow.cellDataChangedInfo) { this.getGridApi().jumpToCell(alertToShow.cellDataChangedInfo.primaryKeyValue, alertToShow.cellDataChangedInfo.column.columnId, alertToShow.cellDataChangedInfo.rowNode); } // Jump to the Row else if (alertProperties.JumpToRow && isAdaptableRowChangedAlert(alertToShow) && alertToShow.rowDataChangedInfo?.rowTrigger === 'Add') { const [firstRowNode] = alertToShow.rowDataChangedInfo.rowNodes; if (firstRowNode) { this.getGridApi().jumpToRow(firstRowNode); } } // For CellChanged Alerts either Highlight the cell or row // for former - we just refresh the cells to trigger a re-evaluation of the Adaptable.setupColumn[Style/Class] if (isAdaptableCellChangedAlert(alertToShow) && alertToShow.cellDataChangedInfo && (alertProperties.HighlightCell || alertProperties.HighlightRow)) { let alertNode = alertToShow.cellDataChangedInfo.rowNode; if (!alertNode) { alertNode = this.getGridApi().getRowNodeForPrimaryKey(alertToShow.cellDataChangedInfo.primaryKeyValue); } if (alertNode) { if (alertProperties.HighlightRow) { this.getGridApi().refreshRowNodes([alertNode]); setTimeout(() => { this.dispatchAction(InternalRedux.AdaptableAlertRemoveRowHighlight(alertToShow)); }, this.getAlertOptions().rowHighlightDuration); } if (alertProperties.HighlightCell) { this.getGridApi().refreshCell(alertNode, alertToShow.cellDataChangedInfo.column.columnId); setTimeout(() => { this.dispatchAction(InternalRedux.AdaptableAlertRemoveCellHighlight(alertToShow)); }, this.getAlertOptions().cellHighlightDuration); } } } // For RowChange Alerts only Highlight the row - we just refresh the rows to trigger a re-evaluation of the Adaptable.setupColumn[Style/Class] else if (alertProperties.HighlightRow && isAdaptableRowChangedAlert(alertToShow) && alertToShow.rowDataChangedInfo?.rowTrigger === 'Add') { this.getGridApi().refreshRowNodes(alertToShow.rowDataChangedInfo.rowNodes); setTimeout(() => { this.dispatchAction(InternalRedux.AdaptableAlertRemoveRowHighlight(alertToShow)); }, this.getAlertOptions().rowHighlightDuration); } } } displayAdaptableAlertNotification(alert) { this.dispatchAction(PopupRedux.PopupShowAlert(alert)); } async showAlert(alertHeader, alertMessage, messageType, alertProperties) { const alertDefinition = ObjectFactory.CreateInternalAlertDefinitionForMessages(messageType, alertProperties); let alertToShow = ObjectFactory.CreateGenericAlert(alertHeader, alertMessage, alertDefinition); await this.displayAdaptableAlert(alertToShow); } async showAlertInfo(alertHeader, alertMessage, alertProperties) { await this.showAlert(alertHeader, alertMessage, 'Info', alertProperties); } async showAlertSuccess(alertHeader, alertMessage, alertProperties) { await this.showAlert(alertHeader, alertMessage, 'Success', alertProperties); } async showAlertWarning(alertHeader, alertMessage, alertProperties) { await this.showAlert(alertHeader, alertMessage, 'Warning', alertProperties); } async showAlertError(alertHeader, alertMessage, alertProperties) { await this.showAlert(alertHeader, alertMessage, 'Error', alertProperties); } openAlertSettingsPanel() { this.showModulePopup(ModuleConstants.AlertModuleId); } editAlertDefinition(alertDefinition) { this.dispatchAction(AlertRedux.AlertDefinitionEdit(alertDefinition)); return this.getAlertDefinitionById(alertDefinition.Uuid); } suspendAlertDefinition(alertDefinition) { this.dispatchAction(AlertRedux.AlertDefinitionSuspend(alertDefinition)); return this.getAlertDefinitionById(alertDefinition.Uuid); } suspendAllAlertDefinition() { this.dispatchAction(AlertRedux.AlertDefinitionSuspendAll()); } unSuspendAllAlertDefinition() { this.dispatchAction(AlertRedux.AlertDefinitionUnSuspendAll()); } unSuspendAlertDefinition(alertDefinition) { this.dispatchAction(AlertRedux.AlertDefinitionUnSuspend(alertDefinition)); return this.getAlertDefinitionById(alertDefinition.Uuid); } evaluateAlertDefinitions(alertDefinitions) { const filterScopeAllDefinitions = (alertDefinition) => { if (this.getColumnScopeApi().scopeIsAll(alertDefinition.Scope) && !this.getExpressionApi().getAdaptableQueryExpression(alertDefinition.Rule)) { // we don't support scope ALL without an expression // the predicates for scope ALL do NOT make any sense for a programmatic evaluation return false; } return true; }; const relevantAlertDefinitions = alertDefinitions.filter((alertDefinition) => filterScopeAllDefinitions(alertDefinition)); const relevantColumnIds = new Set(); relevantAlertDefinitions.forEach((alertDefinition) => { this.getRelevantColumnIdsForAlertDefinition(alertDefinition).forEach((relevantColumnId) => relevantColumnIds.add(relevantColumnId)); }); if (!relevantColumnIds.size) { return; } const cellDataChangedInfos = this.createCellDataChangeInfoStubs(Array.from(relevantColumnIds)); cellDataChangedInfos.forEach((cellDataChangedInfo) => { const alertDefinitions = this.internalApi .getAlertDefinitionsForCellDataChange(cellDataChangedInfo) .filter((alertDefinition) => filterScopeAllDefinitions(alertDefinition)) // some alert definitions might NOT be relevant for the given locator .filter((alertDefinition) => relevantAlertDefinitions.some((relevantAlertDefinition) => relevantAlertDefinition.Uuid === alertDefinition.Uuid)); this.getAlertApi().internalApi.showAlertForDefinitions(cellDataChangedInfo, alertDefinitions); }); } findAlertDefinitions(criteria) { return this.getAdaptableInternalApi().findAdaptableObjectsByLookupCriteria(criteria, this.getAlertDefinitions({ includeLayoutNotAssociatedObjects: true, })); } getRelevantColumnIdsForAlertDefinition(alertDefinition) { // if there is an Expression defined, extract only the columns from there (in that case the Scope would be 'All' anyway) // columns referenced in rule expression const ruleExpression = this.getExpressionApi().getAdaptableQueryExpression(alertDefinition.Rule); if (this.getColumnScopeApi().scopeIsAll(alertDefinition.Scope) && StringExtensions.IsNotNullOrEmpty(ruleExpression)) { // return only first referenced column (otherwise we would generate multiple alerts for the same row) const queryColumns = this.getAdaptableInternalApi() .getQueryLanguageService() .getColumnsFromExpression(ruleExpression); return queryColumns.length > 0 ? [queryColumns[0]] : []; } else { // otherwise return all columns for given scope return this.getColumnScopeApi() .getColumnsInScope(alertDefinition.Scope) .map((adaptableColumn) => adaptableColumn.columnId); } } createCellDataChangeInfoStubs(relevantColumnIds) { const cellDataChangeInfos = []; //const adaptable: IAdaptable = this.getAdaptableInternalApi().getAdaptableInstance(); const relevantColumns = this.getColumnApi() .getColumnsWithColumnIds(relevantColumnIds) .filter(Boolean); const changedAt = Date.now(); this.getAdaptableInternalApi().forAllRowNodesDo((rowNode) => { relevantColumns.forEach((column) => { const cellDataChangeInfoStub = { changedAt, rowNode, column, rowData: rowNode.data, oldValue: null, newValue: this.getGridApi().getRawValueFromRowNode(rowNode, column.columnId), primaryKeyValue: this.getGridApi().getPrimaryKeyValueForRowNode(rowNode), }; cellDataChangeInfos.push(cellDataChangeInfoStub); }); }); return cellDataChangeInfos; } }