import { WixPatternsContainer, ConditionalModalState, FiltersMap, TypedEmitter, withoutDefaults, CloseSidePanel, } from '@wix/bex-core'; import { action, computed, makeObservable, observable, reaction } from 'mobx'; import { CollectionDragEndEvent } from './DragAndDrop'; import { EventEmitter } from 'events'; import { cairoApplyButtonClicked, cairoDiscardChangesBeforeApply, cairoLearnMore, } from '@wix/bex-core/bi'; import { ToolbarCollectionState } from '../../state'; export class ReorderModeState { readonly discardChangesModal = new ConditionalModalState(); readonly feature = 'Drag and Drop'; readonly origin = 'Table Toolbar'; toolbar: ToolbarCollectionState; container: WixPatternsContainer; _isReorderModeSubmitted = false; pendingPromise: Promise | null = null; closeSidePanel?: CloseSidePanel; readonly events = new EventEmitter() as TypedEmitter<{ submitSuccess: () => void; submitError: (error: unknown) => void; }>; constructor(params: { toolbar: ToolbarCollectionState; container: WixPatternsContainer; closeSidePanel?: CloseSidePanel; }) { this.toolbar = params.toolbar; this.container = params.container; this.closeSidePanel = params.closeSidePanel; makeObservable(this, { isReorderModeToolbarVisible: computed, isReorderModePending: computed, _isReorderModeSubmitted: observable.ref, _setIsReorderModeSubmitted: action, }); this.init(); } init() { const disposers = [ reaction( () => this.moves.length, async () => { if (this.moves.length === 0) { this.pendingPromise = null; this._setIsReorderModeSubmitted(false); } else { this.closeSidePanel?.(); } }, ), ]; return () => { disposers.forEach((disposer) => disposer?.()); }; } get optimisticActions() { return this.toolbar.collection._optimisticActions; } get patches() { return this.optimisticActions?.state.patches ?? []; } get dnd() { return this.toolbar._dnd!; } get moves(): CollectionDragEndEvent[] { const { toolbar: { _dnd }, } = this; if (_dnd == null) { return []; } return ( this.patches .filter((patch) => patch.move !== undefined && !patch.isStale) .map(({ move }) => _dnd._createSimpleDragEndEvent(move!)) ?? [] ); } get isReorderModeToolbarVisible() { return this.moves.length > 0 && !this._isReorderModeSubmitted; } get isReorderModePending() { return this.moves.length > 0 && this.pendingPromise !== null; } get snapshot(): T[][] { return this.optimisticActions?.collection.result.pages ?? []; } get onSubmit() { if (this.pendingPromise) { return this.pendingPromise; } const { events } = this; return (this.pendingPromise = new Promise((resolve, reject) => { events.once('submitSuccess', resolve); events.once('submitError', reject); })); } _showSuccessToast() { this.container.showToast?.({ type: 'SUCCESS', message: this.container.translate( 'cairo.dragAndDrop.reorderMode.toast.success', ), biName: 'reorder-mode-submit-success', }); } _reportApplyButtonClickedBiEvent() { this.dnd.reportBi( withoutDefaults(cairoApplyButtonClicked)({ numOfActions: this.moves.length, feature: this.feature, origin: this.origin, }), ); } _reportDiscardChangesBeforeApplyBiEvent() { this.dnd.reportBi( withoutDefaults(cairoDiscardChangesBeforeApply)({ numOfActions: this.moves.length, feature: this.feature, origin: this.origin, }), ); } reportLearnMoreClickedBiEvent() { this.dnd.reportBi( withoutDefaults(cairoLearnMore)({ origin: this.origin, }), ); } async onBulkCancel() { this.discardChangesModal.open(null); const { result } = await this.discardChangesModal.modal.promise(); if (result === 'confirmed') { this._reportDiscardChangesBeforeApplyBiEvent(); this.events.emit( 'submitError', new Error(this.optimisticActions?.reorderModeCanceledMessage), ); } } async onBulkSubmit() { this._reportApplyButtonClickedBiEvent(); try { this._setIsReorderModeSubmitted(true); await this.dnd.onBulkSubmit?.(this.moves, this.snapshot); this._showSuccessToast(); this.events.emit('submitSuccess'); } catch (error) { this.events.emit('submitError', error); this.pendingPromise = null; } } _setIsReorderModeSubmitted(submitted: boolean) { this._isReorderModeSubmitted = submitted; } }