Beyond the template

Learn how to create the custom components with ease. We demonstrate how to wire-in Google Maps (or Apple Maps) into MaximoPlus.

In this tutorial, we will create the component that adapts the existing React Native MapView component to display the locations of the work orders. I assume you don't have the Maximo Spatial installed, so we will put the geo-coordinates in a location description field, to illustrate the point.

The Component Adapter is a MaximoPlus tool we use to create the component. For example:

import {getComponentAdapter} from "mplus-react";

const TestComponent = getComponentAdapter(WrappedComponent);

WrappedComponent is a component that has the following properties, along with the properties passed to the TestComponent:

  • maxrows - data fetched into Component Adapter
  • fetchMore - function to get more data into ComponentAdapter
  • setMaxRowValue - function to change the Maximo data for a given row and column.
  • moveToRow - a function to change the current row of an MboSet

We use the above to bring the Maximo functionality to the component we adapt.

The resulting component, in our case TestComponent, has the following mandatory properties:

  • container - The id of the container
  • columns - The array of required columns
  • norows - Initial number of rows in the component

Let's clarify it with an example.

First, we will create the Map component that displays the markers, and reacts when we tap on it.

import React, { useState, useEffect } from "react";
import MapView, { Marker } from "react-native-maps";
import getInitialCoordinates from "../utils/map.js";
import { StyleSheet } from "react-native";

const style = StyleSheet.create({
  map: {
    ...StyleSheet.absoluteFillObject
  }
});
export default props => {
  const [region, setRegion] = useState(null);

  const asInitCoords = async props => {
    const coords = await getInitialCoordinates(props.coordinates);
    if (!region) {
      setRegion(coords);
    }
  };

  useEffect(() => {
    asInitCoords(props);
  });

  return (
    <MapView style={style.map} region={region}>
      {props.coordinates.map(marker => (
        <Marker
          key={marker.key}
          coordinate={{
            latitude: marker.latitude,
            longitude: marker.longitude
          }}
          title={marker.title}
          onPress={ev => props.handlePress(marker)}
        />
      ))}
    </MapView>
  );
};

We will not show the getInitialCoordinates function here for the sake of simplicity. The code above is almost the same as the official demo for the MapView . Check it out if in doubt.

With this  in hand, let us create the MaximoPlus component. As already discussed, we  use the DESCRIPTION field in the work order location to put the latitude and longitude.  The format is ##latitude,longitude##:

const regex = /##(.*),(.*)##/;
const WOMap = getComponentAdapter(props => {
  if (!props || !props.maxrows) return null;
  const { navigate } = useNavigation();
  const coords = props
    .filter(({ data }) => {
      const locDesc = data["LOCATION.DESCRIPTION"]; //required field for this to work
      return regex.test(locDesc);
    })
    .map(({ data, mxrow }) => {
      const locDesc = data["LOCATION.DESCRIPTION"];
      const [, latitude, longitude] = regex.exec(locDesc).map(parseFloat);
      return {
        latitude,
        longitude,
        key: data.key,
        title: data["DESCRIPTION"],
        rowNum: mxrow
      };
    });
  return (
    <View>
      <CoordsMap
        coordinates={coords}
        handlePress={({ rowNum }) => {
          props.moveToRow(rowNum);
          navigate("WOSection");
        }}
      />
    </View>
  );
});

The component extracts the list of coordinates from the work orders in the list that have it and pass it to the CoordsMap component that we created in the previous step. If the user taps on the map marker, it will navigate him to the section page, and change the current Maximo row.

Our component is ready to be used. Let us create the dialog:

const WOMapDialog = props => (
  <View
    style={{
      flex: 1,
      flexDirection: "column",
      justifyContent: "flex-end"
    }}
  >
    <WOMap
      columns={["wonum", "description", "location.description"]}
      container="wotrack"
      norows={50}
    />
  </View>
);

WOMapDialog.navigationOptions = ({ navigation }) => {
  const backButton = (
    <HeaderActionButtons
      buttons={[{ key: "close", label: "Back", action: closeDialog }]}
      icons={{ close: "md-arrow-back" }}
      style={{ color: "white" }}
    />
  );
  return {
    headerTitle: (
      <Text style={{ color: "white", fontSize: 18 }}>Workorder Mape</Text>
    ),
    headerTransparent: true,
    headerLeft: backButton,
    headerStyle: { borderBottomWidth: 0 }
  };
};

export default WOMapDialog;

And that's it! As an exercise, create the button on the section screen that opens this dialog, as described in  Calling Maximo Actions from MaximoPlus.