├── blog1
├── .editorconfig
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .yo-rc.json
├── README.md
├── client
│ └── README.md
├── common
│ └── models
│ │ ├── category.js
│ │ ├── category.json
│ │ ├── entry.js
│ │ ├── entry.json
│ │ ├── test-content.js
│ │ └── test-content.json
├── package.json
└── server
│ ├── boot
│ ├── 01seed.js
│ ├── authentication.js
│ └── routes.js
│ ├── component-config.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.json
│ ├── middleware.production.json
│ ├── model-config.json
│ ├── server.js
│ └── views
│ ├── entry.handlebars
│ ├── index.handlebars
│ └── layouts
│ └── main.handlebars
├── blog2
├── .editorconfig
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .yo-rc.json
├── README.md
├── client
│ ├── README.md
│ └── electron-quick-start
│ │ ├── .gitignore
│ │ ├── LICENSE.md
│ │ ├── README.md
│ │ ├── main.js
│ │ ├── package.json
│ │ └── www
│ │ ├── css
│ │ └── style.css
│ │ ├── img
│ │ └── ionic.png
│ │ ├── index.html
│ │ ├── js
│ │ ├── app.js
│ │ ├── controllers.js
│ │ └── services.js
│ │ ├── lib
│ │ └── ionic
│ │ │ ├── css
│ │ │ ├── ionic.css
│ │ │ └── ionic.min.css
│ │ │ ├── fonts
│ │ │ ├── ionicons.eot
│ │ │ ├── ionicons.svg
│ │ │ ├── ionicons.ttf
│ │ │ └── ionicons.woff
│ │ │ ├── js
│ │ │ ├── angular-ui
│ │ │ │ ├── angular-ui-router.js
│ │ │ │ └── angular-ui-router.min.js
│ │ │ ├── angular
│ │ │ │ ├── angular-animate.js
│ │ │ │ ├── angular-animate.min.js
│ │ │ │ ├── angular-resource.js
│ │ │ │ ├── angular-resource.min.js
│ │ │ │ ├── angular-sanitize.js
│ │ │ │ ├── angular-sanitize.min.js
│ │ │ │ ├── angular.js
│ │ │ │ └── angular.min.js
│ │ │ ├── ionic-angular.js
│ │ │ ├── ionic-angular.min.js
│ │ │ ├── ionic.bundle.js
│ │ │ ├── ionic.bundle.min.js
│ │ │ ├── ionic.js
│ │ │ └── ionic.min.js
│ │ │ ├── scss
│ │ │ ├── _action-sheet.scss
│ │ │ ├── _animations.scss
│ │ │ ├── _backdrop.scss
│ │ │ ├── _badge.scss
│ │ │ ├── _bar.scss
│ │ │ ├── _button-bar.scss
│ │ │ ├── _button.scss
│ │ │ ├── _checkbox.scss
│ │ │ ├── _form.scss
│ │ │ ├── _grid.scss
│ │ │ ├── _items.scss
│ │ │ ├── _list.scss
│ │ │ ├── _loading.scss
│ │ │ ├── _menu.scss
│ │ │ ├── _mixins.scss
│ │ │ ├── _modal.scss
│ │ │ ├── _platform.scss
│ │ │ ├── _popover.scss
│ │ │ ├── _popup.scss
│ │ │ ├── _progress.scss
│ │ │ ├── _radio.scss
│ │ │ ├── _range.scss
│ │ │ ├── _refresher.scss
│ │ │ ├── _reset.scss
│ │ │ ├── _scaffolding.scss
│ │ │ ├── _select.scss
│ │ │ ├── _slide-box.scss
│ │ │ ├── _slides.scss
│ │ │ ├── _spinner.scss
│ │ │ ├── _tabs.scss
│ │ │ ├── _toggle.scss
│ │ │ ├── _transitions.scss
│ │ │ ├── _type.scss
│ │ │ ├── _util.scss
│ │ │ ├── _variables.scss
│ │ │ ├── ionic.scss
│ │ │ └── ionicons
│ │ │ │ ├── _ionicons-font.scss
│ │ │ │ ├── _ionicons-icons.scss
│ │ │ │ ├── _ionicons-variables.scss
│ │ │ │ └── ionicons.scss
│ │ │ └── version.json
│ │ └── partials
│ │ ├── entry.html
│ │ ├── home.html
│ │ └── login.html
├── common
│ └── models
│ │ ├── appuser.js
│ │ ├── appuser.json
│ │ ├── category.js
│ │ ├── category.json
│ │ ├── entry.js
│ │ └── entry.json
├── package.json
└── server
│ ├── boot
│ ├── authentication.js
│ └── routes.js
│ ├── component-config.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.json
│ ├── middleware.production.json
│ ├── model-config.json
│ ├── server.js
│ └── views
│ ├── entry.handlebars
│ ├── index.handlebars
│ └── layouts
│ └── main.handlebars
├── filetest
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .yo-rc.json
├── client
│ ├── README.md
│ ├── app.js
│ └── index.html
├── common
│ └── models
│ │ ├── attachment.js
│ │ ├── attachment.json
│ │ ├── cat.js
│ │ ├── cat.json
│ │ ├── note.js
│ │ └── note.json
├── data.db
├── files
│ └── resume
│ │ ├── avatar.jpg
│ │ ├── foo.txt
│ │ ├── goo.txt
│ │ └── windowsfield.jpg
├── notes.txt
├── package.json
└── server
│ ├── boot
│ ├── authentication.js
│ └── root.js
│ ├── component-config.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.development.json
│ ├── middleware.json
│ ├── model-config.json
│ └── server.js
├── geotest
├── .editorconfig
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .yo-rc.json
├── README.md
├── client
│ ├── README.md
│ ├── img
│ │ └── sadcat.png
│ ├── js
│ │ ├── map.js
│ │ └── near.js
│ ├── map.html
│ └── near.html
├── common
│ └── models
│ │ ├── cat.js
│ │ ├── cat.json
│ │ └── localmongo.js
├── fakedata.txt
├── memory.db
├── package.json
└── server
│ ├── boot
│ ├── authentication.js
│ └── root.js
│ ├── component-config.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.json
│ ├── middleware.production.json
│ ├── model-config.json
│ └── server.js
├── ormdemo
├── .editorconfig
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .yo-rc.json
├── README.md
├── client
│ └── README.md
├── common
│ └── models
│ │ ├── part.js
│ │ ├── part.json
│ │ ├── product.js
│ │ ├── product.json
│ │ ├── test.js
│ │ └── test.json
├── data.db
├── package.json
└── server
│ ├── boot
│ ├── authentication.js
│ ├── root.js
│ └── routes.js
│ ├── component-config.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.json
│ ├── middleware.production.json
│ ├── model-config.json
│ ├── public
│ └── css
│ │ └── styles.css
│ ├── server.js
│ └── views
│ ├── edit.handlebars
│ ├── editpart.handlebars
│ ├── index.handlebars
│ └── layouts
│ └── main.handlebars
├── simpleauthdemo
├── .editorconfig
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .yo-rc.json
├── README.md
├── client
│ ├── README.md
│ ├── index.html
│ └── js
│ │ └── app.js
├── common
│ └── models
│ │ ├── appuser.js
│ │ ├── appuser.json
│ │ ├── post.js
│ │ └── post.json
├── data.db
├── notes.txt
├── package.json
└── server
│ ├── boot
│ ├── authentication.js
│ └── root.js
│ ├── component-config.json
│ ├── config.json
│ ├── datasources.json
│ ├── middleware.development.json
│ ├── middleware.json
│ ├── model-config.json
│ └── server.js
└── superlongscroll
├── .editorconfig
├── .gitignore
├── .jshintignore
├── .jshintrc
├── .yo-rc.json
├── client
├── README.md
├── app1
│ ├── .gitignore
│ ├── .vscode
│ │ └── typings
│ │ │ └── cordova
│ │ │ └── cordova.d.ts
│ ├── app
│ │ ├── app.ts
│ │ ├── pages
│ │ │ └── home
│ │ │ │ ├── home.html
│ │ │ │ ├── home.scss
│ │ │ │ └── home.ts
│ │ ├── providers
│ │ │ └── people-service
│ │ │ │ └── people-service.ts
│ │ └── theme
│ │ │ ├── app.core.scss
│ │ │ ├── app.ios.scss
│ │ │ ├── app.md.scss
│ │ │ ├── app.variables.scss
│ │ │ └── app.wp.scss
│ ├── gulpfile.js
│ ├── hooks
│ │ ├── README.md
│ │ └── after_prepare
│ │ │ └── 010_add_platform_class.js
│ ├── ionic.config.js
│ ├── ionic.config.json
│ ├── package.json
│ ├── resources
│ │ ├── android
│ │ │ ├── icon
│ │ │ │ ├── drawable-hdpi-icon.png
│ │ │ │ ├── drawable-ldpi-icon.png
│ │ │ │ ├── drawable-mdpi-icon.png
│ │ │ │ ├── drawable-xhdpi-icon.png
│ │ │ │ ├── drawable-xxhdpi-icon.png
│ │ │ │ └── drawable-xxxhdpi-icon.png
│ │ │ └── splash
│ │ │ │ ├── drawable-land-hdpi-screen.png
│ │ │ │ ├── drawable-land-ldpi-screen.png
│ │ │ │ ├── drawable-land-mdpi-screen.png
│ │ │ │ ├── drawable-land-xhdpi-screen.png
│ │ │ │ ├── drawable-land-xxhdpi-screen.png
│ │ │ │ ├── drawable-land-xxxhdpi-screen.png
│ │ │ │ ├── drawable-port-hdpi-screen.png
│ │ │ │ ├── drawable-port-ldpi-screen.png
│ │ │ │ ├── drawable-port-mdpi-screen.png
│ │ │ │ ├── drawable-port-xhdpi-screen.png
│ │ │ │ ├── drawable-port-xxhdpi-screen.png
│ │ │ │ └── drawable-port-xxxhdpi-screen.png
│ │ ├── icon.png
│ │ ├── ios
│ │ │ ├── icon
│ │ │ │ ├── icon-40.png
│ │ │ │ ├── icon-40@2x.png
│ │ │ │ ├── icon-50.png
│ │ │ │ ├── icon-50@2x.png
│ │ │ │ ├── icon-60.png
│ │ │ │ ├── icon-60@2x.png
│ │ │ │ ├── icon-60@3x.png
│ │ │ │ ├── icon-72.png
│ │ │ │ ├── icon-72@2x.png
│ │ │ │ ├── icon-76.png
│ │ │ │ ├── icon-76@2x.png
│ │ │ │ ├── icon-small.png
│ │ │ │ ├── icon-small@2x.png
│ │ │ │ ├── icon-small@3x.png
│ │ │ │ ├── icon.png
│ │ │ │ └── icon@2x.png
│ │ │ └── splash
│ │ │ │ ├── Default-568h@2x~iphone.png
│ │ │ │ ├── Default-667h.png
│ │ │ │ ├── Default-736h.png
│ │ │ │ ├── Default-Landscape-736h.png
│ │ │ │ ├── Default-Landscape@2x~ipad.png
│ │ │ │ ├── Default-Landscape~ipad.png
│ │ │ │ ├── Default-Portrait@2x~ipad.png
│ │ │ │ ├── Default-Portrait~ipad.png
│ │ │ │ ├── Default@2x~iphone.png
│ │ │ │ └── Default~iphone.png
│ │ └── splash.png
│ ├── tsconfig.json
│ ├── typings.json
│ ├── typings
│ │ ├── browser.d.ts
│ │ ├── browser
│ │ │ └── ambient
│ │ │ │ └── es6-shim
│ │ │ │ └── index.d.ts
│ │ ├── main.d.ts
│ │ └── main
│ │ │ └── ambient
│ │ │ └── es6-shim
│ │ │ └── index.d.ts
│ └── www
│ │ └── index.html
└── simple
│ ├── app.js
│ └── index.html
├── common
└── models
│ ├── note.js
│ ├── note.json
│ ├── person.js
│ └── person.json
├── data.db
├── package.json
└── server
├── boot
└── root.js
├── component-config.json
├── config.json
├── datasources.json
├── middleware.json
├── middleware.production.json
├── model-config.json
├── server.js
└── users.json
/blog1/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/blog1/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/blog1/.jshintignore:
--------------------------------------------------------------------------------
1 | /client/
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/blog1/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "eqeqeq": true,
7 | "eqnull": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": "nofunc",
11 | "newcap": true,
12 | "nonew": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "trailing": true,
19 | "sub": true,
20 | "maxlen": 80
21 | }
22 |
--------------------------------------------------------------------------------
/blog1/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/blog1/README.md:
--------------------------------------------------------------------------------
1 | # My Application
2 |
3 | The project is generated by [LoopBack](http://loopback.io).
--------------------------------------------------------------------------------
/blog1/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/blog1/common/models/category.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Category) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/blog1/common/models/category.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "category",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "name": {
11 | "type": "string",
12 | "required": true
13 | }
14 | },
15 | "validations": [],
16 | "relations": {},
17 | "acls": [],
18 | "methods": {}
19 | }
20 |
--------------------------------------------------------------------------------
/blog1/common/models/entry.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Entry) {
2 |
3 | Entry.observe('loaded', function(ctx, next) {
4 | if(ctx && ctx.instance && ctx.instance.released) {
5 | var date = ctx.instance.published;
6 | ctx.instance.url = "/"+date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate()+"/"+ctx.instance.slug;
7 | }
8 | next();
9 | });
10 |
11 | };
12 |
--------------------------------------------------------------------------------
/blog1/common/models/entry.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "entry",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "title": {
11 | "type": "string",
12 | "required": true
13 | },
14 | "released": {
15 | "type": "boolean",
16 | "required": true
17 | },
18 | "published": {
19 | "type": "date",
20 | "required": true
21 | },
22 | "slug": {
23 | "type": "string",
24 | "required": true
25 | },
26 | "body": {
27 | "type": "string",
28 | "required": true
29 | }
30 | },
31 | "validations": [],
32 | "relations": {
33 | "categories": {
34 | "type": "hasMany",
35 | "model": "category",
36 | "foreignKey": ""
37 | }
38 | },
39 | "acls": [],
40 | "methods": {}
41 | }
42 |
--------------------------------------------------------------------------------
/blog1/common/models/test-content.js:
--------------------------------------------------------------------------------
1 | module.exports = function(TestContent) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/blog1/common/models/test-content.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "testContent",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "title": {
11 | "type": "string"
12 | },
13 | "body": {
14 | "type": "string"
15 | },
16 | "posted": {
17 | "type": "date"
18 | }
19 | },
20 | "validations": [],
21 | "relations": {},
22 | "acls": [],
23 | "methods": {}
24 | }
25 |
--------------------------------------------------------------------------------
/blog1/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blog1",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "pretest": "jshint ."
7 | },
8 | "dependencies": {
9 | "chalk": "^1.1.1",
10 | "compression": "^1.0.3",
11 | "cors": "^2.5.2",
12 | "express-handlebars": "^2.0.1",
13 | "handlebars-helper-moment": "^0.2.0",
14 | "loopback": "^2.22.0",
15 | "loopback-boot": "^2.6.5",
16 | "loopback-component-explorer": "^2.1.0",
17 | "loopback-connector-mongodb": "^1.13.2",
18 | "loopback-datasource-juggler": "^2.39.0",
19 | "moment": "^2.11.0",
20 | "serve-favicon": "^2.0.1"
21 | },
22 | "devDependencies": {
23 | "jshint": "^2.5.6"
24 | },
25 | "repository": {
26 | "type": "",
27 | "url": ""
28 | },
29 | "description": "blog1"
30 | }
31 |
--------------------------------------------------------------------------------
/blog1/server/boot/01seed.js:
--------------------------------------------------------------------------------
1 |
2 | var chalk = require('chalk');
3 |
4 | console.log(chalk.magenta('Lets seed this app!'));
5 |
6 | /*
7 | This script is based on:
8 | https://github.com/strongloop-training/coffee-time/blob/master/server/boot/create-sample-model-data.js
9 | */
10 |
11 | module.exports = function(app) {
12 |
13 | //sample data
14 | var data = [
15 | {
16 | title:'Content One',
17 | body:'Body One',
18 | posted:new Date()
19 | },
20 | {
21 | title:'Content Two',
22 | body:"Body Two",
23 | posted:new Date()
24 | },
25 | {
26 | title:'Content Three',
27 | body:'Body Three',
28 | posted:new Date()
29 | }
30 | ];
31 |
32 | app.models.TestContent.create(data, function(err, records) {
33 | if (err) { return console.log(chalk.red(err.message)); }
34 | console.log(chalk.magenta('Done seeding data, '+records.length+' records created.'));
35 | });
36 |
37 |
38 | }
--------------------------------------------------------------------------------
/blog1/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | module.exports = function enableAuthentication(server) {
2 | // enable authentication
3 | server.enableAuth();
4 | };
5 |
--------------------------------------------------------------------------------
/blog1/server/boot/routes.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 | // Install a `/` route that returns server status
3 | //var router = server.loopback.Router();
4 | //router.get('/', server.loopback.status());
5 | //server.use(router);
6 |
7 | app.get('/', function(req, res) {
8 | console.log('getting blog entries');
9 | app.models.entry.find({where:{released:true},order:'published desc'}).then(function(entries) {
10 | res.render('index',{entries:entries});
11 | });
12 | });
13 |
14 | app.get('/:year/:month/:day/:slug', function(req, res) {
15 | console.log('do blog entry');
16 | console.dir(req.params);
17 | //create an upper and lower date range
18 | var lowerDate = new Date(req.params.year, req.params.month-1, req.params.day);
19 | var upperDate = new Date(lowerDate);
20 | upperDate.setDate(upperDate.getDate()+1);
21 | app.models.entry.findOne({where:{
22 | released:true,
23 | slug:req.params.slug,
24 | published:{between:[lowerDate,upperDate]}
25 | },limit:1}).then(function(entry) {
26 | //first - did we get any?
27 | if(!entry) {
28 | res.redirect('/');
29 | }
30 | res.render('entry', {entry:entry});
31 | });
32 | });
33 | };
34 |
--------------------------------------------------------------------------------
/blog1/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/blog1/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": {
7 | "enableHttpContext": false
8 | },
9 | "rest": {
10 | "normalizeHttpPath": false,
11 | "xml": false
12 | },
13 | "json": {
14 | "strict": false,
15 | "limit": "100kb"
16 | },
17 | "urlencoded": {
18 | "extended": true,
19 | "limit": "100kb"
20 | },
21 | "cors": false,
22 | "errorHandler": {
23 | "disableStackTrace": false
24 | }
25 | },
26 | "legacyExplorer": false
27 | }
28 |
--------------------------------------------------------------------------------
/blog1/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "memory"
5 | },
6 | "blogdata": {
7 | "host": "localhost",
8 | "port": 27017,
9 | "database": "blogdata",
10 | "name": "blogdata",
11 | "connector": "mongodb"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/blog1/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | }
14 | },
15 | "session": {},
16 | "auth": {},
17 | "parse": {},
18 | "routes": {
19 | "loopback#rest": {
20 | "paths": [
21 | "${restApiRoot}"
22 | ]
23 | }
24 | },
25 | "files": {},
26 | "final": {
27 | "loopback#urlNotFound": {}
28 | },
29 | "final:after": {
30 | "loopback#errorHandler": {}
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/blog1/server/middleware.production.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "loopback#errorHandler": {
4 | "params": {
5 | "includeStack": false
6 | }
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/blog1/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "db"
18 | },
19 | "AccessToken": {
20 | "dataSource": "db",
21 | "public": false
22 | },
23 | "ACL": {
24 | "dataSource": "db",
25 | "public": false
26 | },
27 | "RoleMapping": {
28 | "dataSource": "db",
29 | "public": false
30 | },
31 | "Role": {
32 | "dataSource": "db",
33 | "public": false
34 | },
35 | "entry": {
36 | "dataSource": "blogdata",
37 | "public": true,
38 | "$promise": {},
39 | "$resolved": true
40 | },
41 | "category": {
42 | "dataSource": "blogdata",
43 | "public": true,
44 | "$promise": {},
45 | "$resolved": true
46 | },
47 | "testContent": {
48 | "dataSource": "db",
49 | "public": true,
50 | "$promise": {},
51 | "$resolved": true
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/blog1/server/server.js:
--------------------------------------------------------------------------------
1 | var loopback = require('loopback');
2 | var boot = require('loopback-boot');
3 |
4 | var app = module.exports = loopback();
5 | var exphbs = require('express-handlebars');
6 |
7 | var hbs = exphbs.create({
8 | defaultLayout:'main',
9 | helpers:require('handlebars-helper-moment')()
10 | });
11 |
12 | app.engine('handlebars', hbs.engine);
13 | app.set('view engine', 'handlebars');
14 |
15 | app.start = function() {
16 | // start the web server
17 | return app.listen(function() {
18 | app.emit('started');
19 | var baseUrl = app.get('url').replace(/\/$/, '');
20 | console.log('Web server listening at: %s', baseUrl);
21 | if (app.get('loopback-component-explorer')) {
22 | var explorerPath = app.get('loopback-component-explorer').mountPath;
23 | console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
24 | }
25 | });
26 | };
27 |
28 | // Bootstrap the application, configure models, datasources and middleware.
29 | // Sub-apps like REST API are mounted via boot scripts.
30 | boot(app, __dirname, function(err) {
31 | if (err) throw err;
32 |
33 | // start the server if `$ node server.js`
34 | if (require.main === module)
35 | app.start();
36 | });
37 |
38 |
--------------------------------------------------------------------------------
/blog1/server/views/entry.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
{{entry.title}}
3 |
4 | Published: {{moment published format="MMMM D, YYYY h:mm A"}}
5 |
6 |
7 | {{{entry.body}}}
--------------------------------------------------------------------------------
/blog1/server/views/index.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 | Entries
4 |
5 | {{#each entries}}
6 |
7 | {{title}}
8 | Published: {{moment published format="MMMM D, YYYY h:mm A"}}
9 |
10 |
11 | {{/each}}
--------------------------------------------------------------------------------
/blog1/server/views/layouts/main.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
50 |
59 |
60 |
61 |
62 |
63 |
64 |
{{{body}}}
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/blog2/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/blog2/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/blog2/.jshintignore:
--------------------------------------------------------------------------------
1 | /client/
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/blog2/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "eqeqeq": true,
7 | "eqnull": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": "nofunc",
11 | "newcap": true,
12 | "nonew": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "trailing": true,
19 | "sub": true,
20 | "maxlen": 80
21 | }
22 |
--------------------------------------------------------------------------------
/blog2/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/blog2/README.md:
--------------------------------------------------------------------------------
1 | # My Application
2 |
3 | The project is generated by [LoopBack](http://loopback.io).
--------------------------------------------------------------------------------
/blog2/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/README.md:
--------------------------------------------------------------------------------
1 | # electron-quick-start
2 |
3 | **Clone and run for a quick way to see an Electron in action.**
4 |
5 | This is a minimal Electron application based on the [Quick Start Guide](http://electron.atom.io/docs/latest/tutorial/quick-start) within the Electron documentation.
6 |
7 | A basic Electron application needs just these files:
8 |
9 | - `index.html` - A web page to render.
10 | - `main.js` - Starts the app and creates a browser window to render HTML.
11 | - `package.json` - Points to the app's main file and lists its details and dependencies.
12 |
13 | You can learn more about each of these components within the [Quick Start Guide](http://electron.atom.io/docs/latest/tutorial/quick-start).
14 |
15 | ## To Use
16 |
17 | To clone and run this repository you'll need [Git](https://git-scm.com) and [Node.js](https://nodejs.org/en/download/) (which comes with [npm](http://npmjs.com)) installed on your computer. From your command line:
18 |
19 | ```bash
20 | # Clone this repository
21 | git clone https://github.com/atom/electron-quick-start
22 | # Go into the repository
23 | cd electron-quick-start
24 | # Install dependencies and run the app
25 | npm install && npm start
26 | ```
27 |
28 | Learn more about Electron and its API in the [documentation](http://electron.atom.io/docs/latest).
29 |
30 | #### License [CC0 (Public Domain)](LICENSE.md)
31 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const electron = require('electron');
4 | // Module to control application life.
5 | const app = electron.app;
6 | // Module to create native browser window.
7 | const BrowserWindow = electron.BrowserWindow;
8 |
9 | // Keep a global reference of the window object, if you don't, the window will
10 | // be closed automatically when the JavaScript object is garbage collected.
11 | let mainWindow;
12 |
13 | function createWindow () {
14 | // Create the browser window.
15 | mainWindow = new BrowserWindow({width: 800, height: 600});
16 |
17 | // and load the index.html of the app.
18 | mainWindow.loadURL('file://' + __dirname + '/www/index.html');
19 |
20 | // Emitted when the window is closed.
21 | mainWindow.on('closed', function() {
22 | // Dereference the window object, usually you would store windows
23 | // in an array if your app supports multi windows, this is the time
24 | // when you should delete the corresponding element.
25 | mainWindow = null;
26 | });
27 | }
28 |
29 | // This method will be called when Electron has finished
30 | // initialization and is ready to create browser windows.
31 | app.on('ready', createWindow);
32 |
33 | // Quit when all windows are closed.
34 | app.on('window-all-closed', function () {
35 | // On OS X it is common for applications and their menu bar
36 | // to stay active until the user quits explicitly with Cmd + Q
37 | if (process.platform !== 'darwin') {
38 | app.quit();
39 | }
40 | });
41 |
42 | app.on('activate', function () {
43 | // On OS X it's common to re-create a window in the app when the
44 | // dock icon is clicked and there are no other windows open.
45 | if (mainWindow === null) {
46 | createWindow();
47 | }
48 | });
49 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "electron-quick-start",
3 | "version": "1.0.0",
4 | "description": "A minimal Electron application",
5 | "main": "main.js",
6 | "scripts": {
7 | "start": "electron main.js"
8 | },
9 | "repository": {
10 | "type": "git",
11 | "url": "git+https://github.com/atom/electron-quick-start.git"
12 | },
13 | "keywords": [
14 | "Electron",
15 | "quick",
16 | "start",
17 | "tutorial"
18 | ],
19 | "author": "GitHub",
20 | "license": "CC0-1.0",
21 | "bugs": {
22 | "url": "https://github.com/atom/electron-quick-start/issues"
23 | },
24 | "homepage": "https://github.com/atom/electron-quick-start#readme",
25 | "devDependencies": {
26 | "electron-prebuilt": "^0.36.0"
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/css/style.css:
--------------------------------------------------------------------------------
1 | /* Empty. Add your own CSS if you like */
2 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/img/ionic.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/blog2/client/electron-quick-start/www/img/ionic.png
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Blog Editor
7 |
8 |
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/js/app.js:
--------------------------------------------------------------------------------
1 | // Ionic Starter App
2 |
3 | // angular.module is a global place for creating, registering and retrieving Angular modules
4 | // 'starter' is the name of this angular module example (also set in a attribute in index.html)
5 | // the 2nd parameter is an array of 'requires'
6 | angular.module('starter', ['ionic','starter.controllers','starter.services','ngResource'])
7 |
8 | .config(function($stateProvider,$urlRouterProvider) {
9 |
10 | $stateProvider
11 | .state('root', {
12 | url:'/root',
13 | abstract:true,
14 | controller:'rootCtrl',
15 | template:''
16 | })
17 | .state('root.Login', {
18 | url:'/login',
19 | controller:'loginCtrl',
20 | templateUrl:'partials/login.html'
21 | })
22 | .state('root.Home', {
23 | url:'/home',
24 | controller:'homeCtrl',
25 | templateUrl:'partials/home.html'
26 | })
27 | .state('root.EditEntry', {
28 | url:'/editentry',
29 | controller:'entryCtrl',
30 | templateUrl:'partials/entry.html'
31 | });
32 |
33 | $urlRouterProvider.otherwise('/root/login');
34 |
35 | })
36 | .run(function($ionicPlatform) {
37 |
38 |
39 | })
40 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/js/controllers.js:
--------------------------------------------------------------------------------
1 | angular.module('starter.controllers', [])
2 |
3 | .controller('rootCtrl', function($scope) {
4 |
5 | $scope.$on('$ionicView.afterEnter', function(ev, data) {
6 | ev.stopPropagation();
7 | });
8 |
9 | })
10 |
11 | .controller('loginCtrl', ['$scope', '$rootScope', 'userService', '$state', '$http',
12 | function($scope, $rootScope, userService, $state, $http) {
13 |
14 | $scope.user = {username:'raymondcamden@gmail.com',password:'password'};
15 |
16 | $scope.doLogin = function() {
17 | if($scope.user.username === '' || $scope.user.password === '') {
18 | return;
19 | }
20 | userService.login({email:$scope.user.username,password:$scope.user.password},function(res) {
21 | $rootScope.authToken = res.id; // don't really need to keep it
22 | $http.defaults.headers.common['Authorization'] = $rootScope.authToken;
23 | $state.go('root.Home');
24 | },function(e) {
25 | //for right now - generic error
26 | alert('Login Failed');
27 | });
28 | };
29 |
30 | }])
31 |
32 | .controller('homeCtrl', ['$scope', '$rootScope', 'entryService', '$state',
33 | function($scope, $rootScope, entryService, state) {
34 |
35 | $scope.$on('$ionicView.enter', function() {
36 | entryService.query({"filter[order]":"published desc"},function(res) {
37 | $scope.entries = res;
38 | }, function(e) {
39 | console.log('bad '+JSON.stringify(e));
40 | });
41 | });
42 |
43 | }])
44 | .controller('entryCtrl', ['$scope', '$rootScope', 'entryService', '$state',
45 | function($scope, $rootScope, entryService, $state) {
46 |
47 | $scope.entry = {title:"",body:""};
48 |
49 | $scope.doSave = function() {
50 | var postedDate = new Date();
51 |
52 | var newEntry = new entryService();
53 | newEntry.title = $scope.entry.title;
54 | newEntry.body = $scope.entry.body;
55 | newEntry.released = true;
56 | newEntry.published = new Date();
57 | //not perfect...
58 | newEntry.slug = newEntry.title.replace(/ /g,'-');
59 | newEntry.$save();
60 | $state.go('root.Home');
61 |
62 | }
63 |
64 | }]);
65 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/js/services.js:
--------------------------------------------------------------------------------
1 | angular.module('starter.services', [])
2 | .factory('userService', function($q,$resource) {
3 |
4 | return $resource('http://localhost:3000/api/appusers/:id',{},
5 | {
6 | 'login':{
7 | 'method':'POST',
8 | 'url':'http://localhost:3000/api/appusers/login'
9 | }
10 | });
11 |
12 | })
13 | .factory('entryService', function($q,$resource) {
14 |
15 | return $resource('http://localhost:3000/api/entries/:id');
16 |
17 | });
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/fonts/ionicons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/blog2/client/electron-quick-start/www/lib/ionic/fonts/ionicons.eot
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/fonts/ionicons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/blog2/client/electron-quick-start/www/lib/ionic/fonts/ionicons.ttf
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/fonts/ionicons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/blog2/client/electron-quick-start/www/lib/ionic/fonts/ionicons.woff
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/js/angular/angular-resource.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | AngularJS v1.4.3
3 | (c) 2010-2015 Google, Inc. http://angularjs.org
4 | License: MIT
5 | */
6 | (function(I,d,B){'use strict';function D(f,q){q=q||{};d.forEach(q,function(d,h){delete q[h]});for(var h in f)!f.hasOwnProperty(h)||"$"===h.charAt(0)&&"$"===h.charAt(1)||(q[h]=f[h]);return q}var x=d.$$minErr("$resource"),C=/^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;d.module("ngResource",["ng"]).provider("$resource",function(){var f=this;this.defaults={stripTrailingSlashes:!0,actions:{get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}}};
7 | this.$get=["$http","$q",function(q,h){function u(d,g){this.template=d;this.defaults=s({},f.defaults,g);this.urlParams={}}function w(y,g,l,m){function c(b,k){var c={};k=s({},g,k);r(k,function(a,k){v(a)&&(a=a());var d;if(a&&a.charAt&&"@"==a.charAt(0)){d=b;var e=a.substr(1);if(null==e||""===e||"hasOwnProperty"===e||!C.test("."+e))throw x("badmember",e);for(var e=e.split("."),n=0,g=e.length;n .ng-enter {
10 | @include transition(all cubic-bezier(.1, .7, .1, 1) 400ms);
11 | }
12 | .slide-in-up.ng-enter-active,
13 | .slide-in-up > .ng-enter-active {
14 | @include translate3d(0, 0, 0);
15 | }
16 |
17 | .slide-in-up.ng-leave,
18 | .slide-in-up > .ng-leave {
19 | @include transition(all ease-in-out 250ms);
20 | }
21 |
22 |
23 | // Scale Out
24 | // Scale from hero (1 in this case) to zero
25 | // -------------------------------
26 |
27 | @-webkit-keyframes scaleOut {
28 | from { -webkit-transform: scale(1); opacity: 1; }
29 | to { -webkit-transform: scale(0.8); opacity: 0; }
30 | }
31 | @keyframes scaleOut {
32 | from { transform: scale(1); opacity: 1; }
33 | to { transform: scale(0.8); opacity: 0; }
34 | }
35 |
36 |
37 | // Super Scale In
38 | // Scale from super (1.x) to duper (1 in this case)
39 | // -------------------------------
40 |
41 | @-webkit-keyframes superScaleIn {
42 | from { -webkit-transform: scale(1.2); opacity: 0; }
43 | to { -webkit-transform: scale(1); opacity: 1 }
44 | }
45 | @keyframes superScaleIn {
46 | from { transform: scale(1.2); opacity: 0; }
47 | to { transform: scale(1); opacity: 1; }
48 | }
49 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_backdrop.scss:
--------------------------------------------------------------------------------
1 |
2 | .backdrop {
3 | position: fixed;
4 | top: 0;
5 | left: 0;
6 | z-index: $z-index-backdrop;
7 |
8 | width: 100%;
9 | height: 100%;
10 |
11 | background-color: $loading-backdrop-bg-color;
12 |
13 | visibility: hidden;
14 | opacity: 0;
15 |
16 | &.visible {
17 | visibility: visible;
18 | }
19 | &.active {
20 | opacity: 1;
21 | }
22 |
23 | @include transition($loading-backdrop-fadein-duration opacity linear);
24 | }
25 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_badge.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Badges
4 | * --------------------------------------------------
5 | */
6 |
7 | .badge {
8 | @include badge-style($badge-default-bg, $badge-default-text);
9 | z-index: $z-index-badge;
10 | display: inline-block;
11 | padding: 3px 8px;
12 | min-width: 10px;
13 | border-radius: $badge-border-radius;
14 | vertical-align: baseline;
15 | text-align: center;
16 | white-space: nowrap;
17 | font-weight: $badge-font-weight;
18 | font-size: $badge-font-size;
19 | line-height: $badge-line-height;
20 |
21 | &:empty {
22 | display: none;
23 | }
24 | }
25 |
26 | //Be sure to override specificity of rule that 'badge color matches tab color by default'
27 | .tabs .tab-item .badge,
28 | .badge {
29 | &.badge-light {
30 | @include badge-style($badge-light-bg, $badge-light-text);
31 | }
32 | &.badge-stable {
33 | @include badge-style($badge-stable-bg, $badge-stable-text);
34 | }
35 | &.badge-positive {
36 | @include badge-style($badge-positive-bg, $badge-positive-text);
37 | }
38 | &.badge-calm {
39 | @include badge-style($badge-calm-bg, $badge-calm-text);
40 | }
41 | &.badge-assertive {
42 | @include badge-style($badge-assertive-bg, $badge-assertive-text);
43 | }
44 | &.badge-balanced {
45 | @include badge-style($badge-balanced-bg, $badge-balanced-text);
46 | }
47 | &.badge-energized {
48 | @include badge-style($badge-energized-bg, $badge-energized-text);
49 | }
50 | &.badge-royal {
51 | @include badge-style($badge-royal-bg, $badge-royal-text);
52 | }
53 | &.badge-dark {
54 | @include badge-style($badge-dark-bg, $badge-dark-text);
55 | }
56 | }
57 |
58 | // Quick fix for labels/badges in buttons
59 | .button .badge {
60 | position: relative;
61 | top: -1px;
62 | }
63 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_button-bar.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Button Bar
4 | * --------------------------------------------------
5 | */
6 |
7 | .button-bar {
8 | @include display-flex();
9 | @include flex(1);
10 | width: 100%;
11 |
12 | &.button-bar-inline {
13 | display: block;
14 | width: auto;
15 |
16 | @include clearfix();
17 |
18 | > .button {
19 | width: auto;
20 | display: inline-block;
21 | float: left;
22 | }
23 | }
24 | }
25 |
26 | .button-bar > .button {
27 | @include flex(1);
28 | display: block;
29 |
30 | overflow: hidden;
31 |
32 | padding: 0 16px;
33 |
34 | width: 0;
35 |
36 | border-width: 1px 0px 1px 1px;
37 | border-radius: 0;
38 | text-align: center;
39 | text-overflow: ellipsis;
40 | white-space: nowrap;
41 |
42 | &:before,
43 | .icon:before {
44 | line-height: 44px;
45 | }
46 |
47 | &:first-child {
48 | border-radius: $button-border-radius 0px 0px $button-border-radius;
49 | }
50 | &:last-child {
51 | border-right-width: 1px;
52 | border-radius: 0px $button-border-radius $button-border-radius 0px;
53 | }
54 | &:only-child {
55 | border-radius: $button-border-radius;
56 | }
57 | }
58 |
59 | .button-bar > .button-small {
60 | &:before,
61 | .icon:before {
62 | line-height: 28px;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_grid.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Grid
3 | * --------------------------------------------------
4 | * Using flexbox for the grid, inspired by Philip Walton:
5 | * http://philipwalton.github.io/solved-by-flexbox/demos/grids/
6 | * By default each .col within a .row will evenly take up
7 | * available width, and the height of each .col with take
8 | * up the height of the tallest .col in the same .row.
9 | */
10 |
11 | .row {
12 | @include display-flex();
13 | padding: ($grid-padding-width / 2);
14 | width: 100%;
15 | }
16 |
17 | .row-wrap {
18 | @include flex-wrap(wrap);
19 | }
20 |
21 | .row-no-padding {
22 | padding: 0;
23 |
24 | > .col {
25 | padding: 0;
26 | }
27 | }
28 |
29 | .row + .row {
30 | margin-top: ($grid-padding-width / 2) * -1;
31 | padding-top: 0;
32 | }
33 |
34 | .col {
35 | @include flex(1);
36 | display: block;
37 | padding: ($grid-padding-width / 2);
38 | width: 100%;
39 | }
40 |
41 |
42 | /* Vertically Align Columns */
43 | /* .row-* vertically aligns every .col in the .row */
44 | .row-top {
45 | @include align-items(flex-start);
46 | }
47 | .row-bottom {
48 | @include align-items(flex-end);
49 | }
50 | .row-center {
51 | @include align-items(center);
52 | }
53 | .row-stretch {
54 | @include align-items(stretch);
55 | }
56 | .row-baseline {
57 | @include align-items(baseline);
58 | }
59 |
60 | /* .col-* vertically aligns an individual .col */
61 | .col-top {
62 | @include align-self(flex-start);
63 | }
64 | .col-bottom {
65 | @include align-self(flex-end);
66 | }
67 | .col-center {
68 | @include align-self(center);
69 | }
70 |
71 | /* Column Offsets */
72 | .col-offset-10 {
73 | margin-left: 10%;
74 | }
75 | .col-offset-20 {
76 | margin-left: 20%;
77 | }
78 | .col-offset-25 {
79 | margin-left: 25%;
80 | }
81 | .col-offset-33, .col-offset-34 {
82 | margin-left: 33.3333%;
83 | }
84 | .col-offset-50 {
85 | margin-left: 50%;
86 | }
87 | .col-offset-66, .col-offset-67 {
88 | margin-left: 66.6666%;
89 | }
90 | .col-offset-75 {
91 | margin-left: 75%;
92 | }
93 | .col-offset-80 {
94 | margin-left: 80%;
95 | }
96 | .col-offset-90 {
97 | margin-left: 90%;
98 | }
99 |
100 |
101 | /* Explicit Column Percent Sizes */
102 | /* By default each grid column will evenly distribute */
103 | /* across the grid. However, you can specify individual */
104 | /* columns to take up a certain size of the available area */
105 | .col-10 {
106 | @include flex(0, 0, 10%);
107 | max-width: 10%;
108 | }
109 | .col-20 {
110 | @include flex(0, 0, 20%);
111 | max-width: 20%;
112 | }
113 | .col-25 {
114 | @include flex(0, 0, 25%);
115 | max-width: 25%;
116 | }
117 | .col-33, .col-34 {
118 | @include flex(0, 0, 33.3333%);
119 | max-width: 33.3333%;
120 | }
121 | .col-40 {
122 | @include flex(0, 0, 40%);
123 | max-width: 40%;
124 | }
125 | .col-50 {
126 | @include flex(0, 0, 50%);
127 | max-width: 50%;
128 | }
129 | .col-60 {
130 | @include flex(0, 0, 60%);
131 | max-width: 60%;
132 | }
133 | .col-66, .col-67 {
134 | @include flex(0, 0, 66.6666%);
135 | max-width: 66.6666%;
136 | }
137 | .col-75 {
138 | @include flex(0, 0, 75%);
139 | max-width: 75%;
140 | }
141 | .col-80 {
142 | @include flex(0, 0, 80%);
143 | max-width: 80%;
144 | }
145 | .col-90 {
146 | @include flex(0, 0, 90%);
147 | max-width: 90%;
148 | }
149 |
150 |
151 | /* Responsive Grid Classes */
152 | /* Adding a class of responsive-X to a row */
153 | /* will trigger the flex-direction to */
154 | /* change to column and add some margin */
155 | /* to any columns in the row for clearity */
156 |
157 | @include responsive-grid-break('.responsive-sm', $grid-responsive-sm-break);
158 | @include responsive-grid-break('.responsive-md', $grid-responsive-md-break);
159 | @include responsive-grid-break('.responsive-lg', $grid-responsive-lg-break);
160 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_list.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Lists
4 | * --------------------------------------------------
5 | */
6 |
7 | .list {
8 | position: relative;
9 | padding-top: $item-border-width;
10 | padding-bottom: $item-border-width;
11 | padding-left: 0; // reset padding because ul and ol
12 | margin-bottom: 20px;
13 | }
14 | .list:last-child {
15 | margin-bottom: 0px;
16 | &.card{
17 | margin-bottom:40px;
18 | }
19 | }
20 |
21 |
22 | /**
23 | * List Header
24 | * --------------------------------------------------
25 | */
26 |
27 | .list-header {
28 | margin-top: $list-header-margin-top;
29 | padding: $list-header-padding;
30 | background-color: $list-header-bg;
31 | color: $list-header-color;
32 | font-weight: bold;
33 | }
34 |
35 | // when its a card make sure it doesn't duplicate top and bottom borders
36 | .card.list .list-item {
37 | padding-right: 1px;
38 | padding-left: 1px;
39 | }
40 |
41 |
42 | /**
43 | * Cards and Inset Lists
44 | * --------------------------------------------------
45 | * A card and list-inset are close to the same thing, except a card as a box shadow.
46 | */
47 |
48 | .card,
49 | .list-inset {
50 | overflow: hidden;
51 | margin: ($content-padding * 2) $content-padding;
52 | border-radius: $card-border-radius;
53 | background-color: $card-body-bg;
54 | }
55 |
56 | .card {
57 | padding-top: $item-border-width;
58 | padding-bottom: $item-border-width;
59 | box-shadow: $card-box-shadow;
60 |
61 | .item {
62 | border-left: 0;
63 | border-right: 0;
64 | }
65 | .item:first-child {
66 | border-top: 0;
67 | }
68 | .item:last-child {
69 | border-bottom: 0;
70 | }
71 | }
72 |
73 | .padding {
74 | .card, .list-inset {
75 | margin-left: 0;
76 | margin-right: 0;
77 | }
78 | }
79 |
80 | .card .item,
81 | .list-inset .item,
82 | .padding > .list .item
83 | {
84 | &:first-child {
85 | border-top-left-radius: $card-border-radius;
86 | border-top-right-radius: $card-border-radius;
87 |
88 | .item-content {
89 | border-top-left-radius: $card-border-radius;
90 | border-top-right-radius: $card-border-radius;
91 | }
92 | }
93 | &:last-child {
94 | border-bottom-right-radius: $card-border-radius;
95 | border-bottom-left-radius: $card-border-radius;
96 |
97 | .item-content {
98 | border-bottom-right-radius: $card-border-radius;
99 | border-bottom-left-radius: $card-border-radius;
100 | }
101 | }
102 | }
103 |
104 | .card .item:last-child,
105 | .list-inset .item:last-child {
106 | margin-bottom: $item-border-width * -1;
107 | }
108 |
109 | .card .item,
110 | .list-inset .item,
111 | .padding > .list .item,
112 | .padding-horizontal > .list .item {
113 | margin-right: 0;
114 | margin-left: 0;
115 |
116 | &.item-input input {
117 | padding-right: 44px;
118 | }
119 | }
120 | .padding-left > .list .item {
121 | margin-left: 0;
122 | }
123 | .padding-right > .list .item {
124 | margin-right: 0;
125 | }
126 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_loading.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Loading
4 | * --------------------------------------------------
5 | */
6 |
7 | .loading-container {
8 | position: absolute;
9 | left: 0;
10 | top: 0;
11 | right: 0;
12 | bottom: 0;
13 |
14 | z-index: $z-index-loading;
15 |
16 | @include display-flex();
17 | @include justify-content(center);
18 | @include align-items(center);
19 |
20 | @include transition(0.2s opacity linear);
21 | visibility: hidden;
22 | opacity: 0;
23 |
24 | &:not(.visible) .icon,
25 | &:not(.visible) .spinner{
26 | display: none;
27 | }
28 | &.visible {
29 | visibility: visible;
30 | }
31 | &.active {
32 | opacity: 1;
33 | }
34 |
35 | .loading {
36 | padding: $loading-padding;
37 |
38 | border-radius: $loading-border-radius;
39 | background-color: $loading-bg-color;
40 |
41 | color: $loading-text-color;
42 |
43 | text-align: center;
44 | text-overflow: ellipsis;
45 | font-size: $loading-font-size;
46 |
47 | h1, h2, h3, h4, h5, h6 {
48 | color: $loading-text-color;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_menu.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Menus
4 | * --------------------------------------------------
5 | * Side panel structure
6 | */
7 |
8 | .menu {
9 | position: absolute;
10 | top: 0;
11 | bottom: 0;
12 | z-index: $z-index-menu;
13 | overflow: hidden;
14 |
15 | min-height: 100%;
16 | max-height: 100%;
17 | width: $menu-width;
18 |
19 | background-color: $menu-bg;
20 |
21 | .scroll-content {
22 | z-index: $z-index-menu-scroll-content;
23 | }
24 |
25 | .bar-header {
26 | z-index: $z-index-menu-bar-header;
27 | }
28 | }
29 |
30 | .menu-content {
31 | @include transform(none);
32 | box-shadow: $menu-side-shadow;
33 | }
34 |
35 | .menu-open .menu-content .pane,
36 | .menu-open .menu-content .scroll-content {
37 | pointer-events: none;
38 | }
39 | .menu-open .menu-content .scroll-content .scroll {
40 | pointer-events: none;
41 | }
42 | .menu-open .menu-content .scroll-content:not(.overflow-scroll) {
43 | overflow: hidden;
44 | }
45 |
46 | .grade-b .menu-content,
47 | .grade-c .menu-content {
48 | @include box-sizing(content-box);
49 | right: -1px;
50 | left: -1px;
51 | border-right: 1px solid #ccc;
52 | border-left: 1px solid #ccc;
53 | box-shadow: none;
54 | }
55 |
56 | .menu-left {
57 | left: 0;
58 | }
59 |
60 | .menu-right {
61 | right: 0;
62 | }
63 |
64 | .aside-open.aside-resizing .menu-right {
65 | display: none;
66 | }
67 |
68 | .menu-animated {
69 | @include transition-transform($menu-animation-speed ease);
70 | }
71 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_modal.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Modals
4 | * --------------------------------------------------
5 | * Modals are independent windows that slide in from off-screen.
6 | */
7 |
8 | .modal-backdrop,
9 | .modal-backdrop-bg {
10 | position: fixed;
11 | top: 0;
12 | left: 0;
13 | z-index: $z-index-modal;
14 | width: 100%;
15 | height: 100%;
16 | }
17 |
18 | .modal-backdrop-bg {
19 | pointer-events: none;
20 | }
21 |
22 | .modal {
23 | display: block;
24 | position: absolute;
25 | top: 0;
26 | z-index: $z-index-modal;
27 | overflow: hidden;
28 | min-height: 100%;
29 | width: 100%;
30 | background-color: $modal-bg-color;
31 | }
32 |
33 | @media (min-width: $modal-inset-mode-break-point) {
34 | // inset mode is when the modal doesn't fill the entire
35 | // display but instead is centered within a large display
36 | .modal {
37 | top: $modal-inset-mode-top;
38 | right: $modal-inset-mode-right;
39 | bottom: $modal-inset-mode-bottom;
40 | left: $modal-inset-mode-left;
41 | min-height: $modal-inset-mode-min-height;
42 | width: (100% - $modal-inset-mode-left - $modal-inset-mode-right);
43 | }
44 |
45 | .modal.ng-leave-active {
46 | bottom: 0;
47 | }
48 |
49 | // remove ios header padding from inset header
50 | .platform-ios.platform-cordova .modal-wrapper .modal {
51 | .bar-header:not(.bar-subheader) {
52 | height: $bar-height;
53 | > * {
54 | margin-top: 0;
55 | }
56 | }
57 | .tabs-top > .tabs,
58 | .tabs.tabs-top {
59 | top: $bar-height;
60 | }
61 | .has-header,
62 | .bar-subheader {
63 | top: $bar-height;
64 | }
65 | .has-subheader {
66 | top: $bar-height + $bar-subheader-height;
67 | }
68 | .has-header.has-tabs-top {
69 | top: $bar-height + $tabs-height;
70 | }
71 | .has-header.has-subheader.has-tabs-top {
72 | top: $bar-height + $bar-subheader-height + $tabs-height;
73 | }
74 | }
75 |
76 | .modal-backdrop-bg {
77 | @include transition(opacity 300ms ease-in-out);
78 | background-color: $modal-backdrop-bg-active;
79 | opacity: 0;
80 | }
81 |
82 | .active .modal-backdrop-bg {
83 | opacity: 0.5;
84 | }
85 | }
86 |
87 | // disable clicks on all but the modal
88 | .modal-open {
89 | pointer-events: none;
90 |
91 | .modal,
92 | .modal-backdrop {
93 | pointer-events: auto;
94 | }
95 | // prevent clicks on modal when loading overlay is active though
96 | &.loading-active {
97 | .modal,
98 | .modal-backdrop {
99 | pointer-events: none;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_platform.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Platform
4 | * --------------------------------------------------
5 | * Platform specific tweaks
6 | */
7 |
8 | .platform-ios.platform-cordova {
9 | // iOS has a status bar which sits on top of the header.
10 | // Bump down everything to make room for it. However, if
11 | // if its in Cordova, and set to fullscreen, then disregard the bump.
12 | &:not(.fullscreen) {
13 | .bar-header:not(.bar-subheader) {
14 | height: $bar-height + $ios-statusbar-height;
15 |
16 | &.item-input-inset .item-input-wrapper {
17 | margin-top: 19px !important;
18 | }
19 |
20 | > * {
21 | margin-top: $ios-statusbar-height;
22 | }
23 | }
24 | .tabs-top > .tabs,
25 | .tabs.tabs-top {
26 | top: $bar-height + $ios-statusbar-height;
27 | }
28 |
29 | .has-header,
30 | .bar-subheader {
31 | top: $bar-height + $ios-statusbar-height;
32 | }
33 | .has-subheader {
34 | top: $bar-height + $bar-subheader-height + $ios-statusbar-height;
35 | }
36 | .has-header.has-tabs-top {
37 | top: $bar-height + $tabs-height + $ios-statusbar-height;
38 | }
39 | .has-header.has-subheader.has-tabs-top {
40 | top: $bar-height + $bar-subheader-height + $tabs-height + $ios-statusbar-height;
41 | }
42 | }
43 | .popover{
44 | .bar-header:not(.bar-subheader) {
45 | height: $bar-height;
46 | &.item-input-inset .item-input-wrapper {
47 | margin-top: -1px;
48 | }
49 | > * {
50 | margin-top: 0;
51 | }
52 | }
53 | .has-header,
54 | .bar-subheader {
55 | top: $bar-height;
56 | }
57 | .has-subheader {
58 | top: $bar-height + $bar-subheader-height;
59 | }
60 | }
61 | &.status-bar-hide {
62 | // Cordova doesn't adjust the body height correctly, this makes up for it
63 | margin-bottom: 20px;
64 | }
65 | }
66 |
67 | @media (orientation:landscape) {
68 | .platform-ios.platform-browser.platform-ipad {
69 | position: fixed; // required for iPad 7 Safari
70 | }
71 | }
72 |
73 | .platform-c:not(.enable-transitions) * {
74 | // disable transitions on grade-c devices (Android 2)
75 | -webkit-transition: none !important;
76 | transition: none !important;
77 | }
78 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_popover.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Popovers
4 | * --------------------------------------------------
5 | * Popovers are independent views which float over content
6 | */
7 |
8 | .popover-backdrop {
9 | position: fixed;
10 | top: 0;
11 | left: 0;
12 | z-index: $z-index-popover;
13 | width: 100%;
14 | height: 100%;
15 | background-color: $popover-backdrop-bg-inactive;
16 |
17 | &.active {
18 | background-color: $popover-backdrop-bg-active;
19 | }
20 | }
21 |
22 | .popover {
23 | position: absolute;
24 | top: 25%;
25 | left: 50%;
26 | z-index: $z-index-popover;
27 | display: block;
28 | margin-top: 12px;
29 | margin-left: -$popover-width / 2;
30 | height: $popover-height;
31 | width: $popover-width;
32 | background-color: $popover-bg-color;
33 | box-shadow: $popover-box-shadow;
34 | opacity: 0;
35 |
36 | .item:first-child {
37 | border-top: 0;
38 | }
39 |
40 | .item:last-child {
41 | border-bottom: 0;
42 | }
43 |
44 | &.popover-bottom {
45 | margin-top: -12px;
46 | }
47 | }
48 |
49 |
50 | // Set popover border-radius
51 | .popover,
52 | .popover .bar-header {
53 | border-radius: $popover-border-radius;
54 | }
55 | .popover .scroll-content {
56 | z-index: 1;
57 | margin: 2px 0;
58 | }
59 | .popover .bar-header {
60 | border-bottom-right-radius: 0;
61 | border-bottom-left-radius: 0;
62 | }
63 | .popover .has-header {
64 | border-top-right-radius: 0;
65 | border-top-left-radius: 0;
66 | }
67 | .popover-arrow {
68 | display: none;
69 | }
70 |
71 |
72 | // iOS Popover
73 | .platform-ios {
74 |
75 | .popover {
76 | box-shadow: $popover-box-shadow-ios;
77 | border-radius: $popover-border-radius-ios;
78 | }
79 | .popover .bar-header {
80 | @include border-top-radius($popover-border-radius-ios);
81 | }
82 | .popover .scroll-content {
83 | margin: 8px 0;
84 | border-radius: $popover-border-radius-ios;
85 | }
86 | .popover .scroll-content.has-header {
87 | margin-top: 0;
88 | }
89 | .popover-arrow {
90 | position: absolute;
91 | display: block;
92 | top: -17px;
93 | width: 30px;
94 | height: 19px;
95 | overflow: hidden;
96 |
97 | &:after {
98 | position: absolute;
99 | top: 12px;
100 | left: 5px;
101 | width: 20px;
102 | height: 20px;
103 | background-color: $popover-bg-color;
104 | border-radius: 3px;
105 | content: '';
106 | @include rotate(-45deg);
107 | }
108 | }
109 | .popover-bottom .popover-arrow {
110 | top: auto;
111 | bottom: -10px;
112 | &:after {
113 | top: -6px;
114 | }
115 | }
116 | }
117 |
118 |
119 | // Android Popover
120 | .platform-android {
121 |
122 | .popover {
123 | margin-top: -32px;
124 | background-color: $popover-bg-color-android;
125 | box-shadow: $popover-box-shadow-android;
126 |
127 | .item {
128 | border-color: $popover-bg-color-android;
129 | background-color: $popover-bg-color-android;
130 | color: #4d4d4d;
131 | }
132 | &.popover-bottom {
133 | margin-top: 32px;
134 | }
135 | }
136 |
137 | .popover-backdrop,
138 | .popover-backdrop.active {
139 | background-color: transparent;
140 | }
141 | }
142 |
143 |
144 | // disable clicks on all but the popover
145 | .popover-open {
146 | pointer-events: none;
147 |
148 | .popover,
149 | .popover-backdrop {
150 | pointer-events: auto;
151 | }
152 | // prevent clicks on popover when loading overlay is active though
153 | &.loading-active {
154 | .popover,
155 | .popover-backdrop {
156 | pointer-events: none;
157 | }
158 | }
159 | }
160 |
161 |
162 | // wider popover on larger viewports
163 | @media (min-width: $popover-large-break-point) {
164 | .popover {
165 | width: $popover-large-width;
166 | margin-left: -$popover-large-width / 2;
167 | }
168 | }
169 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_popup.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Popups
4 | * --------------------------------------------------
5 | */
6 |
7 | .popup-container {
8 | position: absolute;
9 | top: 0;
10 | left: 0;
11 | bottom: 0;
12 | right: 0;
13 | background: rgba(0,0,0,0);
14 |
15 | @include display-flex();
16 | @include justify-content(center);
17 | @include align-items(center);
18 |
19 | z-index: $z-index-popup;
20 |
21 | // Start hidden
22 | visibility: hidden;
23 | &.popup-showing {
24 | visibility: visible;
25 | }
26 |
27 | &.popup-hidden .popup {
28 | @include animation-name(scaleOut);
29 | @include animation-duration($popup-leave-animation-duration);
30 | @include animation-timing-function(ease-in-out);
31 | @include animation-fill-mode(both);
32 | }
33 |
34 | &.active .popup {
35 | @include animation-name(superScaleIn);
36 | @include animation-duration($popup-enter-animation-duration);
37 | @include animation-timing-function(ease-in-out);
38 | @include animation-fill-mode(both);
39 | }
40 |
41 | .popup {
42 | width: $popup-width;
43 | max-width: 100%;
44 | max-height: 90%;
45 |
46 | border-radius: $popup-border-radius;
47 | background-color: $popup-background-color;
48 |
49 | @include display-flex();
50 | @include flex-direction(column);
51 | }
52 |
53 | input,
54 | textarea {
55 | width: 100%;
56 | }
57 | }
58 |
59 | .popup-head {
60 | padding: 15px 10px;
61 | border-bottom: 1px solid #eee;
62 | text-align: center;
63 | }
64 | .popup-title {
65 | margin: 0;
66 | padding: 0;
67 | font-size: 15px;
68 | }
69 | .popup-sub-title {
70 | margin: 5px 0 0 0;
71 | padding: 0;
72 | font-weight: normal;
73 | font-size: 11px;
74 | }
75 | .popup-body {
76 | padding: 10px;
77 | overflow: auto;
78 | }
79 |
80 | .popup-buttons {
81 | @include display-flex();
82 | @include flex-direction(row);
83 | padding: 10px;
84 | min-height: $popup-button-min-height + 20;
85 |
86 | .button {
87 | @include flex(1);
88 | display: block;
89 | min-height: $popup-button-min-height;
90 | border-radius: $popup-button-border-radius;
91 | line-height: $popup-button-line-height;
92 |
93 | margin-right: 5px;
94 | &:last-child {
95 | margin-right: 0px;
96 | }
97 | }
98 | }
99 |
100 | .popup-open {
101 | pointer-events: none;
102 |
103 | &.modal-open .modal {
104 | pointer-events: none;
105 | }
106 |
107 | .popup-backdrop, .popup {
108 | pointer-events: auto;
109 | }
110 | }
111 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_progress.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Progress
4 | * --------------------------------------------------
5 | */
6 |
7 | progress {
8 | display: block;
9 | margin: $progress-margin;
10 | width: $progress-width;
11 | }
12 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_radio.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Radio Button Inputs
4 | * --------------------------------------------------
5 | */
6 |
7 | .item-radio {
8 | padding: 0;
9 |
10 | &:hover {
11 | cursor: pointer;
12 | }
13 | }
14 |
15 | .item-radio .item-content {
16 | /* give some room to the right for the checkmark icon */
17 | padding-right: $item-padding * 4;
18 | }
19 |
20 | .item-radio .radio-icon {
21 | /* checkmark icon will be hidden by default */
22 | position: absolute;
23 | top: 0;
24 | right: 0;
25 | z-index: $z-index-item-radio;
26 | visibility: hidden;
27 | padding: $item-padding - 2;
28 | height: 100%;
29 | font-size: 24px;
30 | }
31 |
32 | .item-radio input {
33 | /* hide any radio button inputs elements (the ugly circles) */
34 | position: absolute;
35 | left: -9999px;
36 |
37 | &:checked + .radio-content .item-content {
38 | /* style the item content when its checked */
39 | background: #f7f7f7;
40 | }
41 |
42 | &:checked + .radio-content .radio-icon {
43 | /* show the checkmark icon when its checked */
44 | visibility: visible;
45 | }
46 | }
47 |
48 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_refresher.scss:
--------------------------------------------------------------------------------
1 |
2 | // Scroll refresher (for pull to refresh)
3 | .scroll-refresher {
4 | position: absolute;
5 | top: -60px;
6 | right: 0;
7 | left: 0;
8 | overflow: hidden;
9 | margin: auto;
10 | height: 60px;
11 | .ionic-refresher-content {
12 | position: absolute;
13 | bottom: 15px;
14 | left: 0;
15 | width: 100%;
16 | color: $scroll-refresh-icon-color;
17 | text-align: center;
18 |
19 | font-size: 30px;
20 |
21 | .text-refreshing,
22 | .text-pulling {
23 | font-size: 16px;
24 | line-height: 16px;
25 | }
26 | &.ionic-refresher-with-text {
27 | bottom: 10px;
28 | }
29 | }
30 |
31 | .icon-refreshing,
32 | .icon-pulling {
33 | width: 100%;
34 | -webkit-backface-visibility: hidden;
35 | backface-visibility: hidden;
36 | -webkit-transform-style: preserve-3d;
37 | transform-style: preserve-3d;
38 | }
39 | .icon-pulling {
40 | @include animation-name(refresh-spin-back);
41 | @include animation-duration(200ms);
42 | @include animation-timing-function(linear);
43 | @include animation-fill-mode(none);
44 | -webkit-transform: translate3d(0,0,0) rotate(0deg);
45 | transform: translate3d(0,0,0) rotate(0deg);
46 | }
47 | .icon-refreshing,
48 | .text-refreshing {
49 | display: none;
50 | }
51 | .icon-refreshing {
52 | @include animation-duration(1.5s);
53 | }
54 |
55 | &.active {
56 | .icon-pulling:not(.pulling-rotation-disabled) {
57 | @include animation-name(refresh-spin);
58 | -webkit-transform: translate3d(0,0,0) rotate(-180deg);
59 | transform: translate3d(0,0,0) rotate(-180deg);
60 | }
61 | &.refreshing {
62 | @include transition(-webkit-transform .2s);
63 | @include transition(transform .2s);
64 | -webkit-transform: scale(1,1);
65 | transform: scale(1,1);
66 |
67 | .icon-pulling,
68 | .text-pulling {
69 | display: none;
70 | }
71 | .icon-refreshing,
72 | .text-refreshing {
73 | display: block;
74 | }
75 | &.refreshing-tail {
76 | -webkit-transform: scale(0,0);
77 | transform: scale(0,0);
78 | }
79 | }
80 | }
81 | }
82 | .overflow-scroll > .scroll{
83 | &.overscroll{
84 | position:fixed;
85 | right: 0;
86 | left: 0;
87 | }
88 | -webkit-overflow-scrolling:touch;
89 | width:100%;
90 | }
91 |
92 | .overflow-scroll.padding > .scroll.overscroll{
93 | padding: 10px;
94 | }
95 | @-webkit-keyframes refresh-spin {
96 | 0% { -webkit-transform: translate3d(0,0,0) rotate(0); }
97 | 100% { -webkit-transform: translate3d(0,0,0) rotate(180deg); }
98 | }
99 |
100 | @keyframes refresh-spin {
101 | 0% { transform: translate3d(0,0,0) rotate(0); }
102 | 100% { transform: translate3d(0,0,0) rotate(180deg); }
103 | }
104 |
105 | @-webkit-keyframes refresh-spin-back {
106 | 0% { -webkit-transform: translate3d(0,0,0) rotate(180deg); }
107 | 100% { -webkit-transform: translate3d(0,0,0) rotate(0); }
108 | }
109 |
110 | @keyframes refresh-spin-back {
111 | 0% { transform: translate3d(0,0,0) rotate(180deg); }
112 | 100% { transform: translate3d(0,0,0) rotate(0); }
113 | }
114 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_select.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Select
4 | * --------------------------------------------------
5 | */
6 |
7 | .item-select {
8 | position: relative;
9 |
10 | select {
11 | @include appearance(none);
12 | position: absolute;
13 | top: 0;
14 | bottom: 0;
15 | right: 0;
16 | padding: 0 ($item-padding * 3) 0 $item-padding;
17 | max-width: 65%;
18 |
19 | border: none;
20 | background: $item-default-bg;
21 | color: #333;
22 |
23 | // hack to hide default dropdown arrow in FF
24 | text-indent: .01px;
25 | text-overflow: '';
26 |
27 | white-space: nowrap;
28 | font-size: $font-size-base;
29 |
30 | cursor: pointer;
31 | direction: rtl; // right align the select text
32 | }
33 |
34 | select::-ms-expand {
35 | // hide default dropdown arrow in IE
36 | display: none;
37 | }
38 |
39 | option {
40 | direction: ltr;
41 | }
42 |
43 | &:after {
44 | position: absolute;
45 | top: 50%;
46 | right: $item-padding;
47 | margin-top: -3px;
48 | width: 0;
49 | height: 0;
50 | border-top: 5px solid;
51 | border-right: 5px solid rgba(0, 0, 0, 0);
52 | border-left: 5px solid rgba(0, 0, 0, 0);
53 | color: #999;
54 | content: "";
55 | pointer-events: none;
56 | }
57 | &.item-light {
58 | select{
59 | background:$item-light-bg;
60 | color:$item-light-text;
61 | }
62 | }
63 | &.item-stable {
64 | select{
65 | background:$item-stable-bg;
66 | color:$item-stable-text;
67 | }
68 | &:after, .input-label{
69 | color:darken($item-stable-border,30%);
70 | }
71 | }
72 | &.item-positive {
73 | select{
74 | background:$item-positive-bg;
75 | color:$item-positive-text;
76 | }
77 | &:after, .input-label{
78 | color:$item-positive-text;
79 | }
80 | }
81 | &.item-calm {
82 | select{
83 | background:$item-calm-bg;
84 | color:$item-calm-text;
85 | }
86 | &:after, .input-label{
87 | color:$item-calm-text;
88 | }
89 | }
90 | &.item-assertive {
91 | select{
92 | background:$item-assertive-bg;
93 | color:$item-assertive-text;
94 | }
95 | &:after, .input-label{
96 | color:$item-assertive-text;
97 | }
98 | }
99 | &.item-balanced {
100 | select{
101 | background:$item-balanced-bg;
102 | color:$item-balanced-text;
103 | }
104 | &:after, .input-label{
105 | color:$item-balanced-text;
106 | }
107 | }
108 | &.item-energized {
109 | select{
110 | background:$item-energized-bg;
111 | color:$item-energized-text;
112 | }
113 | &:after, .input-label{
114 | color:$item-energized-text;
115 | }
116 | }
117 | &.item-royal {
118 | select{
119 | background:$item-royal-bg;
120 | color:$item-royal-text;
121 | }
122 | &:after, .input-label{
123 | color:$item-royal-text;
124 | }
125 | }
126 | &.item-dark {
127 | select{
128 | background:$item-dark-bg;
129 | color:$item-dark-text;
130 | }
131 | &:after, .input-label{
132 | color:$item-dark-text;
133 | }
134 | }
135 | }
136 |
137 | select {
138 | &[multiple],
139 | &[size] {
140 | height: auto;
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_slide-box.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Slide Box
4 | * --------------------------------------------------
5 | */
6 |
7 | .slider {
8 | position: relative;
9 | visibility: hidden;
10 | // Make sure items don't scroll over ever
11 | overflow: hidden;
12 | }
13 |
14 | .slider-slides {
15 | position: relative;
16 | height: 100%;
17 | }
18 |
19 | .slider-slide {
20 | position: relative;
21 | display: block;
22 | float: left;
23 | width: 100%;
24 | height: 100%;
25 | vertical-align: top;
26 | }
27 |
28 | .slider-slide-image {
29 | > img {
30 | width: 100%;
31 | }
32 | }
33 |
34 | .slider-pager {
35 | position: absolute;
36 | bottom: 20px;
37 | z-index: $z-index-slider-pager;
38 | width: 100%;
39 | height: 15px;
40 | text-align: center;
41 |
42 | .slider-pager-page {
43 | display: inline-block;
44 | margin: 0px 3px;
45 | width: 15px;
46 | color: #000;
47 | text-decoration: none;
48 |
49 | opacity: 0.3;
50 |
51 | &.active {
52 | @include transition(opacity 0.4s ease-in);
53 | opacity: 1;
54 | }
55 | }
56 | }
57 |
58 | //Disable animate service animations
59 | .slider-slide,
60 | .slider-pager-page {
61 | &.ng-enter,
62 | &.ng-leave,
63 | &.ng-animate {
64 | -webkit-transition: none !important;
65 | transition: none !important;
66 | }
67 | &.ng-animate {
68 | -webkit-animation: none 0s;
69 | animation: none 0s;
70 | }
71 | }
72 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_spinner.scss:
--------------------------------------------------------------------------------
1 | /**
2 | * Spinners
3 | * --------------------------------------------------
4 | */
5 |
6 | .spinner {
7 | svg {
8 | width: $spinner-width;
9 | height: $spinner-height;
10 | }
11 |
12 | stroke: $spinner-default-stroke;
13 | fill: $spinner-default-fill;
14 |
15 | &.spinner-light {
16 | stroke: $spinner-light-stroke;
17 | fill: $spinner-light-fill;
18 | }
19 | &.spinner-stable {
20 | stroke: $spinner-stable-stroke;
21 | fill: $spinner-stable-fill;
22 | }
23 | &.spinner-positive {
24 | stroke: $spinner-positive-stroke;
25 | fill: $spinner-positive-fill;
26 | }
27 | &.spinner-calm {
28 | stroke: $spinner-calm-stroke;
29 | fill: $spinner-calm-fill;
30 | }
31 | &.spinner-balanced {
32 | stroke: $spinner-balanced-stroke;
33 | fill: $spinner-balanced-fill;
34 | }
35 | &.spinner-assertive {
36 | stroke: $spinner-assertive-stroke;
37 | fill: $spinner-assertive-fill;
38 | }
39 | &.spinner-energized {
40 | stroke: $spinner-energized-stroke;
41 | fill: $spinner-energized-fill;
42 | }
43 | &.spinner-royal {
44 | stroke: $spinner-royal-stroke;
45 | fill: $spinner-royal-fill;
46 | }
47 | &.spinner-dark {
48 | stroke: $spinner-dark-stroke;
49 | fill: $spinner-dark-fill;
50 | }
51 | }
52 |
53 | .spinner-android {
54 | stroke: #4b8bf4;
55 | }
56 |
57 | .spinner-ios,
58 | .spinner-ios-small {
59 | stroke: #69717d;
60 | }
61 |
62 | .spinner-spiral {
63 | .stop1 {
64 | stop-color: $spinner-light-fill;
65 | stop-opacity: 0;
66 | }
67 |
68 | &.spinner-light {
69 | .stop1 {
70 | stop-color: $spinner-default-fill;
71 | }
72 | .stop2 {
73 | stop-color: $spinner-light-fill;
74 | }
75 | }
76 | &.spinner-stable .stop2 {
77 | stop-color: $spinner-stable-fill;
78 | }
79 | &.spinner-positive .stop2 {
80 | stop-color: $spinner-positive-fill;
81 | }
82 | &.spinner-calm .stop2 {
83 | stop-color: $spinner-calm-fill;
84 | }
85 | &.spinner-balanced .stop2 {
86 | stop-color: $spinner-balanced-fill;
87 | }
88 | &.spinner-assertive .stop2 {
89 | stop-color: $spinner-assertive-fill;
90 | }
91 | &.spinner-energized .stop2 {
92 | stop-color: $spinner-energized-fill;
93 | }
94 | &.spinner-royal .stop2 {
95 | stop-color: $spinner-royal-fill;
96 | }
97 | &.spinner-dark .stop2 {
98 | stop-color: $spinner-dark-fill;
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/_type.scss:
--------------------------------------------------------------------------------
1 |
2 | /**
3 | * Typography
4 | * --------------------------------------------------
5 | */
6 |
7 |
8 | // Body text
9 | // -------------------------
10 |
11 | p {
12 | margin: 0 0 ($line-height-computed / 2);
13 | }
14 |
15 |
16 | // Emphasis & misc
17 | // -------------------------
18 |
19 | small { font-size: 85%; }
20 | cite { font-style: normal; }
21 |
22 |
23 | // Alignment
24 | // -------------------------
25 |
26 | .text-left { text-align: left; }
27 | .text-right { text-align: right; }
28 | .text-center { text-align: center; }
29 |
30 |
31 | // Headings
32 | // -------------------------
33 |
34 | h1, h2, h3, h4, h5, h6,
35 | .h1, .h2, .h3, .h4, .h5, .h6 {
36 | color: $base-color;
37 | font-weight: $headings-font-weight;
38 | font-family: $headings-font-family;
39 | line-height: $headings-line-height;
40 |
41 | small {
42 | font-weight: normal;
43 | line-height: 1;
44 | }
45 | }
46 |
47 | h1, .h1,
48 | h2, .h2,
49 | h3, .h3 {
50 | margin-top: $line-height-computed;
51 | margin-bottom: ($line-height-computed / 2);
52 |
53 | &:first-child {
54 | margin-top: 0;
55 | }
56 |
57 | + h1, + .h1,
58 | + h2, + .h2,
59 | + h3, + .h3 {
60 | margin-top: ($line-height-computed / 2);
61 | }
62 | }
63 |
64 | h4, .h4,
65 | h5, .h5,
66 | h6, .h6 {
67 | margin-top: ($line-height-computed / 2);
68 | margin-bottom: ($line-height-computed / 2);
69 | }
70 |
71 | h1, .h1 { font-size: floor($font-size-base * 2.60); } // ~36px
72 | h2, .h2 { font-size: floor($font-size-base * 2.15); } // ~30px
73 | h3, .h3 { font-size: ceil($font-size-base * 1.70); } // ~24px
74 | h4, .h4 { font-size: ceil($font-size-base * 1.25); } // ~18px
75 | h5, .h5 { font-size: $font-size-base; }
76 | h6, .h6 { font-size: ceil($font-size-base * 0.85); } // ~12px
77 |
78 | h1 small, .h1 small { font-size: ceil($font-size-base * 1.70); } // ~24px
79 | h2 small, .h2 small { font-size: ceil($font-size-base * 1.25); } // ~18px
80 | h3 small, .h3 small,
81 | h4 small, .h4 small { font-size: $font-size-base; }
82 |
83 |
84 | // Description Lists
85 | // -------------------------
86 |
87 | dl {
88 | margin-bottom: $line-height-computed;
89 | }
90 | dt,
91 | dd {
92 | line-height: $line-height-base;
93 | }
94 | dt {
95 | font-weight: bold;
96 | }
97 |
98 |
99 | // Blockquotes
100 | // -------------------------
101 |
102 | blockquote {
103 | margin: 0 0 $line-height-computed;
104 | padding: ($line-height-computed / 2) $line-height-computed;
105 | border-left: 5px solid gray;
106 |
107 | p {
108 | font-weight: 300;
109 | font-size: ($font-size-base * 1.25);
110 | line-height: 1.25;
111 | }
112 |
113 | p:last-child {
114 | margin-bottom: 0;
115 | }
116 |
117 | small {
118 | display: block;
119 | line-height: $line-height-base;
120 | &:before {
121 | content: '\2014 \00A0';// EM DASH, NBSP;
122 | }
123 | }
124 | }
125 |
126 |
127 | // Quotes
128 | // -------------------------
129 |
130 | q:before,
131 | q:after,
132 | blockquote:before,
133 | blockquote:after {
134 | content: "";
135 | }
136 |
137 |
138 | // Addresses
139 | // -------------------------
140 |
141 | address {
142 | display: block;
143 | margin-bottom: $line-height-computed;
144 | font-style: normal;
145 | line-height: $line-height-base;
146 | }
147 |
148 |
149 | // Links
150 | // -------------------------
151 | a {
152 | color: $link-color;
153 | }
154 |
155 | a.subdued {
156 | padding-right: 10px;
157 | color: #888;
158 | text-decoration: none;
159 |
160 | &:hover {
161 | text-decoration: none;
162 | }
163 | &:last-child {
164 | padding-right: 0;
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/ionic.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 |
3 | @import
4 | // Ionicons
5 | "ionicons/ionicons.scss",
6 |
7 | // Variables
8 | "mixins",
9 | "variables",
10 |
11 | // Base
12 | "reset",
13 | "scaffolding",
14 | "type",
15 |
16 | // Components
17 | "action-sheet",
18 | "backdrop",
19 | "bar",
20 | "tabs",
21 | "menu",
22 | "modal",
23 | "popover",
24 | "popup",
25 | "loading",
26 | "items",
27 | "list",
28 | "badge",
29 | "slide-box",
30 | "slides",
31 | "refresher",
32 | "spinner",
33 |
34 | // Forms
35 | "form",
36 | "checkbox",
37 | "toggle",
38 | "radio",
39 | "range",
40 | "select",
41 | "progress",
42 |
43 | // Buttons
44 | "button",
45 | "button-bar",
46 |
47 | // Util
48 | "grid",
49 | "util",
50 | "platform",
51 |
52 | // Animations
53 | "animations",
54 | "transitions";
55 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/ionicons/_ionicons-font.scss:
--------------------------------------------------------------------------------
1 | // Ionicons Font Path
2 | // --------------------------
3 |
4 | @font-face {
5 | font-family: $ionicons-font-family;
6 | src:url("#{$ionicons-font-path}/ionicons.eot?v=#{$ionicons-version}");
7 | src:url("#{$ionicons-font-path}/ionicons.eot?v=#{$ionicons-version}#iefix") format("embedded-opentype"),
8 | url("#{$ionicons-font-path}/ionicons.ttf?v=#{$ionicons-version}") format("truetype"),
9 | url("#{$ionicons-font-path}/ionicons.woff?v=#{$ionicons-version}") format("woff"),
10 | url("#{$ionicons-font-path}/ionicons.woff") format("woff"), /* for WP8 */
11 | url("#{$ionicons-font-path}/ionicons.svg?v=#{$ionicons-version}#Ionicons") format("svg");
12 | font-weight: normal;
13 | font-style: normal;
14 | }
15 |
16 | .ion {
17 | display: inline-block;
18 | font-family: $ionicons-font-family;
19 | speak: none;
20 | font-style: normal;
21 | font-weight: normal;
22 | font-variant: normal;
23 | text-transform: none;
24 | text-rendering: auto;
25 | line-height: 1;
26 | -webkit-font-smoothing: antialiased;
27 | -moz-osx-font-smoothing: grayscale;
28 | }
29 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/scss/ionicons/ionicons.scss:
--------------------------------------------------------------------------------
1 | @charset "UTF-8";
2 | @import "ionicons-variables";
3 | /*!
4 | Ionicons, v2.0.1
5 | Created by Ben Sperry for the Ionic Framework, http://ionicons.com/
6 | https://twitter.com/benjsperry https://twitter.com/ionicframework
7 | MIT License: https://github.com/driftyco/ionicons
8 |
9 | Android-style icons originally built by Google’s
10 | Material Design Icons: https://github.com/google/material-design-icons
11 | used under CC BY http://creativecommons.org/licenses/by/4.0/
12 | Modified icons to fit ionicon’s grid from original.
13 | */
14 |
15 | @import "ionicons-font";
16 | @import "ionicons-icons";
17 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/lib/ionic/version.json:
--------------------------------------------------------------------------------
1 | {
2 | "version": "1.2.4",
3 | "codename": "",
4 | "date": "2016-01-03",
5 | "time": "19:55:51"
6 | }
7 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/partials/entry.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
19 |
20 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/partials/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
--------------------------------------------------------------------------------
/blog2/client/electron-quick-start/www/partials/login.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
18 |
19 |
--------------------------------------------------------------------------------
/blog2/common/models/appuser.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Appuser) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/blog2/common/models/appuser.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appuser",
3 | "base": "User",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {},
10 | "validations": [],
11 | "relations": {},
12 | "acls": [],
13 | "methods": {}
14 | }
15 |
--------------------------------------------------------------------------------
/blog2/common/models/category.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Category) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/blog2/common/models/category.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "category",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "name": {
11 | "type": "string",
12 | "required": true
13 | }
14 | },
15 | "validations": [],
16 | "relations": {},
17 | "acls": [
18 | {
19 | "accessType": "*",
20 | "principalType": "ROLE",
21 | "principalId": "$everyone",
22 | "permission": "DENY"
23 | },
24 | {
25 | "accessType": "READ",
26 | "principalType": "ROLE",
27 | "principalId": "$everyone",
28 | "permission": "ALLOW"
29 | },
30 | {
31 | "accessType": "WRITE",
32 | "principalType": "ROLE",
33 | "principalId": "$authenticated",
34 | "permission": "ALLOW"
35 | }
36 | ],
37 | "methods": {}
38 | }
39 |
--------------------------------------------------------------------------------
/blog2/common/models/entry.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Entry) {
2 |
3 | Entry.observe('loaded', function(ctx, next) {
4 | if(ctx && ctx.instance && ctx.instance.released) {
5 | var date = ctx.instance.published;
6 | ctx.instance.url = "/"+date.getFullYear()+"/"+(date.getMonth()+1)+"/"+date.getDate()+"/"+ctx.instance.slug;
7 | }
8 | next();
9 | });
10 |
11 | };
12 |
--------------------------------------------------------------------------------
/blog2/common/models/entry.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "entry",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "title": {
11 | "type": "string",
12 | "required": true
13 | },
14 | "released": {
15 | "type": "boolean",
16 | "required": true
17 | },
18 | "published": {
19 | "type": "date",
20 | "required": true
21 | },
22 | "slug": {
23 | "type": "string",
24 | "required": true
25 | },
26 | "body": {
27 | "type": "string",
28 | "required": true
29 | }
30 | },
31 | "validations": [],
32 | "relations": {
33 | "categories": {
34 | "type": "hasMany",
35 | "model": "category",
36 | "foreignKey": ""
37 | }
38 | },
39 | "acls": [
40 | {
41 | "accessType": "*",
42 | "principalType": "ROLE",
43 | "principalId": "$everyone",
44 | "permission": "DENY"
45 | },
46 | {
47 | "accessType": "READ",
48 | "principalType": "ROLE",
49 | "principalId": "$everyone",
50 | "permission": "ALLOW"
51 | },
52 | {
53 | "accessType": "WRITE",
54 | "principalType": "ROLE",
55 | "principalId": "$authenticated",
56 | "permission": "ALLOW"
57 | }
58 | ],
59 | "methods": {}
60 | }
61 |
--------------------------------------------------------------------------------
/blog2/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "blog1",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "pretest": "jshint ."
7 | },
8 | "dependencies": {
9 | "chalk": "^1.1.1",
10 | "compression": "^1.0.3",
11 | "cors": "^2.5.2",
12 | "express-handlebars": "^2.0.1",
13 | "handlebars-helper-moment": "^0.2.0",
14 | "loopback": "^2.22.0",
15 | "loopback-boot": "^2.6.5",
16 | "loopback-component-explorer": "^2.1.0",
17 | "loopback-connector-mongodb": "^1.13.2",
18 | "loopback-datasource-juggler": "^2.39.0",
19 | "moment": "^2.11.0",
20 | "serve-favicon": "^2.0.1"
21 | },
22 | "devDependencies": {
23 | "jshint": "^2.5.6"
24 | },
25 | "repository": {
26 | "type": "",
27 | "url": ""
28 | },
29 | "description": "blog1"
30 | }
31 |
--------------------------------------------------------------------------------
/blog2/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | module.exports = function enableAuthentication(server) {
2 | // enable authentication
3 | server.enableAuth();
4 | };
5 |
--------------------------------------------------------------------------------
/blog2/server/boot/routes.js:
--------------------------------------------------------------------------------
1 | module.exports = function(app) {
2 | // Install a `/` route that returns server status
3 | //var router = server.loopback.Router();
4 | //router.get('/', server.loopback.status());
5 | //server.use(router);
6 |
7 | app.get('/', function(req, res) {
8 | console.log('getting blog entries');
9 | app.models.entry.find({where:{released:true},order:'published desc'}).then(function(entries) {
10 | res.render('index',{entries:entries});
11 | });
12 | });
13 |
14 | app.get('/:year/:month/:day/:slug', function(req, res) {
15 | console.log('do blog entry');
16 | console.dir(req.params);
17 | //create an upper and lower date range
18 | var lowerDate = new Date(req.params.year, req.params.month-1, req.params.day);
19 | var upperDate = new Date(lowerDate);
20 | upperDate.setDate(upperDate.getDate()+1);
21 | app.models.entry.findOne({where:{
22 | released:true,
23 | slug:req.params.slug,
24 | published:{between:[lowerDate,upperDate]}
25 | },limit:1}).then(function(entry) {
26 | //first - did we get any?
27 | if(!entry) {
28 | res.redirect('/');
29 | }
30 | res.render('entry', {entry:entry});
31 | });
32 | });
33 | };
34 |
--------------------------------------------------------------------------------
/blog2/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/blog2/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": {
7 | "enableHttpContext": false
8 | },
9 | "rest": {
10 | "normalizeHttpPath": false,
11 | "xml": false
12 | },
13 | "json": {
14 | "strict": false,
15 | "limit": "100kb"
16 | },
17 | "urlencoded": {
18 | "extended": true,
19 | "limit": "100kb"
20 | },
21 | "cors": false,
22 | "errorHandler": {
23 | "disableStackTrace": false
24 | }
25 | },
26 | "legacyExplorer": false
27 | }
28 |
--------------------------------------------------------------------------------
/blog2/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "memory"
5 | },
6 | "blogdata": {
7 | "host": "localhost",
8 | "port": 27017,
9 | "database": "blogdata",
10 | "name": "blogdata",
11 | "connector": "mongodb"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/blog2/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | }
14 | },
15 | "session": {},
16 | "auth": {},
17 | "parse": {},
18 | "routes": {
19 | "loopback#rest": {
20 | "paths": [
21 | "${restApiRoot}"
22 | ]
23 | }
24 | },
25 | "files": {},
26 | "final": {
27 | "loopback#urlNotFound": {}
28 | },
29 | "final:after": {
30 | "loopback#errorHandler": {}
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/blog2/server/middleware.production.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "loopback#errorHandler": {
4 | "params": {
5 | "includeStack": false
6 | }
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/blog2/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "db"
18 | },
19 | "AccessToken": {
20 | "dataSource": "db",
21 | "public": false
22 | },
23 | "ACL": {
24 | "dataSource": "db",
25 | "public": false
26 | },
27 | "RoleMapping": {
28 | "dataSource": "db",
29 | "public": false
30 | },
31 | "Role": {
32 | "dataSource": "db",
33 | "public": false
34 | },
35 | "entry": {
36 | "dataSource": "blogdata",
37 | "public": true,
38 | "$promise": {},
39 | "$resolved": true
40 | },
41 | "category": {
42 | "dataSource": "blogdata",
43 | "public": true,
44 | "$promise": {},
45 | "$resolved": true
46 | },
47 | "appuser": {
48 | "dataSource": "blogdata",
49 | "public": true,
50 | "$promise": {},
51 | "$resolved": true
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/blog2/server/server.js:
--------------------------------------------------------------------------------
1 | var loopback = require('loopback');
2 | var boot = require('loopback-boot');
3 |
4 | var app = module.exports = loopback();
5 | var exphbs = require('express-handlebars');
6 |
7 | var hbs = exphbs.create({
8 | defaultLayout:'main',
9 | helpers:require('handlebars-helper-moment')()
10 | });
11 |
12 | app.engine('handlebars', hbs.engine);
13 | app.set('view engine', 'handlebars');
14 |
15 | app.start = function() {
16 | // start the web server
17 | return app.listen(function() {
18 | app.emit('started');
19 | var baseUrl = app.get('url').replace(/\/$/, '');
20 | console.log('Web server listening at: %s', baseUrl);
21 | if (app.get('loopback-component-explorer')) {
22 | var explorerPath = app.get('loopback-component-explorer').mountPath;
23 | console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
24 | }
25 | });
26 | };
27 |
28 | // Bootstrap the application, configure models, datasources and middleware.
29 | // Sub-apps like REST API are mounted via boot scripts.
30 | boot(app, __dirname, function(err) {
31 | if (err) throw err;
32 |
33 | // start the server if `$ node server.js`
34 | if (require.main === module)
35 | app.start();
36 | });
37 |
38 |
--------------------------------------------------------------------------------
/blog2/server/views/entry.handlebars:
--------------------------------------------------------------------------------
1 |
2 | {{entry.title}}
3 |
4 | Published: {{moment published format="MMMM D, YYYY h:mm A"}}
5 |
6 |
7 | {{{entry.body}}}
--------------------------------------------------------------------------------
/blog2/server/views/index.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 | Entries
4 |
5 | {{#each entries}}
6 |
7 | {{title}}
8 | Published: {{moment published format="MMMM D, YYYY h:mm A"}}
9 |
10 |
11 | {{/each}}
--------------------------------------------------------------------------------
/blog2/server/views/layouts/main.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
18 |
19 |
20 |
50 |
59 |
60 |
61 |
62 |
63 |
64 |
{{{body}}}
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
--------------------------------------------------------------------------------
/filetest/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/filetest/.eslintignore:
--------------------------------------------------------------------------------
1 | /client/
--------------------------------------------------------------------------------
/filetest/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "loopback"
3 | }
--------------------------------------------------------------------------------
/filetest/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/filetest/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/filetest/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
5 | yep
--------------------------------------------------------------------------------
/filetest/client/app.js:
--------------------------------------------------------------------------------
1 | var $name, $age, $breed, $picture, $resume, $catList;
2 |
3 | var apiUrl = 'http://localhost:3000/api/';
4 |
5 | $(document).ready(function() {
6 |
7 | $('#addCatForm').on('submit', handleForm);
8 |
9 | $name = $('#name');
10 | $age = $('#age');
11 | $breed = $('#breed');
12 | $picture = $('#picture');
13 | $resume = $('#resume');
14 | $catList = $('#catList');
15 |
16 | getCats();
17 |
18 | });
19 |
20 | function getCats() {
21 |
22 | var list = '';
23 |
24 | $.get(apiUrl + 'cats').then(function(res) {
25 | res.forEach(function(cat) {
26 | list += `${cat.name}
`;
27 | if(cat.picture) {
28 | list += `
`;
29 | }
30 | list += `
31 |
32 | ${cat.name} is a ${cat.breed} and is ${cat.age} year(s) old.
33 |
`;
34 | });
35 | $catList.html(list);
36 | });
37 | }
38 |
39 | function handleForm(e) {
40 | e.preventDefault();
41 |
42 | var cat = {
43 | name:$name.val(),
44 | age:$age.val(),
45 | breed:$breed.val()
46 | }
47 |
48 | console.log(cat);
49 |
50 | // step 1 - make the cat, this gives us something to associate with
51 | $.post(apiUrl + 'cats', cat).then(function(res) {
52 |
53 | //copy res since it has the id
54 | cat = res;
55 |
56 | var promises = [];
57 |
58 | // step 2: do we have binary crap?
59 | if($resume.val() != '') {
60 | console.log('i need to process the resume upload');
61 | promises.push(sendFile($resume.get(0).files[0], apiUrl + 'attachments/resume/upload'));
62 | }
63 |
64 | if($picture.val() != '') {
65 | console.log('i need to process thepicture upload');
66 | promises.push(sendFile($picture.get(0).files[0], apiUrl + 'attachments/picture/upload'));
67 | }
68 |
69 | // no need to see if I have promises, it still resolves if empty
70 | Promise.all(promises).then(function(results) {
71 | console.log('back from all promises', results);
72 | //update cat if we need to
73 | if(promises.length >= 1) {
74 | /*
75 | so we have one or two results, we could add some logic to see what
76 | we selected so we know what is what, but we can simplify since the result
77 | contains a 'container' field that matches the property
78 | */
79 | results.forEach(function(resultOb) {
80 | if(resultOb.result.files && resultOb.result.files.file[0].container) {
81 | cat[resultOb.result.files.file[0].container] = resultOb.result.files.file[0].name;
82 | }
83 | });
84 | console.dir(cat);
85 | //now update cat, we can't include the id though
86 | var id = cat.id;
87 | delete cat.id;
88 | $.post(apiUrl + 'cats/'+id+'/replace', cat).then(function() {
89 | getCats();
90 | });
91 | } else {
92 | getCats();
93 | }
94 | });
95 |
96 | });
97 |
98 | }
99 |
100 | //Stolen from: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications
101 | function sendFile(file, url) {
102 | return new Promise(function(resolve, reject) {
103 |
104 | var xhr = new XMLHttpRequest();
105 | var fd = new FormData();
106 |
107 | xhr.open("POST", url, true);
108 | xhr.onreadystatechange = function() {
109 | if(xhr.readyState == 4 && xhr.status == 200) {
110 | resolve(JSON.parse(xhr.responseText));
111 | }
112 | };
113 | fd.append('file', file);
114 | xhr.send(fd);
115 |
116 | });
117 | }
--------------------------------------------------------------------------------
/filetest/client/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
16 |
17 |
18 |
19 | Cats
20 |
21 |
22 |
23 |
24 |
25 | Add Cat
26 |
27 |
57 |
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/filetest/common/models/attachment.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Attachment) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/filetest/common/models/attachment.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "attachment",
3 | "base": "Model",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true
7 | },
8 | "properties": {},
9 | "validations": [],
10 | "relations": {},
11 | "acls": [],
12 | "methods": {}
13 | }
14 |
--------------------------------------------------------------------------------
/filetest/common/models/cat.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Cat) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/filetest/common/models/cat.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "cat",
3 | "base": "PersistedModel",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true
7 | },
8 | "properties": {
9 | "name": {
10 | "type": "string",
11 | "required": true
12 | },
13 | "age": {
14 | "type": "number",
15 | "required": true
16 | },
17 | "breed": {
18 | "type": "string",
19 | "required": true
20 | }
21 | },
22 | "validations": [],
23 | "relations": {},
24 | "acls": [],
25 | "methods": {}
26 | }
27 |
--------------------------------------------------------------------------------
/filetest/common/models/note.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Note) {
2 | };
3 |
--------------------------------------------------------------------------------
/filetest/common/models/note.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Note",
3 | "properties": {
4 | "title": {
5 | "type": "string",
6 | "required": true
7 | },
8 | "content": {
9 | "type": "string"
10 | }
11 | },
12 | "validations": [],
13 | "relations": {},
14 | "acls": [],
15 | "methods": {}
16 | }
17 |
--------------------------------------------------------------------------------
/filetest/data.db:
--------------------------------------------------------------------------------
1 | {
2 | "ids": {
3 | "User": 1,
4 | "AccessToken": 1,
5 | "ACL": 1,
6 | "RoleMapping": 1,
7 | "Role": 1,
8 | "Note": 1,
9 | "cat": 3
10 | },
11 | "models": {
12 | "User": {},
13 | "AccessToken": {},
14 | "ACL": {},
15 | "RoleMapping": {},
16 | "Role": {},
17 | "Note": {},
18 | "cat": {
19 | "1": "{\"name\":\"Mr Fluffy\",\"age\":2,\"breed\":\"mutt\",\"id\":1}",
20 | "2": "{\"name\":\"moo\",\"age\":7,\"breed\":\"mutt\",\"id\":2}"
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/filetest/files/resume/avatar.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/filetest/files/resume/avatar.jpg
--------------------------------------------------------------------------------
/filetest/files/resume/goo.txt:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/filetest/files/resume/goo.txt
--------------------------------------------------------------------------------
/filetest/files/resume/windowsfield.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/filetest/files/resume/windowsfield.jpg
--------------------------------------------------------------------------------
/filetest/notes.txt:
--------------------------------------------------------------------------------
1 | Storage component - http://loopback.io/doc/en/lb2/Storage-component.html
2 |
3 | issues:
4 |
5 | containers/files
6 |
7 | its a datasource
8 |
9 | the name should be what? what im calling the property or something generic?
10 | make your folder
11 | make a subfolder?
12 | make a model
13 |
14 | {
15 | "result": {
16 | "files": {
17 | "file": [
18 | {
19 | "container": "resume",
20 | "name": "avatar.jpg",
21 | "type": "image/jpeg",
22 | "size": 5055
23 | }
24 | ]
25 | },
26 | "fields": {}
27 | }
28 | }
--------------------------------------------------------------------------------
/filetest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "filetest",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "lint": "eslint .",
7 | "start": "node .",
8 | "posttest": "npm run lint && nsp check"
9 | },
10 | "dependencies": {
11 | "compression": "^1.0.3",
12 | "cors": "^2.5.2",
13 | "helmet": "^1.3.0",
14 | "loopback": "^2.22.0",
15 | "loopback-boot": "^2.6.5",
16 | "loopback-component-explorer": "^2.4.0",
17 | "loopback-datasource-juggler": "^2.39.0",
18 | "serve-favicon": "^2.0.1",
19 | "storage": "^0.2.0",
20 | "strong-error-handler": "^1.0.1"
21 | },
22 | "devDependencies": {
23 | "eslint": "^2.13.1",
24 | "eslint-config-loopback": "^4.0.0",
25 | "nsp": "^2.1.0"
26 | },
27 | "repository": {
28 | "type": "",
29 | "url": ""
30 | },
31 | "license": "UNLICENSED",
32 | "description": "filetest"
33 | }
34 |
--------------------------------------------------------------------------------
/filetest/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function enableAuthentication(server) {
4 | // enable authentication
5 | server.enableAuth();
6 | };
7 |
--------------------------------------------------------------------------------
/filetest/server/boot/root.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(server) {
4 | // Install a `/` route that returns server status
5 | var router = server.loopback.Router();
6 | // router.get('/', server.loopback.status());
7 | server.use(router);
8 | };
9 |
--------------------------------------------------------------------------------
/filetest/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/filetest/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": false,
7 | "rest": {
8 | "normalizeHttpPath": false,
9 | "xml": false
10 | },
11 | "json": {
12 | "strict": false,
13 | "limit": "100kb"
14 | },
15 | "urlencoded": {
16 | "extended": true,
17 | "limit": "100kb"
18 | },
19 | "cors": false,
20 | "handleErrors": false
21 | },
22 | "legacyExplorer": false
23 | }
24 |
--------------------------------------------------------------------------------
/filetest/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "memory",
5 | "file": "data.db"
6 | },
7 | "storage": {
8 | "name": "storage",
9 | "connector": "loopback-component-storage",
10 | "provider": "filesystem",
11 | "root": "./files"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/filetest/server/middleware.development.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "strong-error-handler": {
4 | "params": {
5 | "debug": true,
6 | "log": true
7 | }
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/filetest/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | },
14 | "helmet#xssFilter": {},
15 | "helmet#frameguard": {
16 | "params": [
17 | "deny"
18 | ]
19 | },
20 | "helmet#hsts": {
21 | "params": {
22 | "maxAge": 0,
23 | "includeSubdomains": true
24 | }
25 | },
26 | "helmet#hidePoweredBy": {},
27 | "helmet#ieNoOpen": {},
28 | "helmet#noSniff": {},
29 | "helmet#noCache": {
30 | "enabled": false
31 | }
32 | },
33 | "session": {},
34 | "auth": {},
35 | "parse": {},
36 | "routes": {
37 | "loopback#rest": {
38 | "paths": [
39 | "${restApiRoot}"
40 | ]
41 | }
42 | },
43 | "files": {
44 | "loopback#static":{
45 | "params":"$!../client"
46 | }
47 | },
48 | "final": {
49 | "loopback#urlNotFound": {}
50 | },
51 | "final:after": {
52 | "strong-error-handler": {}
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/filetest/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "db"
18 | },
19 | "AccessToken": {
20 | "dataSource": "db",
21 | "public": false
22 | },
23 | "ACL": {
24 | "dataSource": "db",
25 | "public": false
26 | },
27 | "RoleMapping": {
28 | "dataSource": "db",
29 | "public": false
30 | },
31 | "Role": {
32 | "dataSource": "db",
33 | "public": false
34 | },
35 | "Note": {
36 | "dataSource": "db"
37 | },
38 | "cat": {
39 | "dataSource": "db",
40 | "public": true
41 | },
42 | "attachment": {
43 | "dataSource": "storage",
44 | "public": true
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/filetest/server/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var loopback = require('loopback');
4 | var boot = require('loopback-boot');
5 |
6 | var app = module.exports = loopback();
7 |
8 | app.start = function() {
9 | // start the web server
10 | return app.listen(function() {
11 | app.emit('started');
12 | var baseUrl = app.get('url').replace(/\/$/, '');
13 | console.log('Web server listening at: %s', baseUrl);
14 | if (app.get('loopback-component-explorer')) {
15 | var explorerPath = app.get('loopback-component-explorer').mountPath;
16 | console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
17 | }
18 | });
19 | };
20 |
21 | // Bootstrap the application, configure models, datasources and middleware.
22 | // Sub-apps like REST API are mounted via boot scripts.
23 | boot(app, __dirname, function(err) {
24 | if (err) throw err;
25 |
26 | // start the server if `$ node server.js`
27 | if (require.main === module)
28 | app.start();
29 | });
30 |
--------------------------------------------------------------------------------
/geotest/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/geotest/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/geotest/.jshintignore:
--------------------------------------------------------------------------------
1 | /client/
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/geotest/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "eqeqeq": true,
7 | "eqnull": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": "nofunc",
11 | "newcap": true,
12 | "nonew": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "trailing": true,
19 | "sub": true,
20 | "maxlen": 80
21 | }
22 |
--------------------------------------------------------------------------------
/geotest/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/geotest/README.md:
--------------------------------------------------------------------------------
1 | # My Application
2 |
3 | The project is generated by [LoopBack](http://loopback.io).
--------------------------------------------------------------------------------
/geotest/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/geotest/client/img/sadcat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cfjedimaster/StrongLoopDemos/615610a8c80c011176bd80a9883b4521fbee7caa/geotest/client/img/sadcat.png
--------------------------------------------------------------------------------
/geotest/client/js/map.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 | $.get("/api/Cats", function(res) {
3 | console.log(res);
4 | //generate the map with the results
5 | var mapurl = 'https://maps.googleapis.com/maps/api/staticmap?';
6 | mapurl += '&size=700x700&markers=color:red'
7 | res.forEach(function(cat) {
8 | console.dir(cat.location);
9 | mapurl += '%7C'+cat.location.lat+','+cat.location.lng;
10 | });
11 |
12 | $('#map').attr('src',mapurl);
13 | console.log(mapurl);
14 | });
15 | });
--------------------------------------------------------------------------------
/geotest/client/js/near.js:
--------------------------------------------------------------------------------
1 | $(document).ready(function() {
2 |
3 | $status = $('#status');
4 |
5 | console.log('Begin trying to get position');
6 | navigator.geolocation.getCurrentPosition(function(pos) {
7 |
8 | $.get('/api/Cats/?filter[where][location][near]='+pos.coords.latitude+','+pos.coords.longitude+'&filter[where][location][maxDistance]=20', function(res) {
9 |
10 | if(res.length === 0) {
11 | $status.html('Sorry, but no cats are by you. I has a sad. Here, have this cat.
');
12 | return;
13 | }
14 | var result = 'I found these cats:';
15 | res.forEach(function(cat) {
16 | result += '- '+cat.name+'
';
17 | });
18 | result += '
';
19 | $status.html(result);
20 |
21 | });
22 |
23 | }, function(err) {
24 | $status.html('I\'m sorry, but I was unable to get your location. Blame Apple.');
25 | });
26 | });
--------------------------------------------------------------------------------
/geotest/client/map.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Map Demo
12 |
13 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/geotest/client/near.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Cats near you?
12 |
13 |
14 | Attempting to find your location...
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/geotest/common/models/cat.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Cat) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/geotest/common/models/cat.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Cat",
3 | "base": "PersistedModel",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true
7 | },
8 | "properties": {
9 | "name": {
10 | "type": "string",
11 | "required": true
12 | },
13 | "location": {
14 | "type": "geopoint",
15 | "required": true
16 | }
17 | },
18 | "validations": [],
19 | "relations": {},
20 | "acls": [],
21 | "methods": {}
22 | }
23 |
--------------------------------------------------------------------------------
/geotest/common/models/localmongo.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Localmongo) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/geotest/fakedata.txt:
--------------------------------------------------------------------------------
1 | {
2 | "name": "san fran cat",
3 | "location": {
4 | "lat": 37.77493,
5 | "lng": -122.41942
6 | }
7 | }
8 |
9 | {
10 | "name": "paris cat",
11 | "location": {
12 | "lat": 48.87146,
13 | "lng": 2.355
14 | }
15 | }
16 | {
17 | "name": "home cat",
18 | "location": {
19 | "lat": 30.22996,
20 | "lng": -92.05052
21 | }
22 | }
23 | {
24 | "name": "dallas cat",
25 | "location": {
26 | "lat": 32.68500,
27 | "lng": -96.73069
28 | }
29 | }
30 |
31 | Sorted by closeness to home
32 |
33 | http://localhost:3000/api/Cats/?filter[where][location][near]=30.22996,-92.05052
34 |
35 | home 30.22996 -92.05052
36 |
37 | Not working:
38 |
39 | http://localhost:3000/api/Cats/?filter[where][and][0][location][near]=30.22996,-92.05052&filter[where][and][1][maxdistance][lt]=2000
--------------------------------------------------------------------------------
/geotest/memory.db:
--------------------------------------------------------------------------------
1 | {
2 | "ids": {
3 | "User": 1,
4 | "AccessToken": 1,
5 | "ACL": 1,
6 | "RoleMapping": 1,
7 | "Role": 1,
8 | "Cat": 5
9 | },
10 | "models": {
11 | "User": {},
12 | "AccessToken": {},
13 | "ACL": {},
14 | "RoleMapping": {},
15 | "Role": {},
16 | "Cat": {
17 | "1": "{\"name\":\"paris cat\",\"location\":{\"lat\":48.87146,\"lng\":2.355},\"id\":1}",
18 | "2": "{\"name\":\"san fran cat\",\"location\":{\"lat\":37.77493,\"lng\":-122.41942},\"id\":2}",
19 | "3": "{\"name\":\"home cat\",\"location\":{\"lat\":30.22996,\"lng\":-92.05052},\"id\":3}",
20 | "4": "{\"name\":\"dallas cat\",\"location\":{\"lat\":32.685,\"lng\":-96.73069},\"id\":4}"
21 | }
22 | }
23 | }
--------------------------------------------------------------------------------
/geotest/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "geotest",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "start": "node .",
7 | "pretest": "jshint .",
8 | "posttest": "nsp check"
9 | },
10 | "dependencies": {
11 | "compression": "^1.0.3",
12 | "cors": "^2.5.2",
13 | "helmet": "^0.14.0",
14 | "loopback": "^2.22.0",
15 | "loopback-boot": "^2.6.5",
16 | "loopback-component-explorer": "^2.4.0",
17 | "loopback-connector-mongodb": "^1.13.3",
18 | "loopback-datasource-juggler": "^2.39.0",
19 | "serve-favicon": "^2.0.1"
20 | },
21 | "devDependencies": {
22 | "jshint": "^2.5.6",
23 | "nsp": "^2.1.0"
24 | },
25 | "repository": {
26 | "type": "",
27 | "url": ""
28 | },
29 | "description": "geotest"
30 | }
31 |
--------------------------------------------------------------------------------
/geotest/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | module.exports = function enableAuthentication(server) {
2 | // enable authentication
3 | server.enableAuth();
4 | };
5 |
--------------------------------------------------------------------------------
/geotest/server/boot/root.js:
--------------------------------------------------------------------------------
1 | var loopback = require('loopback');
2 |
3 | module.exports = function(server) {
4 | // Install a `/` route that returns server status
5 | var router = server.loopback.Router();
6 | router.get('/', server.loopback.status());
7 |
8 | router.get('/test', function(req, res) {
9 |
10 | server.models.Cat.find({where: {location: {maxDistance:2, near: {lat: 30.22996, lng: -92.05052}}}}, console.log);
11 |
12 | res.send('done');
13 | });
14 |
15 |
16 | server.use(router);
17 | };
18 |
--------------------------------------------------------------------------------
/geotest/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/geotest/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": {
7 | "enableHttpContext": false
8 | },
9 | "rest": {
10 | "normalizeHttpPath": false,
11 | "xml": false
12 | },
13 | "json": {
14 | "strict": false,
15 | "limit": "100kb"
16 | },
17 | "urlencoded": {
18 | "extended": true,
19 | "limit": "100kb"
20 | },
21 | "cors": false,
22 | "errorHandler": {
23 | "disableStackTrace": false
24 | }
25 | },
26 | "legacyExplorer": false
27 | }
28 |
--------------------------------------------------------------------------------
/geotest/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "memory",
5 | "file": "memory.db"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/geotest/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | },
14 | "helmet#xssFilter": {},
15 | "helmet#frameguard": {
16 | "params": [
17 | "deny"
18 | ]
19 | },
20 | "helmet#hsts": {
21 | "params": {
22 | "maxAge": 0,
23 | "includeSubdomains": true
24 | }
25 | },
26 | "helmet#hidePoweredBy": {},
27 | "helmet#ieNoOpen": {},
28 | "helmet#noSniff": {},
29 | "helmet#noCache": {
30 | "enabled": false
31 | }
32 | },
33 | "session": {},
34 | "auth": {},
35 | "parse": {},
36 | "routes": {
37 | "loopback#rest": {
38 | "paths": [
39 | "${restApiRoot}"
40 | ]
41 | }
42 | },
43 | "files": {
44 | "loopback#static":{
45 | "params":"$!../client"
46 | }
47 | },
48 | "final": {
49 | "loopback#urlNotFound": {}
50 | },
51 | "final:after": {
52 | "loopback#errorHandler": {}
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/geotest/server/middleware.production.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "loopback#errorHandler": {
4 | "params": {
5 | "includeStack": false
6 | }
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/geotest/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "db"
18 | },
19 | "AccessToken": {
20 | "dataSource": "db",
21 | "public": false
22 | },
23 | "ACL": {
24 | "dataSource": "db",
25 | "public": false
26 | },
27 | "RoleMapping": {
28 | "dataSource": "db",
29 | "public": false
30 | },
31 | "Role": {
32 | "dataSource": "db",
33 | "public": false
34 | },
35 | "Cat": {
36 | "dataSource": "db",
37 | "public": true,
38 | "$promise": {},
39 | "$resolved": true
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/geotest/server/server.js:
--------------------------------------------------------------------------------
1 | var loopback = require('loopback');
2 | var boot = require('loopback-boot');
3 |
4 | var app = module.exports = loopback();
5 |
6 | app.start = function() {
7 | // start the web server
8 | return app.listen(function() {
9 | app.emit('started');
10 | var baseUrl = app.get('url').replace(/\/$/, '');
11 | console.log('Web server listening at: %s', baseUrl);
12 | if (app.get('loopback-component-explorer')) {
13 | var explorerPath = app.get('loopback-component-explorer').mountPath;
14 | console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
15 | }
16 | });
17 | };
18 |
19 | // Bootstrap the application, configure models, datasources and middleware.
20 | // Sub-apps like REST API are mounted via boot scripts.
21 | boot(app, __dirname, function(err) {
22 | if (err) throw err;
23 |
24 | // start the server if `$ node server.js`
25 | if (require.main === module)
26 | app.start();
27 | });
28 |
--------------------------------------------------------------------------------
/ormdemo/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/ormdemo/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/ormdemo/.jshintignore:
--------------------------------------------------------------------------------
1 | /client/
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/ormdemo/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "eqeqeq": true,
7 | "eqnull": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": "nofunc",
11 | "newcap": true,
12 | "nonew": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "trailing": true,
19 | "sub": true,
20 | "maxlen": 80
21 | }
22 |
--------------------------------------------------------------------------------
/ormdemo/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/ormdemo/README.md:
--------------------------------------------------------------------------------
1 | # My Application
2 |
3 | The project is generated by [LoopBack](http://loopback.io).
--------------------------------------------------------------------------------
/ormdemo/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/ormdemo/common/models/part.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Part) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/ormdemo/common/models/part.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Part",
3 | "plural": "Parts",
4 | "base": "PersistedModel",
5 | "idInjection": true,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "name": {
11 | "type": "string"
12 | }
13 | },
14 | "validations": [],
15 | "relations": {
16 | "products": {
17 | "type": "hasAndBelongsToMany",
18 | "model": "Product",
19 | "foreignKey": ""
20 | }
21 | },
22 | "acls": [],
23 | "methods": {}
24 | }
25 |
--------------------------------------------------------------------------------
/ormdemo/common/models/product.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Product) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/ormdemo/common/models/product.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "Product",
3 | "plural": "Products",
4 | "base": "PersistedModel",
5 | "idInjection": true,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "name": {
11 | "type": "string"
12 | },
13 | "price": {
14 | "type": "number"
15 | }
16 | },
17 | "validations": [],
18 | "relations": {
19 | "parts": {
20 | "type": "hasAndBelongsToMany",
21 | "model": "Part",
22 | "foreignKey": ""
23 | }
24 | },
25 | "acls": [],
26 | "methods": {}
27 | }
28 |
--------------------------------------------------------------------------------
/ormdemo/common/models/test.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Test) {
2 |
3 | };
4 |
--------------------------------------------------------------------------------
/ormdemo/common/models/test.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test",
3 | "base": "PersistedModel",
4 | "strict": false,
5 | "idInjection": false,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "name": {
11 | "type": "string"
12 | }
13 | },
14 | "validations": [],
15 | "relations": {},
16 | "acls": [],
17 | "methods": {}
18 | }
19 |
--------------------------------------------------------------------------------
/ormdemo/data.db:
--------------------------------------------------------------------------------
1 | {
2 | "ids": {
3 | "User": 1,
4 | "AccessToken": 1,
5 | "ACL": 1,
6 | "RoleMapping": 1,
7 | "Role": 1,
8 | "Product": 5,
9 | "Part": 4
10 | },
11 | "models": {
12 | "User": {},
13 | "AccessToken": {},
14 | "ACL": {},
15 | "RoleMapping": {},
16 | "Role": {},
17 | "Product": {
18 | "1": "{\"name\":\"productAlpha!\",\"price\":90,\"id\":1}",
19 | "4": "{\"name\":\"moon\",\"price\":9,\"id\":4}"
20 | },
21 | "Part": {
22 | "1": "{\"name\":\"partA!\",\"id\":1}",
23 | "3": "{\"name\":\"partb\",\"id\":3}"
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/ormdemo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ormdemo",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "start": "node .",
7 | "pretest": "jshint .",
8 | "posttest": "nsp check"
9 | },
10 | "dependencies": {
11 | "body-parser": "^1.15.0",
12 | "compression": "^1.0.3",
13 | "cors": "^2.5.2",
14 | "express-handlebars": "^2.0.1",
15 | "helmet": "^0.14.0",
16 | "loopback": "^2.22.0",
17 | "loopback-boot": "^2.6.5",
18 | "loopback-component-explorer": "^2.1.0",
19 | "loopback-connector-mongodb": "^1.13.3",
20 | "loopback-datasource-juggler": "^2.39.0",
21 | "serve-favicon": "^2.0.1"
22 | },
23 | "devDependencies": {
24 | "jshint": "^2.5.6",
25 | "nsp": "^2.1.0"
26 | },
27 | "repository": {
28 | "type": "",
29 | "url": ""
30 | },
31 | "description": "ormdemo"
32 | }
33 |
--------------------------------------------------------------------------------
/ormdemo/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | module.exports = function enableAuthentication(server) {
2 | // enable authentication
3 | server.enableAuth();
4 | };
5 |
--------------------------------------------------------------------------------
/ormdemo/server/boot/root.js:
--------------------------------------------------------------------------------
1 | module.exports = function(server) {
2 | // Install a `/` route that returns server status
3 | /*
4 | var router = server.loopback.Router();
5 | router.get('/', server.loopback.status());
6 | server.use(router);
7 | */
8 | };
9 |
--------------------------------------------------------------------------------
/ormdemo/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/ormdemo/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": {
7 | "enableHttpContext": false
8 | },
9 | "rest": {
10 | "normalizeHttpPath": false,
11 | "xml": false
12 | },
13 | "json": {
14 | "strict": false,
15 | "limit": "100kb"
16 | },
17 | "urlencoded": {
18 | "extended": true,
19 | "limit": "100kb"
20 | },
21 | "cors": false,
22 | "errorHandler": {
23 | "disableStackTrace": false
24 | }
25 | },
26 | "legacyExplorer": false
27 | }
28 |
--------------------------------------------------------------------------------
/ormdemo/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "memory",
5 | "file": "data.db"
6 | },
7 | "mongodatasource": {
8 | "database": "ormdemo",
9 | "name": "mongodatasource",
10 | "connector": "mongodb"
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/ormdemo/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | },
14 | "helmet#xssFilter": {},
15 | "helmet#frameguard": {
16 | "params": [
17 | "deny"
18 | ]
19 | },
20 | "helmet#hsts": {
21 | "params": {
22 | "maxAge": 0,
23 | "includeSubdomains": true
24 | }
25 | },
26 | "helmet#hidePoweredBy": {},
27 | "helmet#ieNoOpen": {},
28 | "helmet#noSniff": {},
29 | "helmet#noCache": {
30 | "enabled": false
31 | }
32 | },
33 | "session": {},
34 | "auth": {},
35 | "parse": {},
36 | "routes": {
37 | "loopback#rest": {
38 | "paths": [
39 | "${restApiRoot}"
40 | ]
41 | }
42 | },
43 | "files": {
44 | "loopback#static": {
45 | "params": "$!./public"
46 | }
47 | },
48 | "final": {
49 | "loopback#urlNotFound": {}
50 | },
51 | "final:after": {
52 | "loopback#errorHandler": {}
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/ormdemo/server/middleware.production.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "loopback#errorHandler": {
4 | "params": {
5 | "includeStack": false
6 | }
7 | }
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/ormdemo/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "db"
18 | },
19 | "AccessToken": {
20 | "dataSource": "db",
21 | "public": false
22 | },
23 | "ACL": {
24 | "dataSource": "db",
25 | "public": false
26 | },
27 | "RoleMapping": {
28 | "dataSource": "db",
29 | "public": false
30 | },
31 | "Role": {
32 | "dataSource": "db",
33 | "public": false
34 | },
35 | "Product": {
36 | "dataSource": "mongodatasource",
37 | "public": true,
38 | "$promise": {},
39 | "$resolved": true
40 | },
41 | "Part": {
42 | "dataSource": "mongodatasource",
43 | "public": true,
44 | "$promise": {},
45 | "$resolved": true
46 | },
47 | "test": {
48 | "dataSource": "mongodatasource",
49 | "public": true,
50 | "$promise": {},
51 | "$resolved": true
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/ormdemo/server/public/css/styles.css:
--------------------------------------------------------------------------------
1 | table {
2 | width: 400px;
3 | }
4 |
5 | label {
6 | width: 75px;
7 | display: inline-block;
8 | }
--------------------------------------------------------------------------------
/ormdemo/server/server.js:
--------------------------------------------------------------------------------
1 | var loopback = require('loopback');
2 | var boot = require('loopback-boot');
3 |
4 | var app = module.exports = loopback();
5 | var bodyParser = require('body-parser');
6 | app.use(bodyParser.urlencoded({ extended: true }));
7 |
8 | var exphbs = require('express-handlebars');
9 |
10 | // We customize layoutsDir and views (few lines below) due to confusion of paths by default
11 | var hbs = exphbs.create({
12 | defaultLayout:'main',
13 | layoutsDir:__dirname+'/views/layouts',
14 | helpers:{
15 | ifSelected:function(product,partid) {
16 | if(!product) return '';
17 | var parts = product.parts();
18 | for(var i=0;iEdit
2 |
3 |
21 |
--------------------------------------------------------------------------------
/ormdemo/server/views/editpart.handlebars:
--------------------------------------------------------------------------------
1 | Edit
2 |
3 |
10 |
--------------------------------------------------------------------------------
/ormdemo/server/views/index.handlebars:
--------------------------------------------------------------------------------
1 | Products
2 |
3 |
4 |
5 |
6 | Name |
7 | Price |
8 | |
9 |
10 |
11 |
12 | {{#each products}}
13 |
14 | {{name}} |
15 | {{price}} |
16 | Delete |
17 |
18 | {{/each}}
19 |
20 |
21 |
22 |
23 | Add New Product
24 |
25 |
26 | Parts
27 |
28 |
29 |
30 |
31 | Name |
32 | |
33 |
34 |
35 |
36 | {{#each parts}}
37 |
38 | {{name}} |
39 | Delete |
40 |
41 | {{/each}}
42 |
43 |
44 |
45 |
46 | Add New Part
47 |
--------------------------------------------------------------------------------
/ormdemo/server/views/layouts/main.handlebars:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | {{{body}}}
9 |
10 |
11 |
--------------------------------------------------------------------------------
/simpleauthdemo/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/simpleauthdemo/.eslintignore:
--------------------------------------------------------------------------------
1 | /client/
--------------------------------------------------------------------------------
/simpleauthdemo/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "loopback"
3 | }
--------------------------------------------------------------------------------
/simpleauthdemo/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/simpleauthdemo/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/simpleauthdemo/README.md:
--------------------------------------------------------------------------------
1 | # Simple Authentication Demo
2 |
3 | Blog post coming soon!
--------------------------------------------------------------------------------
/simpleauthdemo/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/simpleauthdemo/common/models/appuser.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Appuser) {
4 |
5 | };
6 |
--------------------------------------------------------------------------------
/simpleauthdemo/common/models/appuser.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "appuser",
3 | "base": "User",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true
7 | },
8 | "properties": {},
9 | "validations": [],
10 | "relations": {},
11 | "acls": [],
12 | "methods": {}
13 | }
14 |
--------------------------------------------------------------------------------
/simpleauthdemo/common/models/post.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(Post) {
4 |
5 | Post.beforeRemote('create', function(ctx, instance, next) {
6 | console.log('before create');
7 | //override created
8 | ctx.args.data.created = new Date();
9 | //set creator to current user
10 | ctx.args.data.ownerId = ctx.req.accessToken.userId;
11 |
12 | next();
13 | });
14 | };
15 |
16 |
--------------------------------------------------------------------------------
/simpleauthdemo/common/models/post.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "post",
3 | "base": "PersistedModel",
4 | "idInjection": true,
5 | "options": {
6 | "validateUpsert": true
7 | },
8 | "properties": {
9 | "created": {
10 | "type": "date",
11 | "required": false
12 | },
13 | "text": {
14 | "type": "string",
15 | "required": true
16 | }
17 | },
18 | "validations": [],
19 | "relations": {
20 | "creator": {
21 | "type": "belongsTo",
22 | "model": "appuser",
23 | "foreignKey": "ownerId"
24 | }
25 | },
26 | "acls": [
27 | {
28 | "accessType": "*",
29 | "principalType": "ROLE",
30 | "principalId": "$everyone",
31 | "permission": "DENY"
32 | },
33 | {
34 | "accessType": "EXECUTE",
35 | "principalType": "ROLE",
36 | "principalId": "$authenticated",
37 | "permission": "ALLOW",
38 | "property": "create"
39 | },
40 | {
41 | "accessType": "EXECUTE",
42 | "principalType": "ROLE",
43 | "principalId": "$owner",
44 | "permission": "ALLOW",
45 | "property": ["updateAttributes","deleteById"]
46 | },
47 | {
48 | "accessType": "READ",
49 | "principalType": "ROLE",
50 | "principalId": "$everyone",
51 | "permission": "ALLOW"
52 | }
53 | ],
54 | "methods": {}
55 | }
56 |
--------------------------------------------------------------------------------
/simpleauthdemo/data.db:
--------------------------------------------------------------------------------
1 | {
2 | "ids": {
3 | "User": 1,
4 | "AccessToken": 10,
5 | "ACL": 1,
6 | "RoleMapping": 1,
7 | "Role": 1,
8 | "post": 23,
9 | "appuser": 5
10 | },
11 | "models": {
12 | "User": {},
13 | "AccessToken": {
14 | "AqL45B6g9iiMcTv8LFGuGFSsUuYPVawCBo2ugDpQT43ZmdSWTjJ9bNYc7mloBaD5": "{\"id\":\"AqL45B6g9iiMcTv8LFGuGFSsUuYPVawCBo2ugDpQT43ZmdSWTjJ9bNYc7mloBaD5\",\"ttl\":1209600,\"created\":\"2016-11-07T17:14:41.616Z\",\"userId\":1}",
15 | "0DVkQecyU4mCDMxpJyvJ9GQbgZhjlmoWJOOuEGLVFH4K4xvbkYlCcLEdRDGZceC1": "{\"id\":\"0DVkQecyU4mCDMxpJyvJ9GQbgZhjlmoWJOOuEGLVFH4K4xvbkYlCcLEdRDGZceC1\",\"ttl\":1209600,\"created\":\"2016-11-07T18:30:59.622Z\",\"userId\":1}",
16 | "BQJGfxNQVif2Owyb9LqjnQslTADYlXLayjYDNpWLY3imKUWNlcGxCvTaBx2ItM0L": "{\"id\":\"BQJGfxNQVif2Owyb9LqjnQslTADYlXLayjYDNpWLY3imKUWNlcGxCvTaBx2ItM0L\",\"ttl\":1209600,\"created\":\"2016-11-07T18:54:50.180Z\",\"userId\":1}",
17 | "RuJRBDtCxMrnmiFQnng7EFByTMop6pc1lLNX7BDxFMBXBHEes6FUngWIu9Wh7rDD": "{\"id\":\"RuJRBDtCxMrnmiFQnng7EFByTMop6pc1lLNX7BDxFMBXBHEes6FUngWIu9Wh7rDD\",\"ttl\":1209600,\"created\":\"2016-11-08T20:09:55.649Z\",\"userId\":3}",
18 | "ASfG7j6rJu2CQn1ywq5KcVxstqEZCazBOdWv0QCqFoECP05Ggom4yDPyQtFgab2g": "{\"id\":\"ASfG7j6rJu2CQn1ywq5KcVxstqEZCazBOdWv0QCqFoECP05Ggom4yDPyQtFgab2g\",\"ttl\":1209600,\"created\":\"2016-11-08T20:15:14.322Z\",\"userId\":4}",
19 | "yW4ZOzNS3JGWzAztnfydCQUx6yG9AEqZPdcYzOva78VviIGnUSovEO4lACwrRin9": "{\"id\":\"yW4ZOzNS3JGWzAztnfydCQUx6yG9AEqZPdcYzOva78VviIGnUSovEO4lACwrRin9\",\"ttl\":1209600,\"created\":\"2016-11-08T23:07:33.274Z\",\"userId\":3}",
20 | "7JDVRr7Nxk4kZTu0XjDRNalVzJrFg83dsqvmy2WzWQKKJMCKUipid98n9cMtjNhh": "{\"id\":\"7JDVRr7Nxk4kZTu0XjDRNalVzJrFg83dsqvmy2WzWQKKJMCKUipid98n9cMtjNhh\",\"ttl\":1209600,\"created\":\"2016-11-08T23:08:04.553Z\",\"userId\":3}",
21 | "K62zp82lb0B5BvcmgrOL1Wo4Yo2nGShD2sPqTUEziDgryfF78HeT3GGW269PqmYB": "{\"id\":\"K62zp82lb0B5BvcmgrOL1Wo4Yo2nGShD2sPqTUEziDgryfF78HeT3GGW269PqmYB\",\"ttl\":1209600,\"created\":\"2016-11-08T23:14:50.980Z\",\"userId\":3}",
22 | "4HWCh6TEYNRzCVicpSN64ndggyJWeDu0I7kEDTxTsqwjEyZkM16MlwiCIfu8cs35": "{\"id\":\"4HWCh6TEYNRzCVicpSN64ndggyJWeDu0I7kEDTxTsqwjEyZkM16MlwiCIfu8cs35\",\"ttl\":1209600,\"created\":\"2016-11-08T23:20:06.158Z\",\"userId\":3}"
23 | },
24 | "ACL": {},
25 | "RoleMapping": {},
26 | "Role": {},
27 | "post": {
28 | "16": "{\"created\":\"2016-11-07T20:07:21.433Z\",\"text\":\"strsddksjdksjsdkjing\",\"ownerId\":1,\"id\":16}",
29 | "17": "{\"created\":\"2016-11-08T16:22:13.781Z\",\"text\":\"test on the 8th\",\"ownerId\":1,\"id\":17}",
30 | "18": "{\"created\":\"2016-11-08T16:27:18.115Z\",\"text\":\"test on the 8th part deux\",\"ownerId\":1,\"id\":18}",
31 | "19": "{\"created\":\"2016-11-08T16:36:07.004Z\",\"text\":\"test on the 8th part three\",\"ownerId\":1,\"id\":19}",
32 | "20": "{\"created\":\"2016-11-08T16:37:39.035Z\",\"text\":\"test on the 8th part 4\",\"ownerId\":1,\"id\":20}",
33 | "21": "{\"created\":\"2016-11-08T16:57:48.601Z\",\"text\":\"sMOOOOOOOtring\",\"ownerId\":1,\"id\":21}",
34 | "22": "{\"created\":\"2016-11-08T23:20:10.447Z\",\"text\":\"foo\",\"ownerId\":3,\"id\":22}"
35 | },
36 | "appuser": {
37 | "1": "{\"password\":\"$2a$10$64cmhn7nw4TZnAoGJQJZket3AulLKemhDdOObhvaxHjPuxXWapEcW\",\"email\":\"user1@gmail.com\",\"id\":1}",
38 | "2": "{\"password\":\"$2a$10$SIoKTp5QrPJubJ9IQS799.p9PVI1.hEvQwBe8ip3oUoBafWKgZS3u\",\"email\":\"user2@gmail.com\",\"id\":2}",
39 | "3": "{\"password\":\"$2a$10$xLnnRgb9e6fF90bSw55lD.Myp.zmDSdAMaQrxsngXr69DhG6xlqqS\",\"email\":\"user3@gmail.com\",\"id\":3}",
40 | "4": "{\"password\":\"$2a$10$xxjL3x7/WXNhykLj0o69nu/Ly/obXQ8dFXtDJJr6z54i7oth2J6oy\",\"email\":\"user4@gmail.com\",\"id\":4}"
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/simpleauthdemo/notes.txt:
--------------------------------------------------------------------------------
1 | Need to extend User (done)
2 | Need to hide User (public: false)
3 |
4 | No way to automatically say, "when making ob, set owner to me"
5 | Link A to B(where B extends user) * thats the magic
6 |
7 |
8 | the object X belongs to me if:
9 |
10 | [12:26]
11 | a) it has a relation to a model that extends user (and obviously it points to me)
12 |
13 | [12:26]
14 | b) it has a simple property called userId where the val matches my user ID
15 |
16 | [12:26]
17 | c) ditto for "owner"
18 |
19 |
20 | When locking down a method - how do you know the names?
21 | this list - http://apidocs.strongloop.com/loopback/#persistedmodel
22 |
23 | beforeSave, set to currentuser
24 |
25 | auth req error even though logged in
26 |
--------------------------------------------------------------------------------
/simpleauthdemo/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "simpleauthdemo",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "lint": "eslint .",
7 | "start": "node .",
8 | "posttest": "npm run lint && nsp check"
9 | },
10 | "dependencies": {
11 | "compression": "^1.0.3",
12 | "cors": "^2.5.2",
13 | "helmet": "^1.3.0",
14 | "loopback-boot": "^2.6.5",
15 | "loopback-component-explorer": "^2.4.0",
16 | "serve-favicon": "^2.0.1",
17 | "strong-error-handler": "^1.0.1",
18 | "loopback-datasource-juggler": "^2.39.0",
19 | "loopback": "^2.22.0"
20 | },
21 | "devDependencies": {
22 | "eslint": "^2.13.1",
23 | "eslint-config-loopback": "^4.0.0",
24 | "nsp": "^2.1.0"
25 | },
26 | "repository": {
27 | "type": "",
28 | "url": ""
29 | },
30 | "license": "UNLICENSED",
31 | "description": "simpleauthdemo"
32 | }
33 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/boot/authentication.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function enableAuthentication(server) {
4 | // enable authentication
5 | server.enableAuth();
6 | };
7 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/boot/root.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | module.exports = function(server) {
4 | // Install a `/` route that returns server status
5 | var router = server.loopback.Router();
6 | //router.get('/', server.loopback.status());
7 | server.use(router);
8 | };
9 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/component-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "loopback-component-explorer": {
3 | "mountPath": "/explorer"
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/config.json:
--------------------------------------------------------------------------------
1 | {
2 | "restApiRoot": "/api",
3 | "host": "0.0.0.0",
4 | "port": 3000,
5 | "remoting": {
6 | "context": false,
7 | "rest": {
8 | "normalizeHttpPath": false,
9 | "xml": false
10 | },
11 | "json": {
12 | "strict": false,
13 | "limit": "100kb"
14 | },
15 | "urlencoded": {
16 | "extended": true,
17 | "limit": "100kb"
18 | },
19 | "cors": false,
20 | "handleErrors": false
21 | },
22 | "legacyExplorer": false
23 | }
24 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/datasources.json:
--------------------------------------------------------------------------------
1 | {
2 | "db": {
3 | "name": "db",
4 | "connector": "memory",
5 | "file": "data.db"
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/middleware.development.json:
--------------------------------------------------------------------------------
1 | {
2 | "final:after": {
3 | "strong-error-handler": {
4 | "params": {
5 | "debug": true,
6 | "log": true
7 | }
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/middleware.json:
--------------------------------------------------------------------------------
1 | {
2 | "initial:before": {
3 | "loopback#favicon": {}
4 | },
5 | "initial": {
6 | "compression": {},
7 | "cors": {
8 | "params": {
9 | "origin": true,
10 | "credentials": true,
11 | "maxAge": 86400
12 | }
13 | },
14 | "helmet#xssFilter": {},
15 | "helmet#frameguard": {
16 | "params": [
17 | "deny"
18 | ]
19 | },
20 | "helmet#hsts": {
21 | "params": {
22 | "maxAge": 0,
23 | "includeSubdomains": true
24 | }
25 | },
26 | "helmet#hidePoweredBy": {},
27 | "helmet#ieNoOpen": {},
28 | "helmet#noSniff": {},
29 | "helmet#noCache": {
30 | "enabled": false
31 | }
32 | },
33 | "session": {},
34 | "auth": {},
35 | "parse": {},
36 | "routes": {
37 | "loopback#rest": {
38 | "paths": [
39 | "${restApiRoot}"
40 | ]
41 | }
42 | },
43 | "files": {
44 | "loopback#static": {
45 | "params": "$!../client"
46 | }
47 | },
48 | "final": {
49 | "loopback#urlNotFound": {}
50 | },
51 | "final:after": {
52 | "strong-error-handler": {}
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/model-config.json:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "sources": [
4 | "loopback/common/models",
5 | "loopback/server/models",
6 | "../common/models",
7 | "./models"
8 | ],
9 | "mixins": [
10 | "loopback/common/mixins",
11 | "loopback/server/mixins",
12 | "../common/mixins",
13 | "./mixins"
14 | ]
15 | },
16 | "User": {
17 | "dataSource": "db",
18 | "public": false
19 | },
20 | "AccessToken": {
21 | "dataSource": "db",
22 | "public": false
23 | },
24 | "ACL": {
25 | "dataSource": "db",
26 | "public": false
27 | },
28 | "RoleMapping": {
29 | "dataSource": "db",
30 | "public": false
31 | },
32 | "Role": {
33 | "dataSource": "db",
34 | "public": false
35 | },
36 | "post": {
37 | "dataSource": "db",
38 | "public": true
39 | },
40 | "appuser": {
41 | "dataSource": "db",
42 | "public": true
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/simpleauthdemo/server/server.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var loopback = require('loopback');
4 | var boot = require('loopback-boot');
5 |
6 | var app = module.exports = loopback();
7 |
8 | app.start = function() {
9 | // start the web server
10 | return app.listen(function() {
11 | app.emit('started');
12 | var baseUrl = app.get('url').replace(/\/$/, '');
13 | console.log('Web server listening at: %s', baseUrl);
14 | if (app.get('loopback-component-explorer')) {
15 | var explorerPath = app.get('loopback-component-explorer').mountPath;
16 | console.log('Browse your REST API at %s%s', baseUrl, explorerPath);
17 | }
18 | });
19 | };
20 |
21 | // Bootstrap the application, configure models, datasources and middleware.
22 | // Sub-apps like REST API are mounted via boot scripts.
23 | boot(app, __dirname, function(err) {
24 | if (err) throw err;
25 |
26 | // start the server if `$ node server.js`
27 | if (require.main === module)
28 | app.start();
29 | });
30 |
--------------------------------------------------------------------------------
/superlongscroll/.editorconfig:
--------------------------------------------------------------------------------
1 | # EditorConfig helps developers define and maintain consistent
2 | # coding styles between different editors and IDEs
3 | # http://editorconfig.org
4 |
5 | root = true
6 |
7 | [*]
8 | indent_style = space
9 | indent_size = 2
10 | end_of_line = lf
11 | charset = utf-8
12 | trim_trailing_whitespace = true
13 | insert_final_newline = true
14 |
--------------------------------------------------------------------------------
/superlongscroll/.gitignore:
--------------------------------------------------------------------------------
1 | *.csv
2 | *.dat
3 | *.iml
4 | *.log
5 | *.out
6 | *.pid
7 | *.seed
8 | *.sublime-*
9 | *.swo
10 | *.swp
11 | *.tgz
12 | *.xml
13 | .DS_Store
14 | .idea
15 | .project
16 | .strong-pm
17 | coverage
18 | node_modules
19 | npm-debug.log
20 |
--------------------------------------------------------------------------------
/superlongscroll/.jshintignore:
--------------------------------------------------------------------------------
1 | /client/
2 | /node_modules/
3 |
--------------------------------------------------------------------------------
/superlongscroll/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "node": true,
3 | "esnext": true,
4 | "bitwise": true,
5 | "camelcase": true,
6 | "eqeqeq": true,
7 | "eqnull": true,
8 | "immed": true,
9 | "indent": 2,
10 | "latedef": "nofunc",
11 | "newcap": true,
12 | "nonew": true,
13 | "noarg": true,
14 | "quotmark": "single",
15 | "regexp": true,
16 | "undef": true,
17 | "unused": false,
18 | "trailing": true,
19 | "sub": true,
20 | "maxlen": 80
21 | }
22 |
--------------------------------------------------------------------------------
/superlongscroll/.yo-rc.json:
--------------------------------------------------------------------------------
1 | {
2 | "generator-loopback": {}
3 | }
--------------------------------------------------------------------------------
/superlongscroll/client/README.md:
--------------------------------------------------------------------------------
1 | ## Client
2 |
3 | This is the place for your application front-end files.
4 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules/
2 | www/build/
3 | platforms/
4 | plugins/
5 | .DS_Store
6 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/.vscode/typings/cordova/cordova.d.ts:
--------------------------------------------------------------------------------
1 | // Type definitions for Apache Cordova
2 | // Project: http://cordova.apache.org
3 | // Definitions by: Microsoft Open Technologies Inc.
4 | // Definitions: https://github.com/borisyankov/DefinitelyTyped
5 | //
6 | // Copyright (c) Microsoft Open Technologies, Inc.
7 | // Licensed under the MIT license.
8 |
9 | interface Cordova {
10 | /** Invokes native functionality by specifying corresponding service name, action and optional parameters.
11 | * @param success A success callback function.
12 | * @param fail An error callback function.
13 | * @param service The service name to call on the native side (corresponds to a native class).
14 | * @param action The action name to call on the native side (generally corresponds to the native class method).
15 | * @param args An array of arguments to pass into the native environment.
16 | */
17 | exec(success: () => any, fail: () => any, service: string, action: string, args?: string[]): void;
18 | /** Gets the operating system name. */
19 | platformId: string;
20 | /** Gets Cordova framework version */
21 | version: string;
22 | /** Defines custom logic as a Cordova module. Other modules can later access it using module name provided. */
23 | define(moduleName: string, factory: (require: any, exports: any, module: any) => any): void;
24 | /** Access a Cordova module by name. */
25 | require(moduleName: string): any;
26 | /** Namespace for Cordova plugin functionality */
27 | plugins:CordovaPlugins;
28 | }
29 |
30 | interface CordovaPlugins {}
31 |
32 | interface Document {
33 | addEventListener(type: "deviceready", listener: (ev: Event) => any, useCapture?: boolean): void;
34 | addEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
35 | addEventListener(type: "resume", listener: (ev: Event) => any, useCapture?: boolean): void;
36 | addEventListener(type: "backbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
37 | addEventListener(type: "menubutton", listener: (ev: Event) => any, useCapture?: boolean): void;
38 | addEventListener(type: "searchbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
39 | addEventListener(type: "startcallbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
40 | addEventListener(type: "endcallbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
41 | addEventListener(type: "volumedownbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
42 | addEventListener(type: "volumeupbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
43 |
44 | removeEventListener(type: "deviceready", listener: (ev: Event) => any, useCapture?: boolean): void;
45 | removeEventListener(type: "pause", listener: (ev: Event) => any, useCapture?: boolean): void;
46 | removeEventListener(type: "resume", listener: (ev: Event) => any, useCapture?: boolean): void;
47 | removeEventListener(type: "backbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
48 | removeEventListener(type: "menubutton", listener: (ev: Event) => any, useCapture?: boolean): void;
49 | removeEventListener(type: "searchbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
50 | removeEventListener(type: "startcallbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
51 | removeEventListener(type: "endcallbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
52 | removeEventListener(type: "volumedownbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
53 | removeEventListener(type: "volumeupbutton", listener: (ev: Event) => any, useCapture?: boolean): void;
54 |
55 | addEventListener(type: string, listener: (ev: Event) => any, useCapture?: boolean): void;
56 | removeEventListener(type: string, listener: (ev: Event) => any, useCapture?: boolean): void;
57 | }
58 |
59 | interface Window {
60 | cordova:Cordova;
61 | }
62 |
63 | // cordova/argscheck module
64 | interface ArgsCheck {
65 | checkArgs(argsSpec: string, functionName: string, args: any[], callee?: any): void;
66 | getValue(value?: any, defaultValue?: any): any;
67 | enableChecks: boolean;
68 | }
69 |
70 | // cordova/urlutil module
71 | interface UrlUtil {
72 | makeAbsolute(url: string): string
73 | }
74 |
75 | /** Apache Cordova instance */
76 | declare var cordova: Cordova;
77 |
78 | declare module 'cordova' {
79 | export = cordova;
80 | }
81 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/app.ts:
--------------------------------------------------------------------------------
1 | import {App, Platform} from 'ionic-angular';
2 | import {StatusBar} from 'ionic-native';
3 | import {HomePage} from './pages/home/home';
4 |
5 |
6 | @App({
7 | template: '',
8 | config: {} // http://ionicframework.com/docs/v2/api/config/Config/
9 | })
10 | export class MyApp {
11 | rootPage: any = HomePage;
12 |
13 | constructor(platform: Platform) {
14 | platform.ready().then(() => {
15 | // Okay, so the platform is ready and our plugins are available.
16 | // Here you can do any higher level native things you might need.
17 | StatusBar.styleDefault();
18 | });
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/pages/home/home.html:
--------------------------------------------------------------------------------
1 |
2 |
3 | Home
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 | {{person.name}}
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/pages/home/home.scss:
--------------------------------------------------------------------------------
1 | .home {
2 |
3 | }
4 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/pages/home/home.ts:
--------------------------------------------------------------------------------
1 | import {Page} from 'ionic-angular';
2 | import {PeopleService} from '../../providers/people-service/people-service';
3 |
4 | @Page({
5 | templateUrl: 'build/pages/home/home.html',
6 | providers:[PeopleService]
7 |
8 | })
9 | export class HomePage {
10 | public people:any = [];
11 | private start:number=0;
12 |
13 | constructor(public peopleService:PeopleService) {
14 |
15 | this.loadPeople();
16 | }
17 |
18 | loadPeople() {
19 |
20 | return new Promise(resolve => {
21 |
22 | this.peopleService.load(this.start)
23 | .then(data => {
24 |
25 | for(let person of data) {
26 | this.people.push(person);
27 | }
28 |
29 | resolve(true);
30 |
31 | });
32 |
33 | });
34 |
35 | }
36 |
37 | doInfinite(infiniteScroll:any) {
38 | console.log('doInfinite, start is currently '+this.start);
39 | this.start+=50;
40 |
41 | this.loadPeople().then(()=>{
42 | infiniteScroll.complete();
43 | });
44 |
45 | }
46 |
47 | }
48 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/providers/people-service/people-service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from 'angular2/core';
2 | import {Http} from 'angular2/http';
3 | import 'rxjs/add/operator/map';
4 |
5 | /*
6 | Generated class for the PeopleService provider.
7 |
8 | See https://angular.io/docs/ts/latest/guide/dependency-injection.html
9 | for more info on providers and Angular 2 DI.
10 | */
11 | @Injectable()
12 | export class PeopleService {
13 |
14 | perpage:number = 50;
15 |
16 | constructor(public http: Http) {}
17 |
18 | load(start:number=0) {
19 |
20 | return new Promise(resolve => {
21 |
22 | this.http.get('http://192.168.4.13:3000/api/people?filter[limit]='+this.perpage+'&filter[skip]='+start)
23 | .map(res => res.json())
24 | .subscribe(data => {
25 |
26 | resolve(data);
27 |
28 | });
29 | });
30 | }
31 | }
32 |
33 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/theme/app.core.scss:
--------------------------------------------------------------------------------
1 | // http://ionicframework.com/docs/v2/theming/
2 |
3 |
4 | // App Shared Imports
5 | // --------------------------------------------------
6 | // These are the imports which make up the design of this app.
7 | // By default each design mode includes these shared imports.
8 | // App Shared Sass variables belong in app.variables.scss.
9 |
10 | @import '../pages/home/home';
11 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/theme/app.ios.scss:
--------------------------------------------------------------------------------
1 | // http://ionicframework.com/docs/v2/theming/
2 |
3 |
4 | // App Shared Variables
5 | // --------------------------------------------------
6 | // Shared Sass variables go in the app.variables.scss file
7 | @import 'app.variables';
8 |
9 |
10 | // App iOS Variables
11 | // --------------------------------------------------
12 | // iOS only Sass variables can go here
13 |
14 |
15 | // Ionic iOS Sass
16 | // --------------------------------------------------
17 | // Custom App variables must be declared before importing Ionic.
18 | // Ionic will use its default values when a custom variable isn't provided.
19 | @import 'ionic.ios';
20 |
21 |
22 | // App Shared Sass
23 | // --------------------------------------------------
24 | // All Sass files that make up this app goes into the app.core.scss file.
25 | // For simpler CSS overrides, custom app CSS must come after Ionic's CSS.
26 | @import 'app.core';
27 |
28 |
29 | // App iOS Only Sass
30 | // --------------------------------------------------
31 | // CSS that should only apply to the iOS app
32 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/theme/app.md.scss:
--------------------------------------------------------------------------------
1 | // http://ionicframework.com/docs/v2/theming/
2 |
3 |
4 | // App Shared Variables
5 | // --------------------------------------------------
6 | // Shared Sass variables go in the app.variables.scss file
7 | @import 'app.variables';
8 |
9 |
10 | // App Material Design Variables
11 | // --------------------------------------------------
12 | // Material Design only Sass variables can go here
13 |
14 |
15 | // Ionic Material Design Sass
16 | // --------------------------------------------------
17 | // Custom App variables must be declared before importing Ionic.
18 | // Ionic will use its default values when a custom variable isn't provided.
19 | @import 'ionic.md';
20 |
21 |
22 | // App Shared Sass
23 | // --------------------------------------------------
24 | // All Sass files that make up this app goes into the app.core.scss file.
25 | // For simpler CSS overrides, custom app CSS must come after Ionic's CSS.
26 | @import 'app.core';
27 |
28 |
29 | // App Material Design Only Sass
30 | // --------------------------------------------------
31 | // CSS that should only apply to the Material Design app
32 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/theme/app.variables.scss:
--------------------------------------------------------------------------------
1 | // http://ionicframework.com/docs/v2/theming/
2 |
3 | // Ionic Shared Functions
4 | // --------------------------------------------------
5 | // Makes Ionic Sass functions available to your App
6 |
7 | @import 'globals.core';
8 |
9 | // App Shared Variables
10 | // --------------------------------------------------
11 | // To customize the look and feel of this app, you can override
12 | // the Sass variables found in Ionic's source scss files. Setting
13 | // variables before Ionic's Sass will use these variables rather than
14 | // Ionic's default Sass variable values. App Shared Sass imports belong
15 | // in the app.core.scss file and not this file. Sass variables specific
16 | // to the mode belong in either the app.ios.scss or app.md.scss files.
17 |
18 |
19 | // App Shared Color Variables
20 | // --------------------------------------------------
21 | // It's highly recommended to change the default colors
22 | // to match your app's branding. Ionic uses a Sass map of
23 | // colors so you can add, rename and remove colors as needed.
24 | // The "primary" color is the only required color in the map.
25 | // Both iOS and MD colors can be further customized if colors
26 | // are different per mode.
27 |
28 | $colors: (
29 | primary: #387ef5,
30 | secondary: #32db64,
31 | danger: #f53d3d,
32 | light: #f4f4f4,
33 | dark: #222,
34 | favorite: #69BB7B
35 | );
36 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/app/theme/app.wp.scss:
--------------------------------------------------------------------------------
1 | // http://ionicframework.com/docs/v2/theming/
2 |
3 |
4 | // App Shared Variables
5 | // --------------------------------------------------
6 | // Shared Sass variables go in the app.variables.scss file
7 | @import 'app.variables';
8 |
9 |
10 | // App Windows Variables
11 | // --------------------------------------------------
12 | // Windows only Sass variables can go here
13 |
14 |
15 | // Ionic Windows Sass
16 | // --------------------------------------------------
17 | // Custom App variables must be declared before importing Ionic.
18 | // Ionic will use its default values when a custom variable isn't provided.
19 | @import "ionic.wp";
20 |
21 |
22 | // App Shared Sass
23 | // --------------------------------------------------
24 | // All Sass files that make up this app goes into the app.core.scss file.
25 | // For simpler CSS overrides, custom app CSS must come after Ionic's CSS.
26 | @import 'app.core';
27 |
28 |
29 | // App Windows Only Sass
30 | // --------------------------------------------------
31 | // CSS that should only apply to the Windows app
32 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | gulpWatch = require('gulp-watch'),
3 | del = require('del'),
4 | runSequence = require('run-sequence'),
5 | argv = process.argv;
6 |
7 |
8 | /**
9 | * Ionic hooks
10 | * Add ':before' or ':after' to any Ionic project command name to run the specified
11 | * tasks before or after the command.
12 | */
13 | gulp.task('serve:before', ['watch']);
14 | gulp.task('emulate:before', ['build']);
15 | gulp.task('deploy:before', ['build']);
16 | gulp.task('build:before', ['build']);
17 |
18 | // we want to 'watch' when livereloading
19 | var shouldWatch = argv.indexOf('-l') > -1 || argv.indexOf('--livereload') > -1;
20 | gulp.task('run:before', [shouldWatch ? 'watch' : 'build']);
21 |
22 | /**
23 | * Ionic Gulp tasks, for more information on each see
24 | * https://github.com/driftyco/ionic-gulp-tasks
25 | *
26 | * Using these will allow you to stay up to date if the default Ionic 2 build
27 | * changes, but you are of course welcome (and encouraged) to customize your
28 | * build however you see fit.
29 | */
30 | var buildBrowserify = require('ionic-gulp-browserify-typescript');
31 | var buildSass = require('ionic-gulp-sass-build');
32 | var copyHTML = require('ionic-gulp-html-copy');
33 | var copyFonts = require('ionic-gulp-fonts-copy');
34 | var copyScripts = require('ionic-gulp-scripts-copy');
35 |
36 | var isRelease = argv.indexOf('--release') > -1;
37 |
38 | gulp.task('watch', ['clean'], function(done){
39 | runSequence(
40 | ['sass', 'html', 'fonts', 'scripts'],
41 | function(){
42 | gulpWatch('app/**/*.scss', function(){ gulp.start('sass'); });
43 | gulpWatch('app/**/*.html', function(){ gulp.start('html'); });
44 | buildBrowserify({ watch: true }).on('end', done);
45 | }
46 | );
47 | });
48 |
49 | gulp.task('build', ['clean'], function(done){
50 | runSequence(
51 | ['sass', 'html', 'fonts', 'scripts'],
52 | function(){
53 | buildBrowserify({
54 | browserifyOptions: {
55 | debug: !isRelease
56 | }
57 | }).on('end', done);
58 | }
59 | );
60 | });
61 |
62 | gulp.task('sass', buildSass);
63 | gulp.task('html', copyHTML);
64 | gulp.task('fonts', copyFonts);
65 | gulp.task('scripts', copyScripts);
66 | gulp.task('clean', function(){
67 | return del('www/build');
68 | });
69 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/hooks/after_prepare/010_add_platform_class.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // Add Platform Class
4 | // v1.0
5 | // Automatically adds the platform class to the body tag
6 | // after the `prepare` command. By placing the platform CSS classes
7 | // directly in the HTML built for the platform, it speeds up
8 | // rendering the correct layout/style for the specific platform
9 | // instead of waiting for the JS to figure out the correct classes.
10 |
11 | var fs = require('fs');
12 | var path = require('path');
13 |
14 | var rootdir = process.argv[2];
15 |
16 | function addPlatformBodyTag(indexPath, platform) {
17 | // add the platform class to the body tag
18 | try {
19 | var platformClass = 'platform-' + platform;
20 | var cordovaClass = 'platform-cordova platform-webview';
21 |
22 | var html = fs.readFileSync(indexPath, 'utf8');
23 |
24 | var bodyTag = findBodyTag(html);
25 | if(!bodyTag) return; // no opening body tag, something's wrong
26 |
27 | if(bodyTag.indexOf(platformClass) > -1) return; // already added
28 |
29 | var newBodyTag = bodyTag;
30 |
31 | var classAttr = findClassAttr(bodyTag);
32 | if(classAttr) {
33 | // body tag has existing class attribute, add the classname
34 | var endingQuote = classAttr.substring(classAttr.length-1);
35 | var newClassAttr = classAttr.substring(0, classAttr.length-1);
36 | newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
37 | newBodyTag = bodyTag.replace(classAttr, newClassAttr);
38 |
39 | } else {
40 | // add class attribute to the body tag
41 | newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
42 | }
43 |
44 | html = html.replace(bodyTag, newBodyTag);
45 |
46 | fs.writeFileSync(indexPath, html, 'utf8');
47 |
48 | process.stdout.write('add to body class: ' + platformClass + '\n');
49 | } catch(e) {
50 | process.stdout.write(e);
51 | }
52 | }
53 |
54 | function findBodyTag(html) {
55 | // get the body tag
56 | try{
57 | return html.match(/])(.*?)>/gi)[0];
58 | }catch(e){}
59 | }
60 |
61 | function findClassAttr(bodyTag) {
62 | // get the body tag's class attribute
63 | try{
64 | return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
65 | }catch(e){}
66 | }
67 |
68 | if (rootdir) {
69 |
70 | // go through each of the platform directories that have been prepared
71 | var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);
72 |
73 | for(var x=0; x
2 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/typings/main.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 |
--------------------------------------------------------------------------------
/superlongscroll/client/app1/www/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Ionic
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
--------------------------------------------------------------------------------
/superlongscroll/client/simple/app.js:
--------------------------------------------------------------------------------
1 | var $backBtn, $fwdBtn;
2 | var $results;
3 |
4 | var currentPos = 0;
5 | var total;
6 |
7 | var perPage = 10;
8 |
9 | $(document).ready(function() {
10 | $backBtn = $("#goBackBtn");
11 | $fwdBtn = $("#goForwardBtn");
12 | $results = $("#results");
13 |
14 | //step one - how much crap do we have?
15 | $.get('http://localhost:3000/api/people/count', function(res) {
16 | total = res.count;
17 | console.log('count is '+total);
18 | },'json');
19 |
20 | fetchData();
21 |
22 | $backBtn.on('click', moveBack);
23 | $fwdBtn.on('click', moveForward);
24 |
25 | });
26 |
27 | function fetchData() {
28 |
29 | //first, disable both
30 | $backBtn.attr('disabled','disabled');
31 | $fwdBtn.attr('disabled','disabled');
32 |
33 | //hide results currently there
34 | $results.html('');
35 |
36 | //now fetch
37 | $.get('http://localhost:3000/api/people?filter[limit]='+perPage+'&filter[skip]='+currentPos, function(res) {
38 | renderData(res);
39 |
40 | if(currentPos > 0) $backBtn.removeAttr('disabled');
41 | if(currentPos + perPage < total) $fwdBtn.removeAttr('disabled');
42 | },'json');
43 |
44 | }
45 |
46 | //could(should) use a nice template lang
47 | function renderData(p) {
48 | s = '';
49 | p.forEach(function(person) {
50 | s += '
'+person.name+'
';
51 | });
52 | $results.html(s);
53 | }
54 |
55 | function moveBack() {
56 | currentPos -= perPage;
57 | fetchData();
58 | }
59 |
60 | function moveForward() {
61 | currentPos += perPage;
62 | fetchData();
63 | }
64 |
65 |
--------------------------------------------------------------------------------
/superlongscroll/client/simple/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | -
14 |
15 |
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/superlongscroll/common/models/note.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Note) {
2 | Note.greet = function(msg, cb) {
3 | process.nextTick(function() {
4 | msg = msg || 'world';
5 | cb(null, 'Hello ' + msg);
6 | });
7 | };
8 | };
9 |
--------------------------------------------------------------------------------
/superlongscroll/common/models/note.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "note",
3 | "properties": {
4 | "title": {
5 | "type": "string",
6 | "required": true
7 | },
8 | "content": {
9 | "type": "string"
10 | }
11 | },
12 | "validations": [],
13 | "relations": {},
14 | "acls": [],
15 | "methods": {
16 | "greet": {
17 | "isStatic": true,
18 | "accepts": [
19 | {
20 | "arg": "msg",
21 | "type": "string",
22 | "http": {
23 | "source": "query"
24 | }
25 | }
26 | ],
27 | "returns": {
28 | "arg": "greeting",
29 | "type": "string"
30 | },
31 | "http": {
32 | "verb": "get"
33 | }
34 | }
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/superlongscroll/common/models/person.js:
--------------------------------------------------------------------------------
1 | module.exports = function(Person) {
2 |
3 | Person.beforeRemote('find', function(ctx, instance, next) {
4 | if(!ctx.args.filter || !ctx.args.filter.limit) {
5 | console.log('forcing limit!');
6 | if(!ctx.args.filter) ctx.args.filter = {};
7 | ctx.args.filter.limit = 10;
8 | }
9 | next();
10 | });
11 | };
12 |
--------------------------------------------------------------------------------
/superlongscroll/common/models/person.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "person",
3 | "plural": "people",
4 | "base": "PersistedModel",
5 | "idInjection": true,
6 | "options": {
7 | "validateUpsert": true
8 | },
9 | "properties": {
10 | "name": {
11 | "type": "string",
12 | "required": true
13 | },
14 | "picture": {
15 | "type": "string",
16 | "required": true
17 | }
18 | },
19 | "validations": [],
20 | "relations": {},
21 | "acls": [],
22 | "methods": {}
23 | }
24 |
--------------------------------------------------------------------------------
/superlongscroll/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "superlongscroll",
3 | "version": "1.0.0",
4 | "main": "server/server.js",
5 | "scripts": {
6 | "start": "node .",
7 | "pretest": "jshint .",
8 | "posttest": "nsp check"
9 | },
10 | "dependencies": {
11 | "compression": "^1.0.3",
12 | "cors": "^2.5.2",
13 | "helmet": "^0.14.0",
14 | "loopback": "^2.22.0",
15 | "loopback-boot": "^2.6.5",
16 | "loopback-component-explorer": "^2.4.0",
17 | "loopback-datasource-juggler": "^2.39.0",
18 | "serve-favicon": "^2.0.1"
19 | },
20 | "devDependencies": {
21 | "jshint": "^2.5.6",
22 | "nsp": "^2.1.0"
23 | },
24 | "repository": {
25 | "type": "",
26 | "url": ""
27 | },
28 | "description": "superlongscroll"
29 | }
30 |
--------------------------------------------------------------------------------
/superlongscroll/server/boot/root.js:
--------------------------------------------------------------------------------
1 | module.exports = function(server) {
2 | // Install a `/` route that returns server status
3 | var router = server.loopback.Router();
4 | router.get('/', server.loopback.status());
5 |
6 | //crappy temp way to copy in a bunch of data
7 | var ucaseFirst = function(s) {
8 | return s.substring(0,1).toUpperCase() + s.substring(1);
9 | };
10 |
11 | /*
12 | router.get('/temp', function(req, res) {
13 |
14 | console.dir(server.models.person);
15 |
16 | var usersRaw = require('../users.json').results;
17 | var users = [];
18 | console.log('going to insert '+usersRaw.length+' users');
19 |
20 | for(var i=0;i