Home Reference Source

scripts/django_cradmin/components/CradminSelectedList.jsx

import React from "react";
import CradminSelectedListItem from "./CradminSelectedListItem";


export default class CradminSelectedList extends React.Component {

  static get defaultProps() {
    return {
      className: 'selectable-list selectable-list--inline selectable-list--nomargin',
      keyAttribute: 'id',
      signalNameSpace: null,
      uniqueId: '',
      itemComponentProps: {}
    }
  }

  constructor(props) {
    super(props);
    this._name = `django_cradmin.components.CradminSelectedList.${this.props.signalNameSpace}.${this.props.uniqueId}`;
    this.logger = new window.ievv_jsbase_core.LoggerSingleton().getLogger(
      'django_cradmin.components.CradminSelectedList');
    if(this.props.signalNameSpace == null) {
      throw new Error('The signalNameSpace prop is required.');
    }
    this._onSelectionChangeSignal = this._onSelectionChangeSignal.bind(this);
    this._onFocusOnDeSelectableItemSignal = this._onFocusOnDeSelectableItemSignal.bind(this);
    this._onFocusOnFirstSelectedItemSignal = this._onFocusOnFirstSelectedItemSignal.bind(this);
    this._onFocusOnLastSelectedItemSignal = this._onFocusOnLastSelectedItemSignal.bind(this);

    this._focusOnItemData = null;
    this.state = {
      selectedItemsMap: new Map()
    };

    this.initializeSignalHandlers();
  }

  initializeSignalHandlers() {
    new window.ievv_jsbase_core.SignalHandlerSingleton().addReceiver(
      `${this.props.signalNameSpace}.SelectionChange`,
      this._name,
      this._onSelectionChangeSignal
    );
    new window.ievv_jsbase_core.SignalHandlerSingleton().addReceiver(
      `${this.props.signalNameSpace}.FocusOnDeSelectableItem`,
      this._name,
      this._onFocusOnDeSelectableItemSignal
    );
    new window.ievv_jsbase_core.SignalHandlerSingleton().addReceiver(
      `${this.props.signalNameSpace}.FocusOnFirstSelectedItem`,
      this._name,
      this._onFocusOnFirstSelectedItemSignal
    );
    new window.ievv_jsbase_core.SignalHandlerSingleton().addReceiver(
      `${this.props.signalNameSpace}.FocusOnLastSelectedItem`,
      this._name,
      this._onFocusOnLastSelectedItemSignal
    );
  }

  componentWillUnmount() {
    new window.ievv_jsbase_core.SignalHandlerSingleton()
      .removeAllSignalsFromReceiver(this._name);
  }


  _onSelectionChangeSignal(receivedSignalInfo) {
    if(this.logger.isDebug) {
      this.logger.debug(receivedSignalInfo.toString(), receivedSignalInfo.data);
    }
    this.setState({
      selectedItemsMap: receivedSignalInfo.data.selectedItemsMap
    });
  }

  _onFocusOnDeSelectableItemSignal(receivedSignalInfo) {
    if(this.logger.isDebug) {
      this.logger.debug(receivedSignalInfo.toString(), receivedSignalInfo.data);
    }
    this._focusOnItemData = receivedSignalInfo.data;
  }

  _onFocusOnFirstSelectedItemSignal(receivedSignalInfo) {
    if(this.logger.isDebug) {
      this.logger.debug(receivedSignalInfo.toString(), receivedSignalInfo.data);
    }
    if(this.state.selectedItemsMap.size > 0) {
      const selectedItemsArray = Array.from(this.state.selectedItemsMap.values());
      this._focusOnItemData = selectedItemsArray[0];
    }
  }

  _onFocusOnLastSelectedItemSignal(receivedSignalInfo) {
    if(this.logger.isDebug) {
      this.logger.debug(receivedSignalInfo.toString(), receivedSignalInfo.data);
    }
    if(this.state.selectedItemsMap.size > 0) {
      const selectedItemsArray = Array.from(this.state.selectedItemsMap.values());
      this._focusOnItemData = selectedItemsArray[selectedItemsArray.length - 1];
    }
  }

  renderItem(itemKey, props) {
    return <CradminSelectedListItem key={itemKey} {...props} />;
  }

  renderItems() {
    const items = [];
    let itemKeys = Array.from(this.state.selectedItemsMap.keys());
    let previousItemData = null;
    for(let index=0; index < itemKeys.length; index++) {
      let itemKey = itemKeys[index];
      let itemData = this.state.selectedItemsMap.get(itemKey);

      let nextItemData = null;
      let isLast = index == (itemKeys.length - 1);
      if(!isLast) {
        nextItemData = this.state.selectedItemsMap.get(itemKeys[index + 1]);
      }

      let props = Object.assign({}, this.props.itemComponentProps, {
        data: itemData,
        itemKey: itemKey,
        signalNameSpace: this.props.signalNameSpace,
        previousItemData: previousItemData,
        nextItemData: nextItemData,
        uniqueListId: this.props.uniqueId
      });
      items.push(this.renderItem(itemKey, props));
      previousItemData = itemData;
    }
    return items;
  }

  render() {
    return <div className={this.props.className}>
      {this.renderItems()}
    </div>;
  }

  _sendFocusOnItemSignal(itemData) {
    const itemKey = itemData[this.props.keyAttribute];
    new window.ievv_jsbase_core.SignalHandlerSingleton().send(
      `${this.props.signalNameSpace}.FocusOnSelectedItem.${itemKey}`);
  }

  componentDidUpdate() {
    if(this._focusOnItemData != null) {
      this._sendFocusOnItemSignal(this._focusOnItemData);
      this._focusOnItemData = null;
    }
  }
}