Mutate to use preferred operators while routing

Operators are different. Think about payment methods, locations, charger experience. To take care of this, operators can be ranked and excluded. Either in the dashboard or in the API. In this example, the API approach will be demonstrated.

View on Github

Requirements

Steps to take

  1. Plotting a route with preferred operators starts by executing the newRoute mutation. This mutation requires information about the car, origin and destination. To use preferred operators the operators argument needs to be configured. The type needs to be set as well as the ranking or excluding. After the mutation is finished executing a route id will be returned.
  2. This id can be used to request route updates through the routeUpdatedById subscription. This subscription receives dynamic updates.
  3. After the subscription returns done as status, a route with preferred operators will be returned. If there are no operator preferred stations available it will fallback on stations from other operators. If all stations on a segment are excluded a route can fail to compute. The polyline and legs object can be used to display the route and charge stations on the map. Additional data such as distance, duration and consumption are also available.

Next steps

To take routes a step further, elevation plots and dynamic variables will be introduced. Let's head over to that.

  • client.js
  • index.js
  • interface.js
  • map.js
  • queries.js
  • 01
  • 02
  • 03
  • 04
  • 05
  • 06
  • 07
  • 08
  • 09
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
          import { createClient, createRequest, defaultExchanges, subscriptionExchange } from '@urql/core';import { pipe, subscribe } from 'wonka';import { SubscriptionClient } from 'subscriptions-transport-ws';import { searchOperatorListQuery, createRouteQuery, routeUpdateSubscription } from './queries.js'; /** * For the purpose of this example we use urql - lightweights GraphQL client. * To establish a connection with Chargetrip GraphQL API you need to have an API key. * The key in this example is a public one and gives an access only to a part of our extensive database. * You need a registered `x-client-id` to access the full database. * Read more about an authorisation in our documentation (https://docs.chargetrip.com/#authorisation). */const headers = {  //Replace this x-client-id and app-id with your own to get access to more cars  'x-client-id': '5ed1175bad06853b3aa1e492',  'x-app-id': '623998b2c35130073829b2d2',}; const subscriptionClient = new SubscriptionClient('wss://api.chargetrip.io/graphql', {  reconnect: true,  connectionParams: headers,}); const client = createClient({  url: 'https://api.chargetrip.io/graphql',  fetchOptions: {    method: 'POST',    headers,  },  exchanges: [    ...defaultExchanges,    subscriptionExchange({      forwardSubscription(operation) {        return subscriptionClient.request(operation);      },    }),  ],}); /** * Searches through our operator list with pagination and various arguments. * @param { Object } - Object that manages the page, size and search to be send towards our request * @param { number } page - Number of the page we are on * @param { number } size - Number of operators that we should fetch in one request * @param { string } search - The keywords that we should filter our operator list on * @param { function } callback - As soon as our asynchronous call is finished we do a callback to update our UI. */export const fetchOperatorList = ({ page, size = 10, search = '', countries = [] }, callback) => {  client    .query(searchOperatorListQuery, { page, size, search, countries })    .toPromise()    .then(response => {      callback(response.data.operatorList);    });};/** * Creates a route based on operator preference * @param { Object } - Object that manages the operator preference * @param { string } type - The type of operator preference. Can be either none, preferred or required. * @param { string } [level1] - The first level of operator preference. The higher the more preferred an operator is. * @param { string } [level2] - The second level of operator preference. * @param { string } [level3] - The third level of operator preference. * @param { string } [excluded] - The excluded level of operator preference. These operators won't be used when calculating the route. */export const createRoute = ({ type = 'none', level1 = [], level2 = [], level3 = [], exclude = [] }, callback) => {  client    .mutation(createRouteQuery, { type, level1, level2, level3, exclude })    .toPromise()    .then(response => {      const routeId = response.data.newRoute;      if (!routeId) return Promise.reject('Could not retrieve Route ID. The response is not valid.');       const { unsubscribe } = pipe(        client.executeSubscription(createRequest(routeUpdateSubscription, { id: routeId })),        subscribe(result => {          const { status, route } = result.data.routeUpdatedById;           if (status === 'done' && route) {            unsubscribe();            callback(route);          } else if (status === 'not_found') {            callback();          }        }),      );    })    .catch(error => console.log(error));};