/Zero-Waste-Locator

MEAN (MongoDB, Express, Angular CLI 7.0.6, Node) app using Google Maps to show shops selling Zero Waste products

Primary LanguageTypeScript

Zero Waste Locator

What this App is about

I try to live a Zero Waste lifestyle. In brief, Zero Waste for me is about reducing consumption, in particular plastic products. I relocated to Norway, I realized it takes time to find out where plastic-free products are sold.

For this reason I am implementing this app where users can search and log stores selling Zero Waste or Less Waste products. This app uses Google Maps to search for stores, and will allow you to save them together with their products so that you or other users can look them up.

Technical description

This is a MEAN app (MongoDB, Express, Angular CLI 7.0.6, Node.js) using the Google Maps API to show store locations on an embedded Google map.

On the back-end a server is based on Node.js/Express server. The Mongoose ODM is used to connect Node.js and the MongoDB database. It provides a schema based solution to organize models and run CRUD operations. JSON web tokens [JWT] handle user authentication and identity management. The front-end is built with Angular-CLI 7, Bootstrap, and Angular Bootstrap. The app uses RxJS for asynchronous or callback-based code.

Through the frontend users can search an address using Google Maps' geolocation. The results are displayed as markers on the Google map.
I implemented a "caching" system that checks whether the searched address is already present in the MongoDB database [DB]. This allows the app to call Google Maps less often, and to load a store/location already present in the DB.

The user has a personal quota for the number of geolocation searches they can run. The quota can be set in three environment variables (see below) as an integer for the maximum number of queries per hour, day, and total maximum. This was done to limit my bill with the Google Maps API.

A form appears when you click on a marker. This form contains user editable information on the store such as the store type, store description, etc. This form allows the user to save or update the store/location to the DB.

To use the Google Map functionality a user is required to register and login. JWT is used to transmit sensitive information (e.g. passwords, access tokens) between front-end and back-end. A password reset functionality is implemented in the back-end using express-nodemailer, handlebars for express and express-nodemailer, and AJAX requests.

NB: This app does not use agm-core for Google Maps as described in many tutorials. IMO at the time of writing the documentation is insufficient to extend the agm-core component and implement functionalities such as InfoWindow or callbacks from markers.

Installation

node, npm, mongoDB, Angular

Install node, npm, mongoDB, Angular CLI, and see the standard generated README below. Install the Angular and Node.js dependencies with:

cd backend
npm run client-install

This script uses concurrently to run npm install on both back- and front-end folders.

For deploying the front end check the Build section below and the Angular deployment documentation

dotenv

Create a .env file with environment variables for the Node.js back-end. Use a template in .env_example.

cp .env_example .env
vi .env

environment*.ts

Similarly to dotenv, set up environment variables for the Angular frontend in the ./environment.ts and ./environment.prod.ts files, which are used for development and production, respectively.

Google Maps

Get a Google Maps API key here to use Google's geolocation service. Place the API key in the ./src/index_INSERTKEY.html file, then rename that file to index.html. This allows you to use it for geocoding from the front end (see src/app/modules/map/map.component.ts).

The code still includes my implementation of geocoding from the server back-end. This implementation uses npm-geocoder but I commented it out in the code. To use it set up a Google Maps API key for using it on a server and see the backend/server.js file.

Launching the app

Launch the MongoDB database:

mongod --dbpath <path to data directory>

Launch the Node.js back-end in the ./backend directory. As an example, use one of these three commands below:

cd backend
npm start       //using npm
node server.js  //using node
nodemon         //using nodemon

Before launching Angular fix the index.html file as explained before:

cp ./src/index_INSERTKEY.html ./src/index.html

Launch Angular for the frontend with one of these two commands:

ng serve
npm run start

Alternatively, use this command to automate the previous two commands on the back- and front-end:

cd backend
npm run dev

Open your browser at http://localhost:4200/. The backend API is by default at http://localhost:4000/, and you can for instance check the http://localhost:4000/ or http://localhost:4000/ endpoints.

Prepare for production

In addition to the previous steps compile the Angular app into the /dist folder:

ng build --prod

The /dist folder is served by Node.js when the environment variable NODE_ENV is set to 'production', so do that before launching the backend with e.g.:

NODE_ENV=production node server.js

How it looks like

Alt Text

Some references

Here are some references I am using to develop MEAN applications:

Building a MEAN Application

MEAN App tutorial with Angular 4

Google Maps API

Integrating Google Maps in Angular 6

Display and Track User's current location using Google Map Geolocation in Angular 5

Post on stackoverflow about Google Maps' infowindow

Create a MEAN Stack Google Map App

How To Implement Password Reset In Node.js

Generated README

This project was generated with Angular CLI version 7.0.3.

Development server

Run ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.

Code scaffolding

Run ng generate component component-name to generate a new component. You can also use ng generate directive|pipe|service|class|guard|interface|enum|module.

Build

Run ng build to build the project. The build artifacts will be stored in the dist/ directory. Use the --prod flag for a production build.

Running unit tests

Run ng test to execute the unit tests via Karma.

Running end-to-end tests

Run ng e2e to execute the end-to-end tests via Protractor.

Further help

To get more help on the Angular CLI use ng help or go check out the Angular CLI README.