"dependencies": {
"@sap/cds": "^3.10.0",
"express": "^4.17.1",
"@sap/xssec": "^2.1.17",
"@sap/xsenv": "^2.0.0",
"hdb": "^0.17.0",
"@sap/hdbext": "^6.0.0",
"@sap/hana-client": "^2.4.139",
"@sap/textbundle": "latest",
"@sap/logging": "^5.0.1",
"@sap/audit-logging": "^3.0.0",
"nodemailer": "^6.2.1",
"passport": "~0.4.0",
"async": "^3.0.1",
"ws": "^7.0.0",
"accept-language-parser": "latest",
"node-xlsx": "^0.15.0",
"node-zip": "~1.1.1",
"xmldoc": "~1.1.2",
"winston": "^3.2.1",
"body-parser": "^1.19.0",
"elementtree": "latest",
"then-request": "latest",
"compression": "~1.7",
"helmet": "^3.18.0",
"request": "^2.81.0",
"csvtojson": "^2.0.10",
"geojson": "^0.5.0"
}
/*eslint no-console: 0, no-unused-vars: 0, no-undef:0, no-process-exit:0*/
/*eslint-env node, es6 */
"use strict";
const port = process.env.PORT || 3000;
const server = require("http").createServer();
const cds = require("@sap/cds");
//Initialize Express App for XSA UAA and HDBEXT Middleware
const xsenv = require("@sap/xsenv");
const passport = require("passport");
const xssec = require("@sap/xssec");
const xsHDBConn = require("@sap/hdbext");
const express = require("express");
global.__base = __dirname + "/";
//logging
var logging = require("@sap/logging");
var appContext = logging.createAppContext();
//Initialize Express App for XS UAA and HDBEXT Middleware
var app = express();
//Compression
app.use(require("compression")({
threshold: "1b"
}));
//Helmet for Security Policy Headers
const helmet = require("helmet");
// ...
app.use(helmet());
app.use(helmet.contentSecurityPolicy({
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "sapui5.hana.ondemand.com"],
scriptSrc: ["'self'", "sapui5.hana.ondemand.com"]
}
}));
// Sets "Referrer-Policy: no-referrer".
app.use(helmet.referrerPolicy({ policy: "no-referrer" }));
app.use(logging.middleware({
appContext: appContext,
logNetwork: true
}));
var http = require("http");
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "REPLACE_WITH_YOUR_SAP_ANALYTICS_CLOUD_DOMAIN); // update to match the domain you will make the request from
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
next();
});
app.get("/node", (req, res) => {
res.send("OK");
});
//Setup Additonal Node.js Routes
require("./router")(app, server);
//Start the Server
server.on("request", app);
server.listen(port, function () {
console.info(`HTTP Server: ${server.address().port}`);
});
/*eslint-env node, es6 */
"use strict";
module.exports = (app, server) => {
app.use("/node", require("./routes/myNode")());
};
/*eslint no-console: 0, no-unused-vars: 0, no-shadow: 0, newcap:0*/
/*eslint-env node, es6 */
"use strict";
const express = require("express");
const async = require("async");
const https = require('https');
const csv = require('csvtojson')
const GeoJSON = require('geojson')
function formatDate(d) {
//get the month
var month = d.getMonth();
//get the day
//convert day to string
var day = d.getDate().toString() - 1;
//get the year
var year = d.getFullYear();
//pull the last two digits of the year
year = year.toString().substr(-2);
//increment month by 1 since it is 0 indexed
//converts month to a string
month = (month + 1).toString();
//if month is 1-9 pad right with a 0 for two digits
if (month.length === 1) {
month = month;
}
//if day is between 1-9 pad right with a 0 for two digits
if (day.length === 1) {
day = day;
}
//return the string "MMddyy"
return month + '/' + day + '/' + year;
}
function readHeader() {
return new Promise(resolve => {
const result = [];
https.get(
'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv',
(resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
csv({
noheader: false,
output: "json"
})
.fromString(data)
.then((csvRow) => {
const result = [];
var d = new Date();
var date = formatDate(d);
console.log(date);
for (var i = 0; i < csvRow.length; i++) {
result.push({
'Province/State': csvRow[i]['Province/State'],
'Country/Region': csvRow[i]['Country/Region'],
'Lat': csvRow[i]['Lat'],
'Long': csvRow[i]['Long']
})
}
resolve(result);
})
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
});
}
function readConfirmed() {
return new Promise(resolve => {
const result = [];
https.get(
'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Confirmed.csv',
(resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
csv({
noheader: false,
output: "json"
})
.fromString(data)
.then((csvRow) => {
const result = [];
var d = new Date();
var date = formatDate(d);
console.log(date);
for (var i = 0; i < csvRow.length; i++) {
result.push(csvRow[i][date]);
}
resolve(result);
})
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
});
}
function readDeath() {
return new Promise(resolve => {
const result = [];
https.get(
'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Deaths.csv',
(resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
csv({
noheader: false,
output: "json"
})
.fromString(data)
.then((csvRow) => {
const result = [];
var d = new Date();
var date = formatDate(d);
console.log(date);
for (var i = 0; i < csvRow.length; i++) {
result.push(csvRow[i][date]);
}
resolve(result);
})
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
});
}
function readRecovered() {
return new Promise(resolve => {
const result = [];
https.get(
'https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_covid_19_time_series/time_series_19-covid-Recovered.csv',
(resp) => {
let data = '';
// A chunk of data has been recieved.
resp.on('data', (chunk) => {
data += chunk;
});
// The whole response has been received. Print out the result.
resp.on('end', () => {
csv({
noheader: false,
output: "json"
})
.fromString(data)
.then((csvRow) => {
const result = [];
var d = new Date();
var date = formatDate(d);
console.log(date);
for (var i = 0; i < csvRow.length; i++) {
result.push(csvRow[i][date]);
}
resolve(result);
})
});
}).on("error", (err) => {
console.log("Error: " + err.message);
});
});
}
module.exports = function () {
var app = express.Router();
var userScope = null;
app.get("/getSessionInfo", (req, res) => {
async function msg() {
const header_msg = await readHeader();
const confirmed_msg = await readConfirmed();
const death_msg = await readDeath();
const recovered_msg = await readRecovered();
const result = [];
for (var i = 0; i < header_msg.length; i++) {
result.push({
'Province/State': header_msg[i]['Province/State'],
'Country/Region': header_msg[i]['Country/Region'],
'Lat': parseFloat(header_msg[i]['Lat']),
'Long': parseFloat(header_msg[i]['Long']),
'Recovered': parseFloat(recovered_msg[i]),
'Confirmed': parseFloat(confirmed_msg[i]),
'Death': parseFloat(death_msg[i])
})
}
var geojson = GeoJSON.parse(result, {
Point: ['Lat', 'Long']
});
res.type("application/json").status(200).send(JSON.stringify(geojson));
}
msg();
});
return app;
};
{
"welcomeFile": "index.html",
"authenticationMethod": "none",
"routes": [{
"source": "/node(.*)",
"destination": "srv_api",
"csrfProtection": true,
"authenticationType": "none"
}]
}
ID: covid19
_schema-version: "2.1"
version: 0.0.1
modules:
- name: covid19-srv
type: nodejs
path: srv
parameters:
memory: 512M
disk-quota: 256M
provides:
- name: srv_api
properties:
url: '${default-url}'
requires:
- name: zcovid-uaa
- name: covid19-web
type: html5
path: web
requires:
- name: zcovid-uaa
- name: srv_api
group: destinations
properties:
name: srv_api
url: '~{url}'
forwardAuthToken: true
resources:
- name: zcovid-uaa
type: com.sap.xs.uaa-space
parameters:
config-path: ./xs-security.json
{
"xsappname": "zcovid19",
"scopes": [{
"name": "$XSAPPNAME.Display",
"description": "display"
}, {
"name": "$XSAPPNAME.Create",
"description": "create"
}, {
"name": "$XSAPPNAME.Edit",
"description": "edit"
}, {
"name": "$XSAPPNAME.Delete",
"description": "delete"
}, {
"name": "$XSAPPNAME.DataGenerator",
"description": "data generator"
}, {
"name": "xs_authorization.read",
"description": "Read authorization information from UAA"
}, {
"name": "xs_authorization.write",
"description": "Write authorization information to UAA"
}, {
"name": "$XSAPPNAME.ODATASERVICEUSER",
"description": "Enter"
}, {
"name": "$XSAPPNAME.ODATASERVICEADMIN",
"description": "Enter"
}],
"attributes": [{
"name": "client",
"description": "Session Client",
"valueType": "int"
}, {
"name": "country",
"description": "country",
"valueType": "s"
}],
"role-templates": [{
"name": "Viewer",
"description": "View all records",
"scope-references": [
"$XSAPPNAME.Display"
],
"attribute-references": [
"client", "country"
]
}, {
"name": "Editor",
"description": "Edit and Delete records",
"scope-references": [
"$XSAPPNAME.Create",
"$XSAPPNAME.Edit",
"$XSAPPNAME.Delete",
"$XSAPPNAME.Display",
"$XSAPPNAME.DataGenerator",
"$XSAPPNAME.ODATASERVICEUSER",
"$XSAPPNAME.ODATASERVICEADMIN"
],
"attribute-references": [
"client"
]
}]
}
<!doctype html>
<html lang="en-us">
<head>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>COVID-19</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.3/dist/leaflet.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
<style>
body {
font-family: sans-serif;
margin: 0px;
border: 0px;
padding: 0px;
}
.container {
top: 0;
left: 0;
right: 0;
bottom: 0;
position: absolute;
}
.header {
position: absolute;
top: -8px;
left: 0px;
padding-left: 50px;
right: 0;
padding: 10px;
z-index: 1000;
background-color: rgba(255,255,255,0.75);
}
h2 {
margin: 10px 0;
margin-left: 50px;
}
h3 {
margin: 0;
}
#map {
height: 100%;
width: 100%;
}
#property-list, #playback {
display: inline-block;
}
.view {
display: inline-block;
font-size: 12px;
border: 1px solid black;
border-radius: 3px;
margin: 3px;
padding: 4px;
background: #ffab96;
}
.view:hover {
background: dodgerblue;
color: white;
margin-top: -2px;
box-shadow: 1px 1px 1px black;
}
.view:active {
margin-top: -2px;
}
#playback {
margin-right: 1em;
margin-left: 1em;
}
#playback .view {
background-color: #ab96ff;
}
.view.selected {
background: white;
color: black;
}
#datepicker {
margin-left: 50px;
font-size: 12px;
}
.flatpickr-minute {
pointer-events: none;
}
.flatpickr-minute + .arrowUp {
pointer-events: none;
}
.flatpickr-minute + .arrowUp + .arrowDown {
pointer-events: none;
}
.numInputWrapper:nth-child(3):hover {
background: none;
}
.numInputWrapper:nth-child(3):hover .arrowUp {
display: none;
}
.numInputWrapper:nth-child(3):hover .arrowDown {
display: none;
}
</style>
</head>
<body>
<div class="header">
<h2>COVID-19 (2019-nCoV)</h2>
</div>
<div class="container">
<div id="map"></div>
</div>
<!-- leaflet -->
<script src="https://unpkg.com/leaflet@1.3.3/dist/leaflet.js"></script>
<!-- D3 -->
<script src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<!-- Demo setup -->
<script>
var circles = [];
var initDate = '2001-02-23t09:00:00';
var timeFormatter = d3.timeFormat('%Y-%m-%dt%H:%M:%S');
var numberFormatter = d3.format(",");
var properties = [
{ code: 'Confirmed', desc: 'Confirmed' },
{ code: 'Death', desc: 'Death' },
{ code: 'Recovered', desc: 'Recovered' }
];
var currProperty = 'Confirmed';
var ProvinceState = 'Province/State';
var CountryRegion = 'Country/Region';
var theMap = L.map('map', {maxZoom: 14});
theMap.attributionControl.addAttribution('COVID-19 (2019-nCoV) <a href="https://github.com/CSSEGISandData/COVID-19">JHU CSSE</a>');
theMap.attributionControl.addAttribution('Map tiles by <a href="http://stamen.com">Stamen Design</a>, under <a href="http://creativecommons.org/licenses/by/3.0">CC BY 3.0</a>. Map data by <a href="http://openstreetmap.org">OpenStreetMap</a>, under <a href="http://www.openstreetmap.org/copyright">ODbL</a>');
L.tileLayer('http://tile.stamen.com/terrain/{z}/{x}/{y}.png').addTo(theMap);
// center of map
theMap.setView([31.160629, 112.248863], 4);
var radiusScale = d3.scaleLinear().domain([0, 200]).range([7, 70]).clamp(true);
var colorScale = d3.scaleSequential(d3.interpolateOrRd).domain([0, 100]);
function renderCircles() {
circles.forEach(function (c) { c.remove(); })
circles = [];
theData.features.forEach(function (feature) {
var c = L.circleMarker(
[feature.geometry.coordinates[1], feature.geometry.coordinates[0]],
{
radius: radiusScale(feature.properties[currProperty] * 0.001),
color: colorScale(feature.properties[currProperty]),
fillColor: colorScale(feature.properties[currProperty]),
fillOpacity: 0.5
});
c.addTo(theMap);
if(feature.properties[ProvinceState] !== "") {
c.bindTooltip('<h3>' + feature.properties[ProvinceState] + '</h3> - ' + feature.properties[CountryRegion] + '<br><br><b>' + currProperty + ': </b>' + numberFormatter(feature.properties[currProperty]) + '<br>' + '<b>Death: </b>' + numberFormatter(feature.properties.Death) + '<br>' + '<b>Recovered: </b>' + numberFormatter(feature.properties.Recovered));
} else {
c.bindTooltip('<h3>' + feature.properties[CountryRegion] + '</h3><br><b>' + currProperty + ': </b>' + numberFormatter(feature.properties[currProperty]) + '<br>' + '<b>Death: </b>' + numberFormatter(feature.properties.Death) + '<br>' + '<b>Recovered: </b>' + numberFormatter(feature.properties.Recovered));
}
circles.push(c);
});
}
function fetchData(dateStr) {
var url = 'https://<HANA_Web_url>/node/getSessionInfo';
d3.json(url).then(function(data) {
console.log(data);
theData = data;
renderCircles();
});
}
fetchData(initDate);
</script>
</body>
</html>
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
10 | |
8 | |
7 | |
6 | |
6 | |
6 | |
5 | |
4 | |
3 | |
3 |