Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
ui-component-library / src / components / atoms / Map / __unused / LocationContainer.tsx
Size: Mime:
import React from 'react'
import ReactDOMServer from 'react-dom/server'
import { isNil } from 'exotic'
import { extendObservable } from 'xmobx/mobx'
import { MapMarkerIcon } from 'atoms/Icons/MapMarkerIcon'
import { toPlaceholder } from 'atoms/Image/deps/toPlaceholder'
import { toggleBounce } from './deps'
import fromStoreToInfoString from './fromStoreToInfoString'

/**
 * @alias MapLocationContainer
 * @api https://developers.google.com/maps/documentation/javascript/events#MarkerEvents
 * @api https://developers.google.com/maps/documentation/javascript/examples/event-simple
 * @api https://developers.google.com/maps/documentation/javascript/examples/marker-simple
 */

const locationIconString = toPlaceholder(<MapMarkerIcon />)

class Store {
  infowindow: Object
  static types = {
    index: 0,
    /**
     * @alias isActive
     * @todo - pretty sure this is used when we click
     *         may need to configure navigatable store
     */
    isFocused: false,
    // apidata / state
    apiState: {},
    // dangerous to make this observable lest we recursively & circularily convert observable things
    // parent: {
    //   // store locator set in .from
    // },
    marker: {
      // position
      // map
      // title
      // position: {lat: 59.327, lng: 18.067}
    },
  }
  constructor() {
    extendObservable(this, Store.types)
    // THIS IS THE WRONG PLACE TO CALL THIS (ugh)
    // this.createMarker()
  }
  /**
   * @access private
   * @readonly
   *
   * @desc get latlng for google
   * @todo I swear I coded this already, must be in ToggleGeolocator
   */
  latlng() {
    return {
      // this is really not safe
      lat: +this.apiState.latitude,
      lng: +this.apiState.longitude,
    }
  }
  get googleMap() {
    return window.googleMapNode
  }

  /**
   * @api https://developers.google.com/maps/documentation/javascript/examples/infowindow-simple-max
   * @description creates the popup on the marker
   *
   * @param {GoogleMaps} [map=undefined] unused
   */
  createInfoWindow = (map = undefined) => {
    /**
     * if we didn't pass in a map reference, default to this dom
     * @todo can  also load with document.getElementById
     */
    // if (isNil(map)) {
    //   map = window.googleMapNode
    // }

    /**
     * @description fallback string if  rendering to string happens to ever error
     */
    let contentString = `<article><h1>${this.apiState.name}</h1><small>had an error rendering</small></article>`

    try {
      contentString = fromStoreToInfoString(this.apiState, this.index)
      // window.storestring = contentString
    } catch (toStringException) {
      console.error(toStringException)
    }

    /**
     * @description store it on the instance, then, call it on the click subscriber in the marker
     */
    this.infowindow = new google.maps.InfoWindow({
      content: contentString,
      maxWidth: 260,
    })

    return this.infowindow
  }
  /**
   * @todo split into  1 2 3
   *
   * @type {Action}
   * @modifies this.marker
   * @see this.animateMarker, this.subscribeToCallParentAction
   *
   * @param {HTMLElement} markerStore (map) google map rendered into dom
   * @param {number} index
   */
  createMarker = (markerStore, index) => {
    if (typeof window !== 'object') {
      return
    }
    /** The info pop-up is not rendered
    *creating the marker,and then it needs to create it again, because the google apis load
    */
    /* if (this.marker) {
      return
    }*/

    /**
     * if we fail to pass in data, default to the  api  data which i s in the container
     */
    if (isNil(markerStore)) {
      markerStore = this.apiState
    }

    this.createInfoWindow()

    // console.log('Create Marker state: ', index)
    // add a marker for each store
    const latlng = new google.maps.LatLng(markerStore.latitude, markerStore.longitude)
    // let latlng = new google.maps.LatLng('59.327', '18.067')
    // this.latlngGoogle = latlng

    this.marker = new google.maps.Marker({
      // animation: google.maps.Animation.DROP,
      // {lat: 59.327, lng: 18.067}
      // position: this.latlng(),
      position: latlng,
      title: markerStore.name,
      zIndex: index,

      // custom property to maintain multiple infowindows
      markerIndex: index,

      /**
       * @invalid @todo @api - not in the api, wrong
       */
      // infowindow: this.createInfoWindow,
      icon: { url: locationIconString },
      label: {
        text: (this.index + 1).toString(),
        color: '#FFFFFF',
        fontSize: '10px',
        fontWeight: 'bold',
      },
      map: window.googleMapNode,
    })

    console.dev('Marker Position: ', this.marker.getPosition())

    this.animateMarker()

    // debug
    // if (typeof window === 'object') {
    //   window.mapmarkers = this
    // }

    console.dev('Store_createMarker', this)
  }

  /**
   * @type {action}
   * @event google.maps.marker.onClick
   * @desc add animation
   *
   * @param {GoogleMapDom} [map]
   * @param {GoogleMaps Marker} [marker]
   * @return {void}
   */
  animateMarker = (map, marker) => {
    const googleMap = map || this.googleMap
    const mapMarker = marker || this.marker

    const openInfoWindow = () => {
      console.dev('MARKER EVENT CALLED', {
        self: this,
        googleMap,
        mapMarker,
      })

      /**
       * @todo - needs to UNfocus the others
       */
      const hideStore = store => {
        // or add .close method
        store.isFocused = false
        store.infowindow.close(googleMap, store.marker)
      }

      this.parent.storeList.forEach(hideStore)
      this.isFocused = true

      // this.infowindow.open(map, marker)
      this.infowindow.open(googleMap, mapMarker)
    }

    this.openInfoWindow = openInfoWindow
    this.marker.addListener('click', this.openInfoWindow)
  }

  /**
   * @description calls createMarker & animateMarker
   */
  // createAnimatedMarker() { }

  /**
   * @type {Factory}
   * @description  easy to use in  .map without a new function
   *
   * @param {StoreLocator} storeLocator top level
   * @param {Object} apiState / state api data in a state tree <--<<<<<<<<<<<<<<<<< @type {LocationContainer}
   * @param {Number} index in array
   * @return {Store} built store
   */
  static from = (storeLocator, apiState, index) => {
    const store = new Store()
    // spread out initial state
    Object.assign(store, apiState)

    // set props
    store.apiState = apiState
    store.index = index

    // reference main container for dependency injection
    store.parent = storeLocator

    // what goes into here again where do we get the .long .lat...
    // => LocationContainer ?
    store.createMarker(apiState)

    return store
  }
}

export { Store }
export { Store as MapLocationContainer }
export default Store