UNPKG

@adaptabletools/adaptable

Version:

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

148 lines (147 loc) 6.05 kB
import * as InternalRedux from '../../Redux/ActionsReducers/InternalRedux'; import ArrayExtensions from '../Extensions/ArrayExtensions'; /** * This service controls the interaction between Notes & Comments * If there are active Notes or Comments it listens to Cell Selection and Mouse Enter events */ export class AnnotationsService { constructor(api) { this.api = api; this.isListeningToEvents = false; this.adaptable = api.internalApi.getAdaptableInstance(); this.adaptable.api.eventApi.on('AdaptableReady', () => this.checkListenToEvents()); } destroy() { } getAdaptableState() { return this.api.internalApi.getAdaptableState(); } dispatchAction(action) { this.api.internalApi.dispatchReduxAction(action); } static isSameAddress(a, b) { if (!a || !b) { return false; } if (a?.ColumnId === b?.ColumnId && a?.PrimaryKeyValue === b?.PrimaryKeyValue) { return true; } // Primary keys retreived from the grid dom are always strings, so we must also consider them strings if ((typeof a.PrimaryKeyValue === 'number' && typeof b.PrimaryKeyValue === 'string') || (typeof b.PrimaryKeyValue === 'string' && typeof a.PrimaryKeyValue === 'number')) { return (a.PrimaryKeyValue.toString() === b.PrimaryKeyValue.toString() && a.ColumnId === b.ColumnId); } return false; } checkListenToEvents() { if (!this.isListeningToEvents && this.shouldListenToEvents()) { this.setUpEventListeners(); this.isListeningToEvents = true; } } shouldListenToEvents() { // Listen to events if we either have Notes in state or if Comments have been set up return (ArrayExtensions.IsNotNullOrEmpty(this.api.noteApi.getAllNotes()) || this.api.internalApi.getModuleService().isModuleAvailable('Comment')); } setUpEventListeners() { this.adaptable._on('MouseEnter', (event) => this.handleMouseEnter(event)); this.api.eventApi.on('CellSelectionChanged', (params) => { const cells = params.selectedCellInfo.gridCells; if (ArrayExtensions.hasOneItem(cells)) { const selectedCell = cells[0]; if (selectedCell.column?.columnId && selectedCell.primaryKeyValue) { const selectedCellAddress = { PrimaryKeyValue: selectedCell.primaryKeyValue, ColumnId: selectedCell.column.columnId, }; this.handleCellSelected(selectedCellAddress); } } }); } getCellPositionFromEvent(event) { const target = event.target; if (!target?.classList?.contains?.('ag-cell')) { return null; } try { const PrimaryKeyValue = target.parentElement.getAttribute('row-id'); return { PrimaryKeyValue, ColumnId: target.getAttribute('col-id'), }; } catch (e) { return null; } } handleMouseEnter(event) { const editMode = this.getEditMode(); if (editMode) { // ignore return; } const cellPosition = this.getCellPositionFromEvent(event); const openCellAddress = this.getOpenCellAddress(); // Hovering over something that is not a cell and there is no open note if (!cellPosition && openCellAddress) { // need to close if the new cell does not have a note this.hidePopup(); return; } // call only if cell address is different if (AnnotationsService.isSameAddress(openCellAddress, cellPosition)) { return; } const cellNote = this.api.noteApi.getNoteForCell(cellPosition); const cellComments = this.api.commentApi.getCommentThreadForCell(cellPosition); if (!cellNote && !cellComments) { return; } this.showPopup(cellPosition, false); } handleCellSelected(cellAddress) { // if already opened - do nothing const openCellAddress = this.getOpenCellAddress(); if (AnnotationsService.isSameAddress(openCellAddress, cellAddress)) { return; } // if open but this has no note, close const cellNote = this.api.noteApi.getNoteForCell(cellAddress); const cellComments = this.api.commentApi.getCommentThreadForCell(cellAddress); const hasNotesOrComments = cellNote || cellComments; if (openCellAddress && !hasNotesOrComments) { // hide only if in edit mode // because if you select a cell and move the mouse fast over another cell // with a note, you do not want to close that note // the selection is debounced, so the moment goes over the new cell this event is triggered if (this.getEditMode()) { this.hidePopup(); } return; } // if open but the new selection has a note open that one in edit mode (because of click) if (openCellAddress && hasNotesOrComments) { this.showPopup(cellAddress, true); return; } } getOpenCellAddress() { return InternalRedux.CommentsAndNotesSelector(this.getAdaptableState().Internal); } getEditMode() { return InternalRedux.CommentsAndNotesEditModeSelector(this.getAdaptableState().Internal); } hidePopup() { this.dispatchAction(InternalRedux.CellPopupHide()); } showPopup(cellAddress, editMode) { this.dispatchAction(InternalRedux.CellPopupShow(cellAddress, editMode)); } editFocusedEntity(entity) { this.dispatchAction(InternalRedux.CellPopupEditFocusedEntity(entity)); } getNotePopupEditMode() { return InternalRedux.CommentsAndNotesEditModeSelector(this.getAdaptableState().Internal); } }