Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexKlimenkov committed Nov 27, 2018
0 parents commit 7245a1c
Show file tree
Hide file tree
Showing 11 changed files with 529 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
@@ -0,0 +1,2 @@
public/codebase
node_modules
29 changes: 29 additions & 0 deletions README.md
@@ -0,0 +1,29 @@
# dhtmlxScheduler with Nodejs

Implementing backend API for dhtmlxScheduler using node.js and MySQL.

## Requirements

- MySql
- node.js

## Setup

- clone or download the demo

```
$ git clone https://github.com/DHTMLX/scheduler-howto-node
$ cd ./scheduler-howto-node
```

- import database from `mysql_dump.sql`
- update db connection settings in `server.js`
- install dependencies using `yarn install` or `npm install`

## Run
- `yarn start`
or
- `npm start`

## Tutorial
A complete tutorial here https://docs.dhtmlx.com/scheduler/desktop__howtostart_nodejs.html
23 changes: 23 additions & 0 deletions mysql_dump.sql
@@ -0,0 +1,23 @@
CREATE DATABASE IF NOT EXISTS `scheduler_howto_node`;
USE `scheduler_howto_node`;

DROP TABLE IF EXISTS `events`;
CREATE TABLE `events` (
`id` bigint(20) unsigned AUTO_INCREMENT,
`start_date` datetime NOT NULL,
`end_date` datetime NOT NULL,
`text` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;

DROP TABLE IF EXISTS `recurring_events`;
CREATE TABLE `recurring_events` (
`id` bigint(20) unsigned AUTO_INCREMENT,
`start_date` datetime NOT NULL,
`end_date` datetime NOT NULL,
`text` varchar(255) DEFAULT NULL,
`event_pid` bigint(20) unsigned DEFAULT '0',
`event_length` bigint(20) unsigned DEFAULT '0',
`rec_type` varchar(25) DEFAULT '""',
PRIMARY KEY (`id`)
) DEFAULT CHARSET=utf8;
16 changes: 16 additions & 0 deletions package.json
@@ -0,0 +1,16 @@
{
"name": "ttttt",
"version": "1.0.0",
"main": "server.js",
"license": "MIT",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"body-parser": "^1.18.3",
"date-format-lite": "^17.7.0",
"express": "^4.16.4",
"helmet": "^3.15.0",
"mysql": "^2.16.0"
}
}
48 changes: 48 additions & 0 deletions public/basic.html
@@ -0,0 +1,48 @@
<!doctype html>
<html>
<head>
<title>DHTMLX Scheduler with Node.js - Basic CRUD</title>
<meta charset="utf-8">

<script src="https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js" charset="utf-8"></script>
<link rel="stylesheet" href="https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_material.css" type="text/css" charset="utf-8">
<style>
html, body{
margin:0px;
padding:0px;
height:100%;
overflow:hidden;
}
</style>
</head>
<body>
<div id="scheduler_here" class="dhx_cal_container" style='width:100%; height:100%;'>
<div class="dhx_cal_navline">
<div class="dhx_cal_prev_button">&nbsp;</div>
<div class="dhx_cal_next_button">&nbsp;</div>
<div class="dhx_cal_today_button"></div>
<div class="dhx_cal_date"></div>
<div class="dhx_cal_tab" name="day_tab"></div>
<div class="dhx_cal_tab" name="week_tab"></div>
<div class="dhx_cal_tab" name="month_tab"></div>
</div>
<div class="dhx_cal_header"></div>
<div class="dhx_cal_data"></div>
</div>
<script>
scheduler.config.xml_date="%Y-%m-%d %H:%i";
scheduler.init("scheduler_here", new Date(2018, 0, 20), "week");
scheduler.setLoadMode("day");

// load data from backend
scheduler.load("/events", "json");

// connect backend to scheduler
var dp = new dataProcessor("/events");
dp.init(scheduler);

// set data exchange mode
dp.setTransactionMode("REST");
</script>
</body>
</html>
74 changes: 74 additions & 0 deletions public/index.html
@@ -0,0 +1,74 @@
<!doctype html>
<html>
<head>
<title>Getting started with dhtmlxScheduler</title>
<meta charset="utf-8">
<link href="https://fonts.googleapis.com/css?family=Roboto:400,600" rel="stylesheet" type="text/css">
<style>
html, body{
background-color: #fff;
color: #636b6f;
font-family: 'Roboto', sans-serif;
padding:0;
height: 100vh;
margin: 0;
}

.main{
height: 100vh;
text-align: center;
align-items: center;
display: flex;
justify-content: center;
flex-direction: column;
}

h1{
margin-top:0;
}

h2 {
margin-top: 20px;
font-weight: normal;
}

.links a {
color: #0f95d7;
padding: 0 25px;
font-size: 13px;
font-weight: 600;
letter-spacing: .1rem;
text-decoration: none;
text-transform: uppercase;
}

.links.samples > a {
font-size:16px;
text-decoration: underline;
}

.links.samples{
margin-bottom:50px;
}
</style>
</head>
<body>
<div class="main">
<h1>dhtmlxScheduler</h1>
<div class="content">
<h2>Check out our samples:</h2>
<div class="links samples">
<a href="/basic.html">Basic CRUD</a>
<a href="/recurring.html">Recurring events</a>
</div>
<h2>Useful links</h2>
<div class="links useful-links">
<a href="https://docs.dhtmlx.com/scheduler">Guides</a>
<a href="https://github.com/DHTMLX/scheduler-howto-node">Github</a>
<a href="https://forum.dhtmlx.com/c/scheduler-all/scheduler">Forum</a>
<a href="https://dhtmlx.com/docs/products/dhtmlxScheduler/">Sales & Licensing</a>
</div>
</div>
</div>
</body>
</html>
49 changes: 49 additions & 0 deletions public/recurring.html
@@ -0,0 +1,49 @@
<!doctype html>
<html>
<head>
<title>DHTMLX Scheduler with Node.js - Recurring events</title>
<meta charset="utf-8">

<script src="https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler.js"></script>
<script src="https://cdn.dhtmlx.com/scheduler/edge/ext/dhtmlxscheduler_recurring.js"></script>
<link rel="stylesheet" href="https://cdn.dhtmlx.com/scheduler/edge/dhtmlxscheduler_material.css" type="text/css" charset="utf-8">
<style>
html, body{
margin:0px;
padding:0px;
height:100%;
overflow:hidden;
}
</style>
</head>
<body>
<div id="scheduler_here" class="dhx_cal_container" style='width:100%; height:100%;'>
<div class="dhx_cal_navline">
<div class="dhx_cal_prev_button">&nbsp;</div>
<div class="dhx_cal_next_button">&nbsp;</div>
<div class="dhx_cal_today_button"></div>
<div class="dhx_cal_date"></div>
<div class="dhx_cal_tab" name="day_tab"></div>
<div class="dhx_cal_tab" name="week_tab"></div>
<div class="dhx_cal_tab" name="month_tab"></div>
</div>
<div class="dhx_cal_header"></div>
<div class="dhx_cal_data"></div>
</div>
<script>
scheduler.config.xml_date="%Y-%m-%d %H:%i";
scheduler.init("scheduler_here", new Date(2018, 0, 20), "week");
scheduler.setLoadMode("day");

// load data from backend
scheduler.load("/recurring_events", "json");

// send client-side updates to the backend
var dp = new dataProcessor("/recurring_events");
dp.init(scheduler);

// set data exchange mode
dp.setTransactionMode("REST");
</script>
</body>
</html>
36 changes: 36 additions & 0 deletions router.js
@@ -0,0 +1,36 @@
function callMethod (method) {
return async (req, res) => {
let result;

try {
result = await method(req, res);
} catch (e) {
result = {
action: "error",
message: e.message
}
}

res.send(result);
}
};

module.exports = {
setRoutes (app, prefix, storage) {
app.get(`${prefix}`, callMethod((req) => {
return storage.getAll(req.query);
}));

app.post(`${prefix}`, callMethod((req) => {
return storage.insert(req.body);
}));

app.put(`${prefix}/:id`, callMethod((req) => {
return storage.update(req.params.id, req.body);
}));

app.delete(`${prefix}/:id`, callMethod((req) => {
return storage.delete(req.params.id);
}));
}
};
58 changes: 58 additions & 0 deletions server.js
@@ -0,0 +1,58 @@
const express = require("express");
// use body parse for parsing POST request
const bodyParser = require("body-parser");
const app = express();
const port = 3000;

// we'll use mysql for db access and util to promisify queries
const util = require("util");
const mysql = require('mysql');

// use your own parameters for database
const mysqlConfig = {
"connectionLimit": 10,
"host": "localhost",
"user": "root",
"password": "",
"database": "scheduler_howto_node"
};

const helmet = require("helmet");
app.use(helmet());

// scheduler sends application/x-www-form-urlencoded requests,
app.use(bodyParser.urlencoded({ extended: true }));

// you'll need these headers if your API is deployed on a different domain than a public page
// in production system you could set Access-Control-Allow-Origin to your domains
// or drop this expression - by default CORS security is turned on in browsers
app.use(function(req, res, next) {
res.header("Access-Control-Allow-Origin", "*");
res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
res.header("Access-Control-Allow-Methods", "*");
next();
});

// return static pages from "./public" directory
app.use(express.static(__dirname + "/public"));

const router = require("./router");

// open connection to mysql
const connectionPool = mysql.createPool(mysqlConfig);
connectionPool.query = util.promisify(connectionPool.query);

// add listeners to basic CRUD requests
const Storage = require("./storage");
const eventsStorage = new Storage(connectionPool);
router.setRoutes(app, "/events", eventsStorage);

// add listeners to basic CRUD with recurring events support
const RecurringStorage = require("./storage_recurring");
const recurringEventsStorage = new RecurringStorage(connectionPool);
router.setRoutes(app, "/recurring_events", recurringEventsStorage)

// start server
app.listen(port, () => {
console.log("Server is running on port " + port + "...");
});

0 comments on commit 7245a1c

Please sign in to comment.