@adaptabletools/adaptable
Version:
Powerful data-agnostic HTML5 AG Grid extension which provides advanced, cutting-edge functionality to meet all DataGrid requirements
228 lines (227 loc) • 11 kB
JavaScript
import * as AlertRedux from '../Redux/ActionsReducers/AlertRedux';
import * as InternalRedux from '../Redux/ActionsReducers/InternalRedux';
import { OBSERVABLE_EXPRESSION_ROW_ADDED, OBSERVABLE_EXPRESSION_ROW_REMOVED, } from '../Utilities/Constants/GeneralConstants';
import * as ModuleConstants from '../Utilities/Constants/ModuleConstants';
import { ArrayExtensions } from '../Utilities/Extensions/ArrayExtensions';
import { getObjectTagsViewItems } from '../Utilities/getObjectTagsViewItems';
import { getRuleViewItems } from '../Utilities/getRuleViewItems';
import { getScopeViewItems } from '../Utilities/getScopeViewItems';
import { ActiveAlertsPanelItemLabel } from '../View/Alert/ActiveAlertsPanelItemLabel';
import { AlertEmptyView } from '../View/Alert/AlertEmptyView';
import { AlertStatusPanel } from '../View/Alert/AlertStatusSubPanel';
import { getAlertType } from '../View/Alert/Utilities/getAlertType';
import { AlertWizard } from '../View/Alert/Wizard/AlertWizard';
import { AdaptableModuleBase } from './AdaptableModuleBase';
import { getAlertBehaviourViewItems } from './Utilities/Alert/getAlertBehaviourViewItems';
import { getAlertPreviewViewItems } from './Utilities/Alert/getAlertPreviewViewItems';
import { getAlertTypeViewItems } from './Utilities/Alert/getAlertTypeViewItems';
export class AlertModule extends AdaptableModuleBase {
constructor(api) {
super(ModuleConstants.AlertModuleId, ModuleConstants.AlertModuleFriendlyName, 'alert', 'AlertPopup', 'Get notified when things happen in Adaptable that you need to know about', api);
this.isListeningToCellDataChanges = false;
}
onAdaptableReady() {
this.checkListenToCellDataChanged();
}
shouldListenToDataChanges() {
return ArrayExtensions.IsNotNullOrEmpty(this.api.alertApi.getActiveAlertDefinitions());
}
checkListenToCellDataChanged() {
if (!this.isListeningToCellDataChanges) {
if (this.shouldListenToDataChanges()) {
this.setupCellDataChangeListener();
this.isListeningToCellDataChanges = true;
}
}
}
setupCellDataChangeListener() {
this.api.internalApi
.getDataService()
.on('CellDataChanged', (cellDataChangedInfo) => {
let shouldIgnoreChange = false;
if (cellDataChangedInfo.trigger === 'undo') {
shouldIgnoreChange = true;
}
if (cellDataChangedInfo.trigger === 'aggChange') {
shouldIgnoreChange = !cellDataChangedInfo.column.isGeneratedPivotResultColumn;
}
if (shouldIgnoreChange) {
// do NOT handle reverted or aggregated changes
return;
}
if (this.api.optionsApi.getAlertOptions().dataChangeDetectionPolicy === 'formattedValue') {
const { oldValue, newValue, rowNode } = cellDataChangedInfo;
const columnId = cellDataChangedInfo.column.columnId;
const oldFormattedValue = this.api.gridApi.getDisplayValueFromRawValue(rowNode, columnId, oldValue);
const newFormattedValue = this.api.gridApi.getDisplayValueFromRawValue(rowNode, columnId, newValue);
if (oldFormattedValue === newFormattedValue) {
// if the formattedValues are identical, then no alert is fired
return;
}
}
this.handleCellDataChanged(cellDataChangedInfo);
});
this.api.internalApi
.getDataService()
.on('RowDataChanged', (rowDataChangedInfo) => {
if (rowDataChangedInfo.rowTrigger === 'Update') {
// changed row alerts should be handled by standard 'AnyChange' Predicate
return;
}
this.handleRowDataChanged(rowDataChangedInfo);
});
this.api.internalApi
.getAlertService()
.onReactiveAlertTriggered((reactiveAlertInfo) => this.handleReactiveAlertTriggered(reactiveAlertInfo));
this.api.alertApi.internalApi.setUpReactiveAlerts();
}
getModuleAdaptableObjects(config) {
return this.api.alertApi.getAlertDefinitions(config);
}
getExplicitlyReferencedColumnIds(alertDefinition) {
const queryExpression = this.api.expressionApi.getAdaptableQueryExpression(alertDefinition.Rule);
if (queryExpression) {
return this.api.expressionApi.getColumnsFromExpression(queryExpression);
}
else if (this.api.columnScopeApi.scopeHasColumns(alertDefinition.Scope)) {
return this.api.columnScopeApi
.getColumnsInScope(alertDefinition.Scope)
.map((adaptableColumn) => adaptableColumn.columnId);
}
return [];
}
getReferencedNamedQueryNames(alertDefinition) {
const queryExpression = this.api.expressionApi.getAdaptableQueryExpression(alertDefinition.Rule);
if (!queryExpression) {
return [];
}
return this.api.namedQueryApi.internalApi.getReferencedNamedQueryNames(queryExpression);
}
createContextMenuItems(menuContext) {
const items = [];
if (!menuContext.isRowGroupColumn && this.isModuleAvailable()) {
if (menuContext.adaptableColumn && menuContext.rowNode) {
let relevantAlert;
// find alerts which highlight the current cell
relevantAlert = this.api.alertApi.internalApi.getAdaptableAlertWithHighlightCell(menuContext.adaptableColumn.columnId, menuContext.rowNode);
if (!relevantAlert) {
// find alerts which highlight the current row
relevantAlert = this.api.alertApi.internalApi.getAdaptableAlertWithHighlightRow(menuContext.rowNode);
}
if (relevantAlert) {
items.push(this.createMenuItemReduxAction('alert-clear', 'Clear Alert', this.moduleInfo.Glyph, InternalRedux.AdaptableAlertDelete(relevantAlert)));
}
}
}
return items;
}
handleCellDataChanged(cellDataChangedInfo) {
const alertDefinitions = this.api.alertApi.internalApi.getAlertDefinitionsForCellDataChange(cellDataChangedInfo);
if (ArrayExtensions.IsNotNullOrEmpty(alertDefinitions)) {
this.api.alertApi.internalApi.showAlertForDefinitions(cellDataChangedInfo, alertDefinitions);
}
}
handleRowDataChanged(rowDataChangedInfo) {
const alertDefinitions = this.getAlertDefinitionsForRowDataChange(rowDataChangedInfo);
this.api.alertApi.internalApi.showAlertsForRowDataChanges(rowDataChangedInfo, alertDefinitions);
}
handleReactiveAlertTriggered(reactiveAlertInfo) {
// TODO - suppress Notification if alert is not relevant for layout
if (reactiveAlertInfo.type === 'cellDataChangedAlert') {
// the row node data is most probably stale because the reactive queries buffer the changed data
// so we have to refresh it
reactiveAlertInfo.cellChangeLogEntry.rowNode = this.api.gridApi.getRowNodeForPrimaryKey(reactiveAlertInfo.cellChangeLogEntry.primaryKeyValue);
reactiveAlertInfo.cellChangeLogEntry.rowData =
reactiveAlertInfo.cellChangeLogEntry.rowNode?.data;
this.api.alertApi.internalApi.showAlertForDefinitions(reactiveAlertInfo.cellChangeLogEntry, [
reactiveAlertInfo.alertDefinition,
]);
}
else {
// reactiveAlertInfo.type === rowDataChangedAlert'
this.api.alertApi.internalApi.showAlertForDefinitions(reactiveAlertInfo.gridChangeLogEntry, [
reactiveAlertInfo.alertDefinition,
]);
}
}
getAlertDefinitionsForRowDataChange(rowDataChangedInfo) {
return this.api.alertApi.internalApi
.getActiveNonReactiveAlertDefinitions()
.filter((alertDefinition) => this.api.alertApi.internalApi.isAlertDefinitionForRowChangeEvent(alertDefinition))
.filter((alertDefinition) => {
if (rowDataChangedInfo.rowTrigger === 'Add') {
return alertDefinition.Rule?.ObservableExpression.includes(OBSERVABLE_EXPRESSION_ROW_ADDED);
}
if (rowDataChangedInfo.rowTrigger === 'Delete') {
return alertDefinition.Rule?.ObservableExpression.includes(OBSERVABLE_EXPRESSION_ROW_REMOVED);
}
return false;
});
}
getTeamSharingAction() {
return {
ModuleEntities: this.api.alertApi.getAlertDefinitions(),
AddAction: AlertRedux.AlertDefinitionAdd,
EditAction: AlertRedux.AlertDefinitionEdit,
};
}
toViewCompact(alert) {
return {
item: {
name: alert.header,
label: ActiveAlertsPanelItemLabel,
values: [alert.message],
},
abObject: alert,
};
}
toView(alert) {
const alertType = getAlertType(alert);
return {
items: [
getAlertTypeViewItems(alert),
alertType === 'DataChange' && {
...getScopeViewItems(alert.Scope, this.api),
label: 'Trigger',
name: 'Trigger',
},
{ ...getRuleViewItems(alert.Rule, this.api), label: 'Rule', name: 'Rule' },
getAlertBehaviourViewItems(this.api),
getAlertPreviewViewItems(alert, this.api),
getObjectTagsViewItems(alert, this.api),
].filter(Boolean),
abObject: alert,
};
}
toViewAll() {
return this.getModuleAdaptableObjects({
includeLayoutNotAssociatedObjects: this.showLayoutNotAssociatedObjects(),
}).map((alert) => this.toView(alert));
}
getViewProperties() {
return {
getDeleteAction: AlertRedux.AlertDefinitionDelete,
getEditAction: AlertRedux.AlertDefinitionEdit,
getSuspendAction: AlertRedux.AlertDefinitionSuspend,
getUnSuspendAction: AlertRedux.AlertDefinitionUnSuspend,
getSuspendAllAction: AlertRedux.AlertDefinitionSuspendAll,
getUnSuspendAllAction: AlertRedux.AlertDefinitionUnSuspendAll,
getCompactDeleteAction: InternalRedux.AdaptableAlertDelete,
getDeleteAllAction: () => {
const alerts = this.api.internalApi.getState().Internal.AdaptableAlerts;
return InternalRedux.AdaptableAlertDeleteAll(alerts);
},
emptyView: AlertEmptyView,
getEditWizard: () => AlertWizard,
getStatusBarPanelProps: () => {
return {
popoverMinWidth: 360,
view: AlertStatusPanel,
};
},
};
}
canBeAssociatedWithLayouts() {
return true;
}
}