import { FiltersMap, KeyedItem, QueryState, syncWithSharedQuery, TaskState, } from '@wix/bex-core'; import { action, computed, makeObservable, observable, runInAction, } from 'mobx'; import { NestedCollectionState } from './NestedCollectionState'; import { NestedCollectionLevelDescriptor } from './NestedCollectionLevelDescriptor'; import { NodeCollection } from './types'; import { createNestedOptimisticActions } from './createNestedOptimisticActions'; export interface NestedCollectionNodeStateBaseParams { readonly levelDescriptor: NestedCollectionLevelDescriptor; readonly notifyAll?: boolean; } export interface NestedCollectionNodeStateParams extends NestedCollectionNodeStateBaseParams { readonly nestedCollection: NestedCollectionState; readonly parentNode: NestedCollectionNodeState | null; readonly parent: KeyedItem | null; readonly nodeCollection?: NodeCollection; } export class NestedCollectionNodeState { readonly nestedCollection; readonly collection; readonly levelDescriptor: NestedCollectionLevelDescriptor; readonly parent; readonly parentNode; readonly parentFilter; readonly parentKeyToChildrenMap = observable.map< string, NestedCollectionNodeState >([], { deep: false, }); _expanded = false; _hovered = false; _notifyAll; readonly initTask = new TaskState(); constructor(params: NestedCollectionNodeStateParams) { const { nestedCollection } = params; this.nestedCollection = nestedCollection; this.levelDescriptor = params.levelDescriptor; this.parent = params.parent; this.parentNode = params.parentNode; this._notifyAll = params.notifyAll; runInAction(() => { this._expanded = !nestedCollection.isFetchAllAborted && nestedCollection.expandAll; }); const nestedOptimisticActionsState = { parentId: this.parent?.id ?? 'null', sequences: nestedCollection.sequences, query: nestedCollection.query as QueryState, levelDescriptor: this.levelDescriptor, }; const { collection, parentFilter } = params.nodeCollection ?? this.levelDescriptor.createCollection(nestedOptimisticActionsState); createNestedOptimisticActions(this.nestedCollection.container, collection, { ...nestedOptimisticActionsState, parentFilter, }); if (!nestedCollection.isFetchAllAborted) { collection.queryObserver.setOptions({ ...collection.queryObserver.options, staleTime: Infinity, }); } this.collection = collection; this.parentFilter = parentFilter; const { parent, nestedCollection: { query: sharedQuery }, } = this; const { query } = collection; syncWithSharedQuery(query, sharedQuery); if (parent != null && parentFilter != null) { parentFilter.persistent = true; parentFilter.setValue([parent.key]); } makeObservable(this, { init: action, _toggleExpand: action, _changeHover: action, _expanded: observable.ref, _hovered: observable.ref, hoveredOrParentHovered: computed, }); } async _toggleExpand() { this._expanded = !this._expanded; if (this._expanded) { try { await this.collection.initialFetch(); } catch (e) { console.error(e); } } } get hoveredOrParentHovered(): boolean { return this._hovered || !!this.parentNode?.hoveredOrParentHovered; } _changeHover(hovered: boolean) { this._hovered = hovered; } init({ skipCollectionInit }: { skipCollectionInit?: boolean } = {}) { const { initTask, collection, nestedCollection } = this; if (collection._optimisticActions) { nestedCollection.events.on( 'dispose', collection._optimisticActions.init(), ); } const disposers = [ !skipCollectionInit ? collection.init({ skipInitialFetch: nestedCollection.isFetchAllAborted === true && !this._expanded, skipFilterListeners: true, }) : undefined, ]; initTask.runOnce(async () => { collection.initTask.runOnce(); await collection.initTask.status.promise; }); return () => { disposers.forEach((d) => d?.()); }; } _createNode( parent: KeyedItem, params: NestedCollectionNodeStateBaseParams, ) { const { nestedCollection } = this; return new NestedCollectionNodeState({ parent, parentNode: this, nestedCollection, levelDescriptor: params.levelDescriptor, notifyAll: params.notifyAll, }); } }