aws-samples/wild-rydes-mobile

Name: wild-rydes-mobile

Owner: AWS Samples

Description: Learn serverless mobile cloud computing with this fictional unicorn ride-sharing app.

Created: 2018-04-03 17:12:58.0

Updated: 2018-05-09 06:53:13.0

Pushed: 2018-05-10 04:58:46.0

Homepage: null

Size: 191268

Language: CSS

GitHub Committers

UserMost Recent Commit# Commits

Other Committers

UserEmailMost Recent Commit# Commits

README

Wild Rydes Mobile

Welcome to the Wild Rydes Mobile project. In this project, we will take you through the steps necessary to build a complete website with analytics, authentication, email list sign-up and booking of a ride.

Getting Started

To continue with this course, you must first have the AWS Mobile CLI installed and configured:

  1. Install the CLI
i -g awsmobile-cli
  1. Configure the CLI
obile configure
Lesson 1: Web Hosting

The design team has dropped the final version of the web site, but has not set up web hosting. In this lesson, we will quickly set up a scalable web site with global reach and deploy the code to the web site.

Clone the project & change into the directory:

clone https://github.com/aws-samples/wild-rydes-mobile
ild-rydes-mobile

Install the dependencies using npm or yarn:



install

Create the new Mobile Hub project

obile init

For the questions:

The AWS Mobile Hub project will be created.

To run the projecte locally:

Run the project locally using either npm or yarn:

 start

start

To build the website in the cloud:

Use the following to build and publish the project to the cloud:

obile publish

A browser will open pointing to the newly created site once publication completes.

Lesson 2: Email Campaign

Before using any AWS Amplify modules, we first need to configure Amplify to use the AWS Mobile configuration stored in src/aws-exports.js.

Edit the src/index.js file & add the following lines to the top of the file (below all the other imports) to configure Amplify:

rt Amplify from 'aws-amplify';
rt awsConfig from './aws-exports';

ify.configure(awsConfig);

One of the features on the home page is an email sign-up page. In this lesson, you will link the email sign-up to Amazon Pinpoint, then use the Amazon Pinpoint user segmentation and campaigns features to send an email to all the registered users.

Edit the src/components/EmailSignUp.js file. Add the following lines to the top of the file:

rt uuid from 'uuid';
rt { Auth } from 'aws-amplify';
rt * as Pinpoint from 'aws-sdk/clients/pinpoint';
rt awsConfig from '../aws-exports';

Then look for /* TODO: HANDLE FORM INPUT */ - this is where we need to add code to submit the email address into the Amazon Pinpoint analytics platform. Replace the onEmailSubmitted() method that is there now with the following:

ync onEmailSubmitted(event) {
event.preventDefault();

// Create a Pinpoint connection
const credentials = await Auth.currentCredentials();
const pinpointClient = new Pinpoint({
  region: awsConfig.aws_mobile_analytics_app_region,
  credentials: Auth.essentialCredentials(credentials)
});
if (!this.endpointId)
  this.endpointId = uuid.v4();

// Create an endpoint definition
const params = {
  ApplicationId: awsConfig.aws_mobile_analytics_app_id,
  EndpointId: this.endpointId,
  EndpointRequest: {
    Address: this.state.email,
    ChannelType: 'EMAIL',
    EffectiveDate: new Date().toISOString(),
    OptOut: 'NONE',
    RequestId: uuid.v4(),
    User: {
      UserAttributes: {
        email: [ this.state.email ],
        emailsignup: [ 'true' ]
      },
      UserId: this.state.email
    }
  }
};

// Update the endpoint definition
pinpointClient.updateEndpoint(params, (err, data) => {
  if (err) {
    alert('Email Signup Failed');
    console.error('updateEndpoint: ', err);
  } else {
    this.setState({ email: '', emailsubmitted: true });
  }
});
/* END OF PINPOINT CHANGES */

Change the function to “async” by adding async in the front of onEmailSubmitted(event)

Publish the code with awsmobile publish. Once the app has been published, enter your email address within the email sign-up form and click Submit.

Configure the Email Channel
Create a User Segment
Create an Email Campaign

Check your email for your test message!

Lesson 3: Authentication

Sign up, sign in, and forgot password screens have been provided, but need to be wired up to the main application. First, create an Amazon Cognito user pool:

obile user-signin enable
obile push

This will update the backend without publishing updated code. Now, update the src/auth/SignUp.js file to do the sign-up process:

ync onSubmitForm(e) {
e.preventDefault();
try {
  const params = {
    username: this.state.email.replace(/[@.]/g, '|'),
    password: this.state.password,
    attributes: {
      email: this.state.email,
      phone_number: this.state.phone
    },
    validationData: []
  };
  const data = await Auth.signUp(params);
  console.log(data);
  this.setState({ stage: 1 });
} catch (err) {
  alert(err.message);
  console.error("Exception from Auth.signUp: ", err);
  this.setState({ stage: 0, email: '', password: '', confirm: '' });
}


ync onSubmitVerification(e) {
e.preventDefault();
try {
  const data = await Auth.confirmSignUp(
    this.state.email.replace(/[@.]/g, '|'),
    this.state.code
  );
  console.log(data);
  // Go to the sign in page
  this.props.history.replace('/signin');
} catch (err) {
  alert(err.message);
  console.error("Exception from Auth.confirmSignUp: ", err);
  this.setState({ stage: 0, email: '', password: '', confirm: '', code: '' });
}

Update the src/auth/SignIn.js file to do the sign-in process:

ync onSubmitForm(e) {
e.preventDefault();
try {
    const userObject = await Auth.signIn(
        this.state.email.replace(/[@.]/g, '|'),
        this.state.password
    );
    console.log('userObject = ', userObject);
    this.setState({ userObject, stage: 1 });
} catch (err) {
    alert(err.message);
    console.error('Auth.signIn(): ', err);
}


ync onSubmitVerification(e) {
e.preventDefault();
try {
    const data = await Auth.confirmSignIn(
        this.state.userObject,
        this.state.code
    );
    console.log('data = ', data);
    this.setState({ stage: 0, email: '', password: '', code: '' });
    this.props.history.replace('/app');
} catch (err) {
    alert(err.message);
    console.error('Auth.confirmSignIn(): ', err);
}

Finally, take a look at the route configuration in src/index.js. We need to update so that the current authentication is read from local storage, then adjust the routing based on authentication.

t isAuthenticated = () => Amplify.Auth.user !== null;

Run the following to publish the new site:

obile publish -c -n -f

This will ensure CloudFront is also flushed. If in doubt, go to the S3 bucket instead. You should now be able to click on the Giddy Up! button and get a sign-up / sign-in button. When signed-in, you should see the temporary Ride page.

Lesson 4: Analytics

Now that we have authentication enabled in the app, let's add an analytics event that will track the use case of a user attempting to sign up but instead receiving an error.

We want to know what types of errors are being thrown when our users are attempting to sign up to better understand the signup flow.

To do this, let's create an Analytics event that will get called in the event of an error.

We'll do this in the catch error block of the onSubmitForm method in src/auth/SignUp.js.

rc/auth/SignUp.js

c onSubmitForm(e) {
 previous code here omitted
catch (err) {
alert(err.message);
Analytics.record('Signup Error', err.message) // New
console.error("Exception from Auth.signUp: ", err);
this.setState({ stage: 0, email: '', password: '', confirm: '' });


Lesson 5: Create a Serverless Backend

First, create a DynamoDB table. This can only be done on the console (creating a database on the command line also creates a CRUD API which is not desired in this instance):

Next, create the Cloud Logic API. This can be done from the command line:

obile pull
obile cloud-api enable --prompt

When asked sync corresponding contents in backend/ with #current-backend-info? choose y

The awsmobile pull command will pull the current definition from the AWS Mobile Hub service. This will include the definition of the DynamoDB table. You can then continue by changing the current definition with the second awsmobile command.

Select Create a new API. This will prompt you for some information:

Once complete, copy ./server/requestUnicorn.js to ./awsmobilejs/backend/cloud-api/requestUnicorn/app.js. This is the code that will be run in the serverless backend in response to the API request.

Run awsmobile push to publish the backend changes to AWS.

Next, edit the hasApi method and uncomment the code:

pi() {
nst api = awsConfig.aws_cloud_logic_custom.filter(v => v.name === 'requestUnicorn');
turn (typeof api !== 'undefined');

Finally, edit the ./src/pages/MainApp.js page. Adjust the getData() method to read as follows:

ync getData(pin) {
const body = {
  PickupLocation: {
    Longitude: pin.longitude,
    Latitude: pin.latitude
  }
};
return await API.post(apiName, apiPath, { body });

Publish the application using awsmobile publish. Run the application (either locally or from the cloud), log in. Click somewhere on the map to set the pickup location, then click Request to request the ride.


This work is supported by the National Institutes of Health's National Center for Advancing Translational Sciences, Grant Number U24TR002306. This work is solely the responsibility of the creators and does not necessarily represent the official views of the National Institutes of Health.