Jump to content

Developing on Cloud Hosted Version


LMX

Recommended Posts

Hello to whomever may stumble upon this! 

I work for a small organization that doesn't have the capacity to support a self hosted solution but still needed to extend upon the base functionality of the website. This means I don't have access to the developer console - as a result I have been experimenting over the last month or so with development on the cloud hosted version. While not ideal I have been able to accomplish some features that have been useful for us.  If you are in a similar situation I hope this can be useful for you as well and perhaps save you some time.

If you read this and think there are better ways to achieve these means I would be very happy to learn them. Please do share any ideas you may have if you care to do so!

Here is an example of a Community Map we built via PHP & HTML custom blocks.

PHP Block for getting member data - template key = "php_template_key"

Standard API request as outlined in the docs with the addition of setting the returned data in the global $_SESSION variable to make it accessible from the front end HTML block. (thanks to @bfarber for that idea!).

$communityUrl = 'BASE_URL_HERE';
$apiKey = 'API_KEY_HERE';
$endpoint = '/core/members?perPage=700';
$curl = curl_init( $communityUrl . 'api' . $endpoint );
curl_setopt_array( $curl, array(
  CURLOPT_RETURNTRANSFER	=> TRUE,
  CURLOPT_HTTPAUTH	=> CURLAUTH_BASIC,
  CURLOPT_USERPWD		=> "{$apiKey}:",
  CURLOPT_USERAGENT		=> "MyUserAgent/1.0"
));
$response = curl_exec( $curl );

$_SESSION['apiResponseVariable'] = json_encode($response,JSON_HEX_APOS|JSON_HEX_QUOT);

Since I only need member name, a custom field and their location I could (and probably should) groom the data here on the BE before passing to the front end. 

 

HTML Block for rendering map

This requires you to enable Google Maps Third-party Enhancement at 'YOUR-DOMAIN/admin/?app=core&module=applications&controller=enhancements'.

Some useful docs for working with the Google Maps API:
https://developers.google.com/maps/documentation/javascript/adding-a-google-map

https://developers.google.com/maps/documentation/javascript/marker-clustering

{block="php_template_key"}
{{$response = $_SESSION['apiResponseVariable'];}}
<html>
  <head>
    <title>Community Map</title>
    <script src="https://unpkg.com/@google/markerclustererplus@4.0.1/dist/markerclustererplus.min.js"></script>
    <script
      src="https://maps.googleapis.com/maps/api/js?key=API_KEY&callback=initMap&libraries=&v=weekly"
      defer
    ></script>
    <style type="text/css">
      #map {
        height: 400px;
        width: 100%;
      }
      .welcome-text {
        padding-bottom: 20px;
      }
      .welcome-text span {
        font-size: 16px;
      }
    </style>
    <script>
function initMap() {
  let mapStyleOptions = [
    {
      featureType: "water",
      elementType: "geometry",
      stylers: [
        { color: "#d0d3d4" }
      ]
    },
    {
      featureType: "landscape",
      elementType: "geometry",
      stylers: [
        { color: "#dee2e3" }
      ],
    },
    {
      featureType: "road",
      elementType: "geometry",
      stylers: [
        { visibility: "off" }
      ],
  }];

  const myMap = new google.maps.Map(document.getElementById("map"), {
    zoom: 2.5,
    center: {lat:24.63940428579627, lng:-50.6783944937192},
  	styles: mapStyleOptions,
  });
  
  /* This is the messy bit of conforming the $apiResponseVariable to usable json */
  
  let data = '{json_decode($response, TRUE)}';
  data = data.replace('{json_decode("', '');
  data = data.replace('", TRUE)}', '');
  data = JSON.parse(data);

  let locations = [];
  let markers = [];
  let infowindow = new google.maps.InfoWindow();
  
  data.results.forEach(member => {
    let memberLoc = JSON.parse(member.customFields[1].fields[2].value);
    if(memberLoc.lat !== null && memberLoc.long !== null) {
      let organization = member.customFields[1].fields[3].value;
      let memberName = member.formattedName;
      let memberUrl = member.profileUrl;
      let displayName = memberName;
      
      if (memberName != organization && organization != '') {
        displayName = memberName + ' - ' + organization;
      }
      
      locations.push({
        id: memberLoc.lat.toString() + memberLoc.long.toString(),
        name: displayName,
        profileUrl: member.profileUrl,
        lat: memberLoc.lat,
        lng: memberLoc.long
      });
    };
  });

  const uniqueLocations = Array.from(new Set(locations.map(a => a.id)))
  .map(id => {
    return locations.find(a => a.id === id)
  });

  for (i = 0; i < uniqueLocations.length; i++) {
    marker = new google.maps.Marker({
      position: new google.maps.LatLng(uniqueLocations[i].lat, uniqueLocations[i].lng),
      icon: {
        url: "some-custom-image-url",
      },
    });

    markers.push(marker);

    google.maps.event.addListener(marker, 'click', (function(marker, i) {
      return function() {
        let UrlElement = '<a href="' + uniqueLocations[i].profileUrl + '">' + uniqueLocations[i].name + '</a>';
        infowindow.setContent(UrlElement);
        infowindow.open(myMap, marker);
      }
    })(marker, i));
  }
  
  let clusterImagePath = 'some-custom-image-url'
 
  new MarkerClusterer(myMap, markers, {
      imagePath: clusterImagePath,
      height: '100px',
      width: '100px',
  });
}
    </script>
  </head>
  <body>
    	<div class="welcome-text"><h2>Welcome to the community map!</h2><span>Use our Community Map below to find and interact with other members.</span></div>
    	<!--The div element for the map -->
    	<div id="map"></div>
  </body>
</html>


I've used this pattern of BE API request and FE PHTML/JS jumble to achieve a fair amount of custom tooling so far (in the absence of access to the developer console). Hope this is useful to someone out there.  Happy to answer any questions or receive feedback.

Peace love and chicken grease.

 

Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...