Skip to content

Commit c2ef254

Browse files
authored
Merge pull request #8 from neonexus/master
Added pagination helpers. Fixed create user action (added role). Removed some unused code. Updated NPM packages.
2 parents b6b0af6 + 318a531 commit c2ef254

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

57 files changed

+3454
-398
lines changed

.idea/README.md

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/codeStyles/codeStyleConfig.xml

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/runConfigurations/Run_Tests_w__Coverage.xml

Lines changed: 12 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.mocharc.yaml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
bail: false #stop on first error
22
async-only: true # require use of "done" cb or an async function (a Promise)
33
require:
4-
- 'test/hooks.js'
4+
- 'test/hooks.js' # starting point for tests
55
spec: 'test/**/*.test.js'
66
timeout: 10000 # Give Sails some breathing room... We are building schemas / data fixtures.
77
checkLeaks: true
88
global:
9-
- '_'
9+
- '_' # Lodash global
1010
- 'sails'
1111
- '__core-js_shared__'
1212
- 'Archive' # Sails' built-in archive
1313
- 'User'
1414
- 'Session'
1515
- 'RequestLog'
1616
- 'Log'
17+
- '__coverage__' # NYC coverage global

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ This repo is not installable via `npm`. Instead, Github provides a handy "Use th
2525
### Configuration
2626
In the `config` folder, there is `local.js.sample` file, which is meant to be copied to `local.js`. This file is ignored by Git, and intended for use in local development, not remote servers.
2727

28+
#### Want to configure the "X-Powered-By" header?
29+
Sails, by default, has middleware (akin to [Express.js Middleware](https://expressjs.com/en/guide/using-middleware.html), Sails is built on Express.js after all...). Inside of [`config/http.js`](config/http.js) we disable the default middleware, and create our own `X-Powered-By` header, using Express.js Middleware.
30+
2831
### Scripts built into [`package.json`](package.json):
2932

3033
| Command | Description
@@ -89,6 +92,29 @@ module.exports.bootstrap = function(next) {
8992
};
9093
```
9194

95+
## What about SEO?
96+
I recommend looking at [prerender.io](https://prerender.io). They offer a service (free up to 250 pages) that caches the end result of a JavaScript-rendered view (React, Vue, Angular), allowing search engines to crawl otherwise un-crawlable web views. You can use the service in a number of ways. One way, is to use the [prerender-node](https://www.npmjs.com/package/prerender-node) package. To use it with Sails, you'll have to add it to the [HTTP Middleware](https://sailsjs.com/documentation/concepts/middleware#?http-middleware). Here's a quick example:
97+
98+
```javascript
99+
middleware: {
100+
101+
order: [
102+
'cookieParser',
103+
'session',
104+
'bodyParser',
105+
'prerender', // reference our custom middleware found below
106+
'compress',
107+
'router',
108+
'assetLog',
109+
'www',
110+
'favicon'
111+
],
112+
113+
prerender: require('prerender-node').set('prerenderToken', 'YOUR_TOKEN')
114+
115+
}
116+
```
117+
92118
### Useful Links
93119

94120
+ [Sails Framework Documentation](https://sailsjs.com/get-started)

api/controllers/admin/create-user.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,11 @@ module.exports = {
2727
isEmail: true,
2828
required: true,
2929
maxLength: 191
30+
},
31+
32+
role: {
33+
type: 'string',
34+
defaultsTo: 'user'
3035
}
3136
},
3237

@@ -63,7 +68,7 @@ module.exports = {
6368
firstName: inputs.firstName,
6469
lastName: inputs.lastName,
6570
password: inputs.password,
66-
role: 'user',
71+
role: inputs.role,
6772
email: inputs.email
6873
}).meta({fetch: true}).exec((err, newUser) => {
6974
if (err) {

api/helpers/paginate-for-json.js

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
module.exports = {
2+
friendlyName: 'Paginate for JSON',
3+
4+
description: 'Expects the query from sails.helpers.paginateForQuery().',
5+
6+
inputs: {
7+
query: {
8+
description: 'This should be the value returned from sails.helpers.paginateForQuery()',
9+
type: 'json',
10+
required: true,
11+
// this is a custom validator, which returns true or false
12+
custom: (thisQuery) => (
13+
_.isObject(thisQuery) && _.isNumber(thisQuery.limit) &&
14+
_.isNumber(thisQuery.page) && _.isString(thisQuery.sort) &&
15+
_.isObject(thisQuery.where)
16+
)
17+
},
18+
19+
model: { // must be a reference to a Sails model, like User or sails.models.user
20+
type: 'ref',
21+
required: true
22+
},
23+
24+
objToWrap: { // the response to be given to the end-user
25+
type: 'json',
26+
required: true
27+
}
28+
},
29+
30+
exits: {},
31+
32+
fn: (inputs, exits) => {
33+
let query = inputs.query;
34+
35+
const limit = query.limit;
36+
const page = query.page;
37+
const sort = query.sort;
38+
39+
delete query.limit;
40+
delete query.page;
41+
delete query.skip;
42+
delete query.sort;
43+
44+
inputs.model.count(query).exec((err, totalCount) => {
45+
if (err) {
46+
throw new Error(err);
47+
}
48+
49+
let objToWrap = _.merge({}, inputs.objToWrap); // copy the object
50+
51+
objToWrap.totalFound = totalCount;
52+
objToWrap.totalPages = Math.ceil(totalCount / limit);
53+
objToWrap.limit = limit;
54+
objToWrap.page = page;
55+
objToWrap.sort = sort;
56+
57+
return exits.success(objToWrap);
58+
});
59+
}
60+
};

api/helpers/paginate-for-query.js

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
module.exports = {
2+
sync: true, // is a synchronous
3+
4+
friendlyName: 'Paginate for query',
5+
6+
description: 'Takes in pagination options, and returns query for .find() calls.',
7+
8+
inputs: {
9+
page: {
10+
type: 'number',
11+
defaultsTo: 1
12+
},
13+
limit: {
14+
type: 'number',
15+
defaultsTo: 25
16+
},
17+
sort: {
18+
type: 'string',
19+
defaultsTo: 'createdAt DESC'
20+
},
21+
where: {
22+
type: 'ref', // JavaScript reference to an object
23+
defaultsTo: null
24+
}
25+
},
26+
27+
exits: {},
28+
29+
fn: (inputs, exits) => {
30+
let baseObj = {
31+
limit: inputs.limit,
32+
page: inputs.page,
33+
skip: (inputs.page - 1) * inputs.limit,
34+
sort: inputs.sort,
35+
where: inputs.where
36+
};
37+
38+
if (!baseObj.where) {
39+
baseObj.where = {deletedAt: null};
40+
} else if (baseObj.where.sort && baseObj.sort === 'createdAt DESC') { // if sort is the default, and the where contains a sort, use the where.sort, otherwise, use inputs.sort
41+
baseObj.sort = baseObj.where.sort;
42+
delete baseObj.where.sort;
43+
}
44+
45+
return exits.success(baseObj);
46+
}
47+
};

assets/src/Admin/AdminRouter.jsx

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -18,43 +18,10 @@ import {UserProvider, UserConsumer} from '../data/userContext';
1818
class AdminRouter extends React.Component {
1919
constructor(props) {
2020
super(props);
21-
22-
// this.state = {
23-
// isAuthenticated: false,
24-
// user: sessionStorage.getItem('user')
25-
// };
26-
27-
// this.userLogin = this.userLogin.bind(this);
28-
// this.userLogout = this.userLogout.bind(this);
2921
}
3022

31-
// userLogin(user) {
32-
// this.setState({user, isAuthenticated: true});
33-
// sessionStorage.setItem('user', user);
34-
// }
35-
//
36-
// userLogout() {
37-
// this.setState({user: {}, isAuthenticated: false});
38-
// sessionStorage.removeItem('user');
39-
// }
40-
4123
render() {
42-
const that = this;
43-
4424
function RenderOrLogin(props) {
45-
// if (that.state.isAuthenticated) {
46-
// return props.children;
47-
// }
48-
49-
// return (
50-
// <Redirect
51-
// to={{
52-
// pathname: '/admin/login',
53-
// state: {from: props.location}
54-
// }}
55-
// />
56-
// );
57-
5825
return (
5926
<UserConsumer>
6027
{

config/env/production.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,11 +78,11 @@ module.exports = {
7878
* If, in production, this app has access to physical-layer CASCADE *
7979
* constraints (e.g. PostgreSQL or MySQL), then set those up in the *
8080
* database and uncomment this to disable Waterline's `cascadeOnDestroy` *
81-
* polyfill. (Otherwise, if you are using a databse like Mongo, you might *
81+
* polyfill. (Otherwise, if you are using a database like Mongo, you might *
8282
* choose to keep this enabled.) *
8383
* *
8484
***************************************************************************/
85-
// cascadeOnDestroy: false,
85+
cascadeOnDestroy: false,
8686

8787
/*dataEncryptionKeys: {
8888
default: process.env.DATA_ENCRYPTION_KEY

0 commit comments

Comments
 (0)