Initial node additions
rodzic
d5236c8ec3
commit
1a6fb2fe7b
|
@ -0,0 +1,162 @@
|
|||
# Places
|
||||
|
||||
**Places** is a web application written in [ReactJS](https://reactjs.org) and [NodeJS](https://nodejs.org) that, backed by the power of the [MariaDB Node Connector](https://github.com/MariaDB/mariadb-connector-nodejs) and [MariaDB platform](https://mariadb.com/products/mariadb-platform/), allows you to record all of your favorite locations!
|
||||
|
||||
<p align="center">
|
||||
<img src="media/map.png" />
|
||||
</p>
|
||||
|
||||
This `README` will walk you through the steps for getting this app up and running (locally) within minutes!
|
||||
|
||||
# Table of Contents
|
||||
1. [Overview](#overview)
|
||||
1. [Introduction to MariaDB](#intro-mariadb)
|
||||
2. [Using JSON in a relational database](#json-relational)
|
||||
2. [Requirements](#requirements)
|
||||
3. [Getting started](#getting-started)
|
||||
1. [Grab the code](#grab-code)
|
||||
2. [Build the code](#build-code)
|
||||
3. [Run the app](#run-app)
|
||||
4. [Support and Contribution](#support-contribution)
|
||||
|
||||
## Overview <a name="overview"></a>
|
||||
|
||||
### Introduction to MariaDB <a name="intro-mariadb"></a>
|
||||
|
||||
[MariaDB platform](https://mariadb.com/products/mariadb-platform/) unifies [MariaDB TX (transactions)](https://mariadb.com/products/mariadb-platform-transactional/) and [MariaDB AX (analytics)](https://mariadb.com/products/mariadb-platform-analytical/) so transactional applications can retain unlimited historical data and leverage powerful, real-time analytics in order to provide data-driven customers with more information, actionable insight and greater value – and businesses with endless ways to monetize data. It is the enterprise open source database for hybrid transactional/analytical processing at scale.
|
||||
|
||||
<p align="center">
|
||||
<img src="media/platform.png" />
|
||||
</p>
|
||||
|
||||
### Using JSON in a relational database <a name="json-relational"></a>
|
||||
|
||||
[JSON](https://www.json.org) is fast becoming the standard format for data interchange and for unstructured data, and MariaDB Platform (in fact, all MariaDB versions 10.2 and later) include a range of [JSON supporting functions](https://mariadb.com/topic/json/).
|
||||
|
||||
The Places application uses only a **single table** for all location, and uses JSON to store more specific information based on the location type.
|
||||
|
||||
```sql
|
||||
CREATE TABLE `Locations` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) NOT NULL DEFAULT '',
|
||||
`description` varchar(500) DEFAULT '',
|
||||
`type` char(1) NOT NULL DEFAULT '',
|
||||
`latitude` decimal(9,6) NOT NULL,
|
||||
`longitude` decimal(9,6) NOT NULL,
|
||||
`attr` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`attr`)),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
For more information on how JSON can be used within MariaDB please check out this [blog post](https://mariadb.com/resources/blog/json-with-mariadb-10-2/)!
|
||||
|
||||
|
||||
## Requirements <a name="requirements"></a>
|
||||
|
||||
This project assumes you have familiarity with building web applications using ReactJS and NodeJS technologies.
|
||||
|
||||
* Download and install [MariaDB](https://go.mariadb.com/download-mariadb-server-community.html?utm_source=google&utm_medium=ppc&utm_campaign=MKG-Search-Google-Branded-DL-NA-Server-DL&gclid=CjwKCAiAwZTuBRAYEiwAcr67OUBIqnFBo9rUBhYql3VZV_nhlSKzkwoUv7vhA6gwNdGoBSc2uWe7SBoCX_oQAvD_BwE).
|
||||
* Download and install [NodeJS](https://nodejs.org/).
|
||||
* git (Optional) - this is required if you would prefer to pull the source code from GitHub repo.
|
||||
- Create a [free github account](https://github.com/) if you don’t already have one
|
||||
- git can be downloaded from git-scm.org
|
||||
|
||||
## Getting started <a name="getting-started"></a>
|
||||
|
||||
In order to run the Places application you will need to have a MariaDB instance to connect to. For more information please check out "[Get Started with MariaDB](https://mariadb.com/get-started-with-mariadb/)".
|
||||
|
||||
In order to build and run the Places applications you will need to have NodeJS installed. You can find more information [here](https://nodejs.org/).
|
||||
|
||||
### Create the schema <a name="create-schema"></a>
|
||||
|
||||
Using CLI or SQL client run the following SQL command:
|
||||
|
||||
```sql
|
||||
CREATE TABLE `Locations` (
|
||||
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
|
||||
`name` varchar(100) NOT NULL DEFAULT '',
|
||||
`description` varchar(500) DEFAULT '',
|
||||
`type` char(1) NOT NULL DEFAULT '',
|
||||
`latitude` decimal(9,6) NOT NULL,
|
||||
`longitude` decimal(9,6) NOT NULL,
|
||||
`attr` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT NULL CHECK (json_valid(`attr`)),
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=InnoDB AUTO_INCREMENT=19 DEFAULT CHARSET=utf8mb4;
|
||||
```
|
||||
|
||||
### Grab the code <a name="grab-code"></a>
|
||||
|
||||
Download this code directly or use [git](git-scm.org) (through CLI or a client) to retrieve the code.
|
||||
|
||||
### Configure the code <a name="configure-code"></a>
|
||||
|
||||
**The gist;** Add a Google Maps API Key and database connection information to the code.
|
||||
|
||||
1. Once you've obtained a Google Maps API Key place add it to the code [here](src/client/src/components/MapContainer.js#245).
|
||||
|
||||
```js
|
||||
export default GoogleApiWrapper({
|
||||
apiKey: ("reallllllylongkeyhere")
|
||||
})(MapContainer)
|
||||
```
|
||||
|
||||
2. Update the MariaDB connection configuration here.
|
||||
|
||||
```js
|
||||
const pool = mariadb.createPool({
|
||||
host: 'localhost',
|
||||
user:'root',
|
||||
password: 'sosafemuchsecure',
|
||||
database: 'Places',
|
||||
multipleStatements: true,
|
||||
connectionLimit: 5
|
||||
});
|
||||
```
|
||||
|
||||
### Build the code <a name="build-code"></a>
|
||||
|
||||
Now that you have a copy of the code you're ready to build and run the project. However, before running the code it's important to point out that the application uses several Node Packages.
|
||||
|
||||
For the client-side:
|
||||
- [google-maps-react](https://www.npmjs.com/package/google-map-react)
|
||||
- [props-type](https://www.npmjs.com/package/props-type)
|
||||
- [react](https://www.npmjs.com/package/react)
|
||||
- [react-datepicker](https://www.npmjs.com/package/react-datepicker)
|
||||
- [react-dom](https://www.npmjs.com/package/react-dom)
|
||||
- [react-modal](https://www.npmjs.com/package/react-modal)
|
||||
- [react-scripts](https://www.npmjs.com/package/react-scripts)
|
||||
|
||||
For the server-side:
|
||||
- [body-parser](https://www.npmjs.com/package/body-parser)
|
||||
- [concurrently](https://www.npmjs.com/package/concurrently)
|
||||
- [express](https://www.npmjs.com/package/express)
|
||||
- [mariadb](https://www.npmjs.com/package/mariadb) (the best database in world)
|
||||
|
||||
|
||||
### Run the app <a name="run-app"></a>
|
||||
|
||||
Once you've pulled down the code and have verified that all of the required Node packages are installed you're ready to run the application! It's as easy as 1,2,3.
|
||||
|
||||
1. Using a command line interface (CLI) navigate to where to the `src` directory of Places.
|
||||
|
||||
<p align="center">
|
||||
<img src="media/cli_root.png" />
|
||||
</p>
|
||||
|
||||
2. Run the command:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
<p align="center">
|
||||
<img src="media/npm_start.png" />
|
||||
</p>
|
||||
|
||||
3. Open a browser window and navigate to http://localhost:3000.
|
||||
|
||||
## Support and Contribution <a name="support-contribution"></a>
|
||||
|
||||
Thanks so much for taking a look at the Places app! As this is a very simple example,there's a lot of potential for customization!
|
||||
|
||||
If you have any questions, comments, or would like to contribute to this or future projects like this please reach out to us directly at developers@mariadb.com or on [Twitter](https://twitter.com/mariadb).
|
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 125 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 443 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 432 KiB |
Plik binarny nie jest wyświetlany.
Po Szerokość: | Wysokość: | Rozmiar: 233 KiB |
|
@ -0,0 +1,61 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
|
@ -0,0 +1,23 @@
|
|||
var mariadb = require('mariadb');
|
||||
|
||||
// Local Connection
|
||||
const pool = mariadb.createPool({
|
||||
host: 'localhost',
|
||||
user:'root',
|
||||
password: 'password',
|
||||
database: 'Places',
|
||||
multipleStatements: true,
|
||||
connectionLimit: 5
|
||||
});
|
||||
|
||||
module.exports={
|
||||
getConnection: function(){
|
||||
return new Promise(function(resolve,reject){
|
||||
pool.getConnection().then(function(connection){
|
||||
resolve(connection);
|
||||
}).catch(function(error){
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
Plik diff jest za duży
Load Diff
|
@ -0,0 +1,19 @@
|
|||
{
|
||||
"name": "places",
|
||||
"version": "1.0.0",
|
||||
"description": "",
|
||||
"main": "server.js",
|
||||
"scripts": {
|
||||
"start": "concurrently \"npm run server\" \"npm run client\"",
|
||||
"server": "node server.js",
|
||||
"client": "npm start --prefix client"
|
||||
},
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"concurrently": "^5.0.0",
|
||||
"express": "^4.17.1",
|
||||
"mariadb": "^2.1.2"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
"use strict";
|
||||
|
||||
let express = require("express"),
|
||||
router = express.Router(),
|
||||
pool = require('../db');
|
||||
|
||||
// GET all locations
|
||||
router.get("/", async (req, res, next) => {
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "select id, name, type, longitude, latitude, " +
|
||||
"case when type = 'R' then concat((case when json_length(attr, '$.favorites') " +
|
||||
"is not null then json_length(attr, '$.favorites') else 0 end), ' favorite meals') " +
|
||||
"when type = 'A' then (case when json_value(attr, '$.lastVisitDate') is not null " +
|
||||
"then json_value(attr, '$.lastVisitDate') else 'N/A' end) " +
|
||||
"when type = 'S' then concat((case when json_length(attr, '$.events') is not null " +
|
||||
"then json_length(attr, '$.events') else 0 end), ' events') end as description " +
|
||||
"from Locations";
|
||||
var rows = await conn.query(query);
|
||||
res.send(rows);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// POST new location
|
||||
router.post("/", async (req, res, next) => {
|
||||
let location = req.body;
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "insert into Locations (name, description, type, latitude, longitude, attr) values (?, ?, ?, ?, ?, json_compact(?))";
|
||||
var result = await conn.query(query, [location.name, location.description, location.type, location.latitude, location.longitude, JSON.stringify(location.attr)]);
|
||||
res.send(result);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// GET restaurant by id
|
||||
router.get("/restaurant", async (req, res, next) => {
|
||||
let conn;
|
||||
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var id = req.query.id;
|
||||
var query = "select " +
|
||||
"name, " +
|
||||
"json_value(attr,'$.details.foodType') as foodType, " +
|
||||
"json_value(attr,'$.details.menu') as menu, " +
|
||||
"json_query(attr,'$.favorites') as favorites " +
|
||||
"from Locations " +
|
||||
"where id = ?";
|
||||
var rows = await conn.query(query, [id]);
|
||||
res.send(rows[0]);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// POST new restaurant favorite
|
||||
router.post("/restaurant/favorites", async (req, res, next) => {
|
||||
let favorite = req.body;
|
||||
let details = favorite.details;
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "update Locations set attr = json_array_append(attr, '$.favorites', json_compact(?)) where id = ?"
|
||||
var result = await conn.query(query, [JSON.stringify(details), favorite.locationid]);
|
||||
res.send(result);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// GET sports venue by id
|
||||
router.get("/sportsvenue", async (req, res, next) => {
|
||||
let conn;
|
||||
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var id = req.query.id;
|
||||
var query = "select " +
|
||||
"name, " +
|
||||
"json_value(attr,'$.details.yearOpened') as yearOpened, " +
|
||||
"json_value(attr,'$.details.capacity') as capacity, " +
|
||||
"json_query(attr,'$.events') as events " +
|
||||
"from Locations " +
|
||||
"where id = ?";
|
||||
var rows = await conn.query(query, [id]);
|
||||
res.send(rows[0]);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// POST new sports venue event
|
||||
router.post("/sportsvenue/event", async (req, res, next) => {
|
||||
let event = req.body;
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "update Locations set attr = json_array_append(attr, '$.events', json_compact(?)) where id = ?";
|
||||
var result = await conn.query(query, [JSON.stringify(event.details), event.locationid]);
|
||||
res.send(result);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
// PUT last visited an attraction
|
||||
router.put("/attractions", async (req, res, next) => {
|
||||
let locationId = req.query.id;
|
||||
let lastVisitDate = req.query.dt;
|
||||
let conn;
|
||||
try {
|
||||
conn = await pool.getConnection();
|
||||
var query = "update Locations set attr = json_set(attr,'$.lastVisitDate', ?) where id = ?";
|
||||
var result = await conn.query(query, [lastVisitDate, locationId]);
|
||||
res.send(result);
|
||||
} catch (err) {
|
||||
throw err;
|
||||
} finally {
|
||||
if (conn) return conn.release();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = router;
|
|
@ -0,0 +1,28 @@
|
|||
const express = require('express');
|
||||
const app = express();
|
||||
const port = 8080;
|
||||
const path = require('path');
|
||||
const bodyParser = require("body-parser");
|
||||
|
||||
const locationRoutes = require("./routes/locationRoutes");
|
||||
|
||||
app.use(bodyParser.json());
|
||||
app.use(bodyParser.urlencoded({ extended: false }));
|
||||
|
||||
if (process.env.NODE_ENV === 'production') {
|
||||
app.use(express.static('client/build'));
|
||||
}
|
||||
|
||||
app.use("/api/locations", locationRoutes);
|
||||
|
||||
app.get("/*", (req, res) => {
|
||||
res.sendFile(path.join(__dirname, "/client/build/index.html"));
|
||||
});
|
||||
|
||||
app.use((err, req, res, next) => {
|
||||
res.status(422).send({ error: err._message });
|
||||
});
|
||||
|
||||
// console.log that your server is up and running
|
||||
app.listen(port, () => console.log(`Listening on port ${port}`));
|
||||
|
Ładowanie…
Reference in New Issue