Commit f6a4415af709ba3295700f510b7729b4e26d8fa7
0 parents
Exists in
master
start smart-rms-calendar
Showing
18 changed files
with
857 additions
and
0 deletions
Show diff stats
1 | +++ a/.eslintrc.js | |
... | ... | @@ -0,0 +1,19 @@ |
1 | +module.exports = { | |
2 | + "extends": ["standard"], | |
3 | + "env": { | |
4 | + "browser": 1 | |
5 | + }, | |
6 | + | |
7 | + "globals": { | |
8 | + "angular": 1 | |
9 | + }, | |
10 | + | |
11 | + "rules": { | |
12 | + "quotes": [2, "single"], | |
13 | + "space-before-function-paren": 0, | |
14 | + "eqeqeq": 0, | |
15 | + "strict": 0, | |
16 | + "indent": 0, | |
17 | + "eol-last": 0 | |
18 | + } | |
19 | +}; | |
0 | 20 | \ No newline at end of file | ... | ... |
1 | +++ a/.eslintrc.json | |
... | ... | @@ -0,0 +1,23 @@ |
1 | +{ | |
2 | + "env": { | |
3 | + "browser": true, | |
4 | + "commonjs": true, | |
5 | + "es6": true, | |
6 | + "node": true | |
7 | + }, | |
8 | + "parserOptions": { | |
9 | + "ecmaFeatures": { | |
10 | + "jsx": true | |
11 | + }, | |
12 | + "sourceType": "module" | |
13 | + }, | |
14 | + "rules": { | |
15 | + "no-const-assign": "warn", | |
16 | + "no-this-before-super": "warn", | |
17 | + "no-undef": "warn", | |
18 | + "no-unreachable": "warn", | |
19 | + "no-unused-vars": "warn", | |
20 | + "constructor-super": "warn", | |
21 | + "valid-typeof": "warn" | |
22 | + } | |
23 | +} | |
0 | 24 | \ No newline at end of file | ... | ... |
1 | +++ a/.gitignore | |
... | ... | @@ -0,0 +1,227 @@ |
1 | + | |
2 | +# Created by https://www.gitignore.io/api/bower,node,osx,windows,jetbrains | |
3 | + | |
4 | +### Bower ### | |
5 | +bower_components | |
6 | +.bower-cache | |
7 | +.bower-registry | |
8 | +.bower-tmp | |
9 | + | |
10 | + | |
11 | +### Node ### | |
12 | +# Logs | |
13 | +logs | |
14 | +*.log | |
15 | +npm-debug.log* | |
16 | + | |
17 | +# Runtime data | |
18 | +pids | |
19 | +*.pid | |
20 | +*.seed | |
21 | + | |
22 | +# Directory for instrumented libs generated by jscoverage/JSCover | |
23 | +lib-cov | |
24 | + | |
25 | +# Coverage directory used by tools like istanbul | |
26 | +coverage | |
27 | + | |
28 | +# nyc test coverage | |
29 | +.nyc_output | |
30 | + | |
31 | +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) | |
32 | +.grunt | |
33 | + | |
34 | +# node-waf configuration | |
35 | +.lock-wscript | |
36 | + | |
37 | +# Compiled binary addons (http://nodejs.org/api/addons.html) | |
38 | +build/Release | |
39 | + | |
40 | +# Dependency directories | |
41 | +node_modules | |
42 | +jspm_packages | |
43 | + | |
44 | +# Optional npm cache directory | |
45 | +.npm | |
46 | + | |
47 | +# Optional REPL history | |
48 | +.node_repl_history | |
49 | + | |
50 | + | |
51 | +### OSX ### | |
52 | +*.DS_Store | |
53 | +.AppleDouble | |
54 | +.LSOverride | |
55 | + | |
56 | +# Icon must end with two \r | |
57 | +Icon | |
58 | + | |
59 | + | |
60 | +# Thumbnails | |
61 | +._* | |
62 | + | |
63 | +# Files that might appear in the root of a volume | |
64 | +.DocumentRevisions-V100 | |
65 | +.fseventsd | |
66 | +.Spotlight-V100 | |
67 | +.TemporaryItems | |
68 | +.Trashes | |
69 | +.VolumeIcon.icns | |
70 | +.com.apple.timemachine.donotpresent | |
71 | + | |
72 | +# Directories potentially created on remote AFP share | |
73 | +.AppleDB | |
74 | +.AppleDesktop | |
75 | +Network Trash Folder | |
76 | +Temporary Items | |
77 | +.apdisk | |
78 | + | |
79 | + | |
80 | +### Windows ### | |
81 | +# Windows image file caches | |
82 | +Thumbs.db | |
83 | +ehthumbs.db | |
84 | + | |
85 | +# Folder config file | |
86 | +Desktop.ini | |
87 | + | |
88 | +# Recycle Bin used on file shares | |
89 | +$RECYCLE.BIN/ | |
90 | + | |
91 | +# Windows Installer files | |
92 | +*.cab | |
93 | +*.msi | |
94 | +*.msm | |
95 | +*.msp | |
96 | + | |
97 | +# Windows shortcuts | |
98 | +*.lnk | |
99 | + | |
100 | + | |
101 | +### JetBrains ### | |
102 | +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm | |
103 | +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 | |
104 | + | |
105 | +# User-specific stuff: | |
106 | +.idea/workspace.xml | |
107 | +.idea/tasks.xml | |
108 | +.idea/dictionaries | |
109 | +.idea/vcs.xml | |
110 | +.idea/jsLibraryMappings.xml | |
111 | + | |
112 | +# Sensitive or high-churn files: | |
113 | +.idea/dataSources.ids | |
114 | +.idea/dataSources.xml | |
115 | +.idea/dataSources.local.xml | |
116 | +.idea/sqlDataSources.xml | |
117 | +.idea/dynamic.xml | |
118 | +.idea/uiDesigner.xml | |
119 | + | |
120 | +# Gradle: | |
121 | +.idea/gradle.xml | |
122 | +.idea/libraries | |
123 | + | |
124 | +# Mongo Explorer plugin: | |
125 | +.idea/mongoSettings.xml | |
126 | + | |
127 | +## File-based project format: | |
128 | +*.iws | |
129 | + | |
130 | +## Plugin-specific files: | |
131 | + | |
132 | +# IntelliJ | |
133 | +/out/ | |
134 | + | |
135 | +# mpeltonen/sbt-idea plugin | |
136 | +.idea_modules/ | |
137 | + | |
138 | +# JIRA plugin | |
139 | +atlassian-ide-plugin.xml | |
140 | + | |
141 | +# Crashlytics plugin (for Android Studio and IntelliJ) | |
142 | +com_crashlytics_export_strings.xml | |
143 | +crashlytics.properties | |
144 | +crashlytics-build.properties | |
145 | +fabric.properties | |
146 | + | |
147 | +### JetBrains Patch ### | |
148 | +# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721 | |
149 | + | |
150 | +# *.iml | |
151 | +# modules.xml | |
152 | +<<<<<<< HEAD | |
153 | + | |
154 | + | |
155 | +### Eclipse ### | |
156 | + | |
157 | +.metadata | |
158 | +bin/ | |
159 | +tmp/ | |
160 | +*.tmp | |
161 | +*.bak | |
162 | +*.swp | |
163 | +*~.nib | |
164 | +local.properties | |
165 | +.settings/ | |
166 | +.loadpath | |
167 | +.recommenders | |
168 | + | |
169 | +# Eclipse Core | |
170 | +.project | |
171 | + | |
172 | +# External tool builders | |
173 | +.externalToolBuilders/ | |
174 | + | |
175 | +# Locally stored "Eclipse launch configurations" | |
176 | +*.launch | |
177 | + | |
178 | +# PyDev specific (Python IDE for Eclipse) | |
179 | +*.pydevproject | |
180 | + | |
181 | +# CDT-specific (C/C++ Development Tooling) | |
182 | +.cproject | |
183 | + | |
184 | +# JDT-specific (Eclipse Java Development Tools) | |
185 | +.classpath | |
186 | + | |
187 | +# Java annotation processor (APT) | |
188 | +.factorypath | |
189 | + | |
190 | +# PDT-specific (PHP Development Tools) | |
191 | +.buildpath | |
192 | + | |
193 | +# sbteclipse plugin | |
194 | +.target | |
195 | + | |
196 | +# Tern plugin | |
197 | +.tern-project | |
198 | + | |
199 | +# TeXlipse plugin | |
200 | +.texlipse | |
201 | + | |
202 | +# STS (Spring Tool Suite) | |
203 | +.springBeans | |
204 | + | |
205 | +# Code Recommenders | |
206 | +.recommenders/ | |
207 | + | |
208 | + | |
209 | +### Java ### | |
210 | +*.class | |
211 | + | |
212 | +# Mobile Tools for Java (J2ME) | |
213 | +.mtj.tmp/ | |
214 | + | |
215 | +# Package Files # | |
216 | +## commented out to support storage of libs in git | |
217 | +# *.jar | |
218 | +# *.war | |
219 | +# *.ear | |
220 | + | |
221 | +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | |
222 | +hs_err_pid* | |
223 | +logs | |
224 | + | |
225 | +# logstatalarm # | |
226 | +logstatalarm | |
227 | +T16/Interface_Specification_SS7_Simulator_1.0_draft_J.docx | ... | ... |
1 | +++ a/.vscode/cSpell.json | |
... | ... | @@ -0,0 +1,26 @@ |
1 | +// cSpell Settings | |
2 | +{ | |
3 | + // Version of the setting file. Always 0.1 | |
4 | + "version": "0.1", | |
5 | + // language - current active spelling language | |
6 | + "language": "en", | |
7 | + // words - list of words to be always considered correct | |
8 | + "words": [ | |
9 | + "ussd", | |
10 | + "eventlog", | |
11 | + "USSN", | |
12 | + "PUSR", | |
13 | + "GPRS", | |
14 | + "isup", | |
15 | + "toastr", | |
16 | + "}", | |
17 | + "lastname", | |
18 | + "firstname" | |
19 | + ], | |
20 | + // flagWords - list of words to be always considered incorrect | |
21 | + // This is useful for offensive words and common spelling errors. | |
22 | + // For example "hte" should be "the" | |
23 | + "flagWords": [ | |
24 | + "hte" | |
25 | + ] | |
26 | +} | |
0 | 27 | \ No newline at end of file | ... | ... |
1 | +++ a/.vscode/extensions.json | |
... | ... | @@ -0,0 +1,13 @@ |
1 | +{ | |
2 | + "recommendations": [ | |
3 | + "christian-kohler.path-intellisense", | |
4 | + "dbaeumer.vscode-eslint", | |
5 | + "abusaidm.html-snippets", | |
6 | + "be5invis.vscode-icontheme-nomo-dark", | |
7 | + "alefragnani.Bookmarks", | |
8 | + "donjayamanne.githistory", | |
9 | + "karyfoundation.comment", | |
10 | + "ms-vscode.typescript-javascript-grammar", | |
11 | + "mkaufman.HTMLHint" | |
12 | + ] | |
13 | +} | |
0 | 14 | \ No newline at end of file | ... | ... |
1 | +++ a/.vscode/launch.json | |
... | ... | @@ -0,0 +1,46 @@ |
1 | +{ | |
2 | + "version": "0.2.0", | |
3 | + "configurations": [ | |
4 | + { | |
5 | + "name": "Launch", | |
6 | + "type": "node", | |
7 | + "request": "launch", | |
8 | + "program": "${workspaceRoot}/server.js", | |
9 | + "stopOnEntry": false, | |
10 | + "args": [], | |
11 | + "cwd": "${workspaceRoot}", | |
12 | + "preLaunchTask": null, | |
13 | + "runtimeExecutable": null, | |
14 | + "runtimeArgs": [ | |
15 | + "--nolazy" | |
16 | + ], | |
17 | + "env": { | |
18 | + "NODE_ENV": "localhost" | |
19 | + }, | |
20 | + "console": "integratedTerminal", | |
21 | + "sourceMaps": true, | |
22 | + "outDir": null | |
23 | + }, | |
24 | + { | |
25 | + "name": "Attach", | |
26 | + "type": "node", | |
27 | + "request": "attach", | |
28 | + "port": 5858, | |
29 | + "address": "localhost", | |
30 | + "restart": false, | |
31 | + "sourceMaps": false, | |
32 | + "outDir": null, | |
33 | + "localRoot": "${workspaceRoot}", | |
34 | + "remoteRoot": null | |
35 | + }, | |
36 | + { | |
37 | + "name": "Attach to Process", | |
38 | + "type": "node", | |
39 | + "request": "attach", | |
40 | + "processId": "${command.PickProcess}", | |
41 | + "port": 5858, | |
42 | + "sourceMaps": false, | |
43 | + "outDir": null | |
44 | + } | |
45 | + ] | |
46 | +} | |
0 | 47 | \ No newline at end of file | ... | ... |
1 | +++ a/.vscode/settings.json | |
... | ... | @@ -0,0 +1,17 @@ |
1 | +// Place your settings in this file to overwrite default and user settings. | |
2 | +{ | |
3 | + "editor.tabSize": 4, | |
4 | + "beautify.onSave": true, | |
5 | + "editor.renderIndentGuides": true, | |
6 | + "editor.wordWrap": false, | |
7 | + "editor.detectIndentation": false, | |
8 | + "editor.wrappingColumn": -1, | |
9 | + "editor.cursorBlinking": "smooth", | |
10 | + "editor.glyphMargin": true, | |
11 | + "editor.formatOnType": true, | |
12 | + "html.suggest.angular1": true, | |
13 | + "html.suggest.html5": true, | |
14 | + "editor.formatOnSave": true, | |
15 | + "workbench.editor.showIcons": true, | |
16 | + "eslint.enable": false | |
17 | +} | |
0 | 18 | \ No newline at end of file | ... | ... |
1 | +++ a/app/controllers/home.controller.js | |
... | ... | @@ -0,0 +1,73 @@ |
1 | +'use strict' | |
2 | + | |
3 | +const console = process.console | |
4 | +const yamlConfig = require('node-yaml-config') | |
5 | +const path = require('path') | |
6 | +const config = yamlConfig.load(path.join(__dirname, '/../../config/config.yml')) | |
7 | + | |
8 | +const lib = require('../lib') | |
9 | + | |
10 | +// lib.authorize() | |
11 | +// lib.listEvents() | |
12 | +// lib.createEvent() | |
13 | + | |
14 | +const url = config.server.url | |
15 | +const port = config.server.port | |
16 | +const urlto = config.server.urlto | |
17 | +const portto = config.server.portto | |
18 | + | |
19 | +function index(req, res) { | |
20 | + res.send({ | |
21 | + message: 'Google Calendar API', | |
22 | + endpoint: { | |
23 | + listEvents: 'GET /events', | |
24 | + createEvent: 'POST /events' | |
25 | + } | |
26 | + }) | |
27 | +} | |
28 | + | |
29 | +function events(req, res) { | |
30 | + lib.authorize((err, auth) => { | |
31 | + if (err) { | |
32 | + res.send(err) | |
33 | + } | |
34 | + lib.listEvents(auth, (err, response) => { | |
35 | + if (err) { | |
36 | + res.send(err) | |
37 | + } else { | |
38 | + res.send(response) | |
39 | + } | |
40 | + }) | |
41 | + }) | |
42 | +} | |
43 | + | |
44 | +function create(req, res) { | |
45 | + let payload = req.body | |
46 | + | |
47 | + let summary = payload.summary | |
48 | + let description = payload.description | |
49 | + let email = payload.email | |
50 | + let startDate = payload.startDate | |
51 | + let endDate = payload.endDate | |
52 | + | |
53 | + lib.authorize((err, auth) => { | |
54 | + if (err) { | |
55 | + res.send(err) | |
56 | + } | |
57 | + | |
58 | + // let options = lib.eventBuilder(payload) | |
59 | + // options.auth = auth | |
60 | + | |
61 | + lib.createEvent(auth, payload, (err, result) => { | |
62 | + if (err) { | |
63 | + res.send(err) | |
64 | + } else { | |
65 | + res.send(result) | |
66 | + } | |
67 | + }) | |
68 | + }) | |
69 | +} | |
70 | + | |
71 | +module.exports.index = index | |
72 | +module.exports.events = events | |
73 | +module.exports.create = create | ... | ... |
1 | +++ a/app/lib/index.js | |
... | ... | @@ -0,0 +1,97 @@ |
1 | +'use strict'; | |
2 | + | |
3 | +const google = require('googleapis'); | |
4 | +const googleAuth = require('google-auth-library'); | |
5 | +const calendar = google.calendar('v3'); | |
6 | + | |
7 | +const fs = require('fs'); | |
8 | + | |
9 | +const SCOPES = [process.env.SCOPES]; | |
10 | +const TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH || process.env.USERPROFILE) + '/.credentials/'; | |
11 | +const TOKEN_PATH = TOKEN_DIR + 'calendar-nodejs-quickstart.json'; | |
12 | + | |
13 | +module.exports = { | |
14 | + | |
15 | + authorize: (callback) => { | |
16 | + | |
17 | + fs.readFile('client_secret.json', function processClientSecrets(err, content) { | |
18 | + if (err) { | |
19 | + console.log('Error loading client secret file: ' + err); | |
20 | + return; | |
21 | + } | |
22 | + | |
23 | + let credentials = JSON.parse(content); | |
24 | + var clientSecret = credentials.installed.client_secret; | |
25 | + var clientId = credentials.installed.client_id; | |
26 | + var redirectUrl = credentials.installed.redirect_uris[0]; | |
27 | + var auth = new googleAuth(); | |
28 | + var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl); | |
29 | + | |
30 | + // Check if we have previously stored a token. | |
31 | + fs.readFile(TOKEN_PATH, function (err, token) { | |
32 | + if (err) { | |
33 | + return callback(err); | |
34 | + } else { | |
35 | + oauth2Client.credentials = JSON.parse(token); | |
36 | + return callback(null, oauth2Client); | |
37 | + } | |
38 | + }); | |
39 | + | |
40 | + }); | |
41 | + | |
42 | + }, | |
43 | + | |
44 | + getNewToken: (oauth2Client, callback) => { | |
45 | + var authUrl = oauth2Client.generateAuthUrl({ | |
46 | + access_type: 'offline', | |
47 | + scope: SCOPES | |
48 | + }); | |
49 | + console.log('Authorize this app by visiting this url: ', authUrl); | |
50 | + var rl = readline.createInterface({ | |
51 | + input: process.stdin, | |
52 | + output: process.stdout | |
53 | + }); | |
54 | + rl.question('Enter the code from that page here: ', function (code) { | |
55 | + rl.close(); | |
56 | + oauth2Client.getToken(code, function (err, token) { | |
57 | + if (err) { | |
58 | + console.log('Error while trying to retrieve access token', err); | |
59 | + return; | |
60 | + } | |
61 | + oauth2Client.credentials = token; | |
62 | + storeToken(token); | |
63 | + callback(oauth2Client); | |
64 | + }); | |
65 | + }); | |
66 | + }, | |
67 | + | |
68 | + listEvents: (auth, callback) => { | |
69 | + calendar.events.list({ | |
70 | + auth: auth, | |
71 | + calendarId: process.env.CALENDAR_ID, | |
72 | + timeMin: (new Date()).toISOString(), | |
73 | + maxResults: 50, | |
74 | + singleEvents: true, | |
75 | + orderBy: 'startTime' | |
76 | + }, (err, response) => { | |
77 | + if (err) { | |
78 | + return callback(err); | |
79 | + } | |
80 | + return callback(null, response); | |
81 | + }); | |
82 | + }, | |
83 | + | |
84 | + createEvent: (auth, event, callback) => { | |
85 | + | |
86 | + calendar.events.insert({ | |
87 | + auth: auth, | |
88 | + calendarId: process.env.CALENDAR_ID, | |
89 | + resource: event, | |
90 | + }, (err, event) => { | |
91 | + if (err) { | |
92 | + return callback('There was an error contacting the Calendar service: ' + err); | |
93 | + } | |
94 | + return callback(null, event.htmlLink); | |
95 | + }); | |
96 | + } | |
97 | +} | |
0 | 98 | \ No newline at end of file | ... | ... |
1 | +++ a/app/routes/home.routes.js | |
... | ... | @@ -0,0 +1,10 @@ |
1 | +// var console = process.console | |
2 | +var express = require('express') | |
3 | +var router = express.Router() | |
4 | +var home = require('../controllers/home.controller') | |
5 | + | |
6 | +router.get('/', home.index) | |
7 | +router.get('/events', home.events) | |
8 | +router.post('/events', home.create) | |
9 | + | |
10 | +module.exports = router | |
0 | 11 | \ No newline at end of file | ... | ... |
1 | +++ a/bower.json | |
... | ... | @@ -0,0 +1,36 @@ |
1 | +{ | |
2 | + "name": "ss7", | |
3 | + "description": "", | |
4 | + "main": "", | |
5 | + "license": "MIT", | |
6 | + "homepage": "", | |
7 | + "private": true, | |
8 | + "ignore": [ | |
9 | + "**/.*", | |
10 | + "node_modules", | |
11 | + "bower_components", | |
12 | + "test", | |
13 | + "tests" | |
14 | + ], | |
15 | + "dependencies": { | |
16 | + "angular-datatables": "^0.5.4", | |
17 | + "yamljs": "^0.1.5", | |
18 | + "sweetalert": "^1.1.3", | |
19 | + "angular-ui-router": "^0.3.1", | |
20 | + "ui-router-extras": "^0.1.2", | |
21 | + "ng-slim-scroll": "^0.2.2", | |
22 | + "angular-slimscroll": "^1.1.5", | |
23 | + "angular-ladda": "^0.4.1", | |
24 | + "toastr": "^2.1.3", | |
25 | + "angular-toastr": "^2.1.1", | |
26 | + "angular-animate": "^1.5.8", | |
27 | + "angular-validation-match": "^1.9.0", | |
28 | + "ngFitText": "^4.2.1", | |
29 | + "angular-loading-bar": "^0.9.0", | |
30 | + "animate.css": "^3.5.2", | |
31 | + "ng-dialog": "^0.6.4" | |
32 | + }, | |
33 | + "resolutions": { | |
34 | + "angular-ui-router": "^0.3.1" | |
35 | + } | |
36 | +} | ... | ... |
1 | +++ a/client_secret.json | |
... | ... | @@ -0,0 +1,14 @@ |
1 | +{ | |
2 | + "installed": { | |
3 | + "client_id": "16634359544-7crvssfmpmtp0ng3jbipms65ccl9aol1.apps.googleusercontent.com", | |
4 | + "project_id": "psyched-garage-146109", | |
5 | + "auth_uri": "https://accounts.google.com/o/oauth2/auth", | |
6 | + "token_uri": "https://accounts.google.com/o/oauth2/token", | |
7 | + "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs", | |
8 | + "client_secret": "lpIa_7Wwbang6jTypMfCpOR6", | |
9 | + "redirect_uris": [ | |
10 | + "urn:ietf:wg:oauth:2.0:oob", | |
11 | + "http://localhost" | |
12 | + ] | |
13 | + } | |
14 | +} | |
0 | 15 | \ No newline at end of file | ... | ... |
1 | +++ a/config/config.yml | |
... | ... | @@ -0,0 +1,18 @@ |
1 | +##### deverlopment Config | |
2 | +localhost: | |
3 | + skipLogin: true | |
4 | + debug: true | |
5 | + server: | |
6 | + url: 'localhost' | |
7 | + urlto: 'localhost' | |
8 | + port: 3001 | |
9 | + portto: 4001 | |
10 | + database: | |
11 | + host: 'localhost' | |
12 | + port: 27017 | |
13 | + name: 'ss7' | |
14 | + options: | |
15 | + user: | |
16 | + pass: | |
17 | + timerecheck: '10000' #millisecond | |
18 | + apitimeout: 3000 #millisecond | |
0 | 19 | \ No newline at end of file | ... | ... |
1 | +++ a/jsconfig.json | |
... | ... | @@ -0,0 +1,16 @@ |
1 | +{ | |
2 | + // See https://go.microsoft.com/fwlink/?LinkId=759670 | |
3 | + // for the documentation about the jsconfig.json format | |
4 | + "compilerOptions": { | |
5 | + "target": "es6", | |
6 | + "module": "commonjs", | |
7 | + "allowSyntheticDefaultImports": true | |
8 | + }, | |
9 | + "exclude": [ | |
10 | + "node_modules", | |
11 | + "bower_components", | |
12 | + "jspm_packages", | |
13 | + "tmp", | |
14 | + "temp" | |
15 | + ] | |
16 | +} | ... | ... |
1 | +++ a/package.json | |
... | ... | @@ -0,0 +1,32 @@ |
1 | +{ | |
2 | + "name": "smart-rms-schedule", | |
3 | + "version": "1.0.0", | |
4 | + "dependencies": { | |
5 | + "async": "^2.0.1", | |
6 | + "bluebird": "^3.4.1", | |
7 | + "body-parser": "~1.15.0", | |
8 | + "busboy-body-parser": "0.0.10", | |
9 | + "ejs": "^2.5.2", | |
10 | + "express": "~4.13.0", | |
11 | + "formidable": "^1.0.17", | |
12 | + "google-auth-library": "^0.9.8", | |
13 | + "googleapis": "^14.0.0", | |
14 | + "indicative": "^2.1.0", | |
15 | + "moment": "^2.14.1", | |
16 | + "moment-timezone": "^0.5.5", | |
17 | + "node-yaml-config": "0.0.4", | |
18 | + "scribe-js": "^2.0.4", | |
19 | + "unirest": "^0.5.0" | |
20 | + }, | |
21 | + "devDependencies": { | |
22 | + "eslint": "^3.4.0", | |
23 | + "eslint-config-angular": "^0.5.0", | |
24 | + "eslint-config-defaults": "^9.0.0", | |
25 | + "eslint-config-google": "^0.6.0", | |
26 | + "eslint-config-standard": "^6.0.0", | |
27 | + "eslint-plugin-angular": "^1.3.1", | |
28 | + "eslint-plugin-promise": "^2.0.1", | |
29 | + "eslint-plugin-standard": "^2.0.0", | |
30 | + "gulp-ftp": "^1.1.0" | |
31 | + } | |
32 | +} | ... | ... |
1 | +++ a/public/views/index.html | |
... | ... | @@ -0,0 +1,14 @@ |
1 | +<!DOCTYPE html> | |
2 | +<html lang="en"> | |
3 | + | |
4 | +<head> | |
5 | + <title>Smart RMS Schedule</title> | |
6 | + <meta charset="UTF-8"> | |
7 | + <meta name="viewport" content="width=device-width, initial-scale=1"> | |
8 | +</head> | |
9 | + | |
10 | +<body> | |
11 | + <h1>HELLO</h1> | |
12 | +</body> | |
13 | + | |
14 | +</html> | |
0 | 15 | \ No newline at end of file | ... | ... |
1 | +++ a/quickstart.js | |
... | ... | @@ -0,0 +1,131 @@ |
1 | + | |
2 | + | |
3 | +var fs = require('fs'); | |
4 | +var readline = require('readline'); | |
5 | +var google = require('googleapis'); | |
6 | +var googleAuth = require('google-auth-library'); | |
7 | + | |
8 | +// If modifying these scopes, delete your previously saved credentials | |
9 | +// at ~/.credentials/calendar-nodejs-quickstart.json | |
10 | +var SCOPES = ['https://www.googleapis.com/auth/calendar.readonly']; | |
11 | +var TOKEN_DIR = (process.env.HOME || process.env.HOMEPATH || | |
12 | + process.env.USERPROFILE) + '/.credentials/'; | |
13 | +var TOKEN_PATH = TOKEN_DIR + 'calendar-nodejs-quickstart.json'; | |
14 | + | |
15 | +// Load client secrets from a local file. | |
16 | +fs.readFile('client_secret.json', function processClientSecrets(err, content) { | |
17 | + if (err) { | |
18 | + console.log('Error loading client secret file: ' + err); | |
19 | + return; | |
20 | + } | |
21 | + // Authorize a client with the loaded credentials, then call the | |
22 | + // Google Calendar API. | |
23 | + authorize(JSON.parse(content), listEvents); | |
24 | +}); | |
25 | + | |
26 | +/** | |
27 | + * Create an OAuth2 client with the given credentials, and then execute the | |
28 | + * given callback function. | |
29 | + * | |
30 | + * @param {Object} credentials The authorization client credentials. | |
31 | + * @param {function} callback The callback to call with the authorized client. | |
32 | + */ | |
33 | +function authorize(credentials, callback) { | |
34 | + var clientSecret = credentials.installed.client_secret; | |
35 | + var clientId = credentials.installed.client_id; | |
36 | + var redirectUrl = credentials.installed.redirect_uris[0]; | |
37 | + var auth = new googleAuth(); | |
38 | + var oauth2Client = new auth.OAuth2(clientId, clientSecret, redirectUrl); | |
39 | + | |
40 | + // Check if we have previously stored a token. | |
41 | + fs.readFile(TOKEN_PATH, function(err, token) { | |
42 | + if (err) { | |
43 | + getNewToken(oauth2Client, callback); | |
44 | + } else { | |
45 | + oauth2Client.credentials = JSON.parse(token); | |
46 | + callback(oauth2Client); | |
47 | + } | |
48 | + }); | |
49 | +} | |
50 | + | |
51 | +/** | |
52 | + * Get and store new token after prompting for user authorization, and then | |
53 | + * execute the given callback with the authorized OAuth2 client. | |
54 | + * | |
55 | + * @param {google.auth.OAuth2} oauth2Client The OAuth2 client to get token for. | |
56 | + * @param {getEventsCallback} callback The callback to call with the authorized | |
57 | + * client. | |
58 | + */ | |
59 | +function getNewToken(oauth2Client, callback) { | |
60 | + var authUrl = oauth2Client.generateAuthUrl({ | |
61 | + access_type: 'offline', | |
62 | + scope: SCOPES | |
63 | + }); | |
64 | + console.log('Authorize this app by visiting this url: ', authUrl); | |
65 | + var rl = readline.createInterface({ | |
66 | + input: process.stdin, | |
67 | + output: process.stdout | |
68 | + }); | |
69 | + rl.question('Enter the code from that page here: ', function(code) { | |
70 | + rl.close(); | |
71 | + oauth2Client.getToken(code, function(err, token) { | |
72 | + if (err) { | |
73 | + console.log('Error while trying to retrieve access token', err); | |
74 | + return; | |
75 | + } | |
76 | + oauth2Client.credentials = token; | |
77 | + storeToken(token); | |
78 | + callback(oauth2Client); | |
79 | + }); | |
80 | + }); | |
81 | +} | |
82 | + | |
83 | +/** | |
84 | + * Store token to disk be used in later program executions. | |
85 | + * | |
86 | + * @param {Object} token The token to store to disk. | |
87 | + */ | |
88 | +function storeToken(token) { | |
89 | + try { | |
90 | + fs.mkdirSync(TOKEN_DIR); | |
91 | + } catch (err) { | |
92 | + if (err.code != 'EEXIST') { | |
93 | + throw err; | |
94 | + } | |
95 | + } | |
96 | + fs.writeFile(TOKEN_PATH, JSON.stringify(token)); | |
97 | + console.log('Token stored to ' + TOKEN_PATH); | |
98 | +} | |
99 | + | |
100 | +/** | |
101 | + * Lists the next 10 events on the user's primary calendar. | |
102 | + * | |
103 | + * @param {google.auth.OAuth2} auth An authorized OAuth2 client. | |
104 | + */ | |
105 | +function listEvents(auth) { | |
106 | + var calendar = google.calendar('v3'); | |
107 | + calendar.events.list({ | |
108 | + auth: auth, | |
109 | + calendarId: 'primary', | |
110 | + timeMin: (new Date()).toISOString(), | |
111 | + maxResults: 10, | |
112 | + singleEvents: true, | |
113 | + orderBy: 'startTime' | |
114 | + }, function(err, response) { | |
115 | + if (err) { | |
116 | + console.log('The API returned an error: ' + err); | |
117 | + return; | |
118 | + } | |
119 | + var events = response.items; | |
120 | + if (events.length == 0) { | |
121 | + console.log('No upcoming events found.'); | |
122 | + } else { | |
123 | + console.log('Upcoming 10 events:'); | |
124 | + for (var i = 0; i < events.length; i++) { | |
125 | + var event = events[i]; | |
126 | + var start = event.start.dateTime || event.start.date; | |
127 | + console.log('%s - %s', start, event.summary); | |
128 | + } | |
129 | + } | |
130 | + }); | |
131 | +} | |
0 | 132 | \ No newline at end of file | ... | ... |
1 | +++ a/server.js | |
... | ... | @@ -0,0 +1,45 @@ |
1 | +var express = require('express') | |
2 | +var bodyParser = require('body-parser') | |
3 | +var yaml_config = require('node-yaml-config') | |
4 | +var busboyBodyParser = require('busboy-body-parser') | |
5 | +var scribe = require('scribe-js')() | |
6 | +var Async = require('async') | |
7 | + | |
8 | +var console = process.console | |
9 | +var app = express() | |
10 | +var router = express.Router() | |
11 | +var config = yaml_config.load(__dirname + '/config/config.yml') | |
12 | + | |
13 | +var url = config.server.url | |
14 | +var port = config.server.port | |
15 | + | |
16 | +app.use(bodyParser.urlencoded({ | |
17 | + extended: false | |
18 | +})) | |
19 | +app.use(bodyParser.json()) | |
20 | +app.use(express.static('public')) | |
21 | +app.use(express.static('bower_components')) | |
22 | + | |
23 | +var home = require('./app/routes/home.routes') | |
24 | + | |
25 | +app.set('views', './public/views') | |
26 | +app.set('view engine', 'html') | |
27 | +app.engine('html', require('ejs').renderFile) | |
28 | + | |
29 | +app.use(function (req, res, next) { | |
30 | + res.header('Access-Control-Allow-Origin', '*') | |
31 | + res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept') | |
32 | + next() | |
33 | +}) | |
34 | + | |
35 | +app.use('/', home) | |
36 | + | |
37 | +app.use(scribe.express.logger()) // Log each request | |
38 | +app.use('/logs', scribe.webPanel()) | |
39 | + | |
40 | +app.use(busboyBodyParser()) | |
41 | + | |
42 | +app.listen(port) | |
43 | +// console.log('Server is running at http://'+url+':'+port+''); | |
44 | + | |
45 | +console.tag('START').time().file().log('Server is running at http://' + url + ':' + port) | |
0 | 46 | \ No newline at end of file | ... | ... |