Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 0 additions & 10 deletions .env.sample

This file was deleted.

6 changes: 6 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
{
"env": {
"browser": true,
"commonjs": true,
"es6": true,
"jquery": true
},
"extends": "airbnb-base",
"plugins": [
"import"
Expand Down
2 changes: 2 additions & 0 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ module.exports = (grunt) => {

grunt.initConfig(tasks);
grunt.registerTask('build', ['cssmin', 'uglify']);
grunt.registerTask('watch', ['watch']);
grunt.loadNpmTasks('grunt-contrib-watch');

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to have this here, as it is already in the drop-in task.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But without it here command 'grunt watch' doesn't work at me correctly.
And official documentation (https://github.com/gruntjs/grunt-contrib-watch) says

npm install grunt-contrib-watch --save-dev
Once the plugin has been installed, it may be enabled inside your Gruntfile with this line of JavaScript:
grunt.loadNpmTasks('grunt-contrib-watch');

I'll better remove it from file /grunt/watch.task.js

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant this line: grunt.loadNpmTasks('grunt-contrib-watch'); which is already loaded in the drop-in task.

} catch (error) {
console.error(`I can't load Grunt; ${error.message}`);
}
Expand Down
19 changes: 16 additions & 3 deletions app/core/controllers/cities.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,11 @@ const m = attract('core/models');
module.exports = {
create: async (req, res, next) => {
try {
const city = await m.city.create(req.body);
return res.render('cities', city);
await m.city.create(req.body);
return res.render('cities', {
section: 'Cities',
cities: await m.city.find({ 'meta.status': 'active' })
});
} catch (error) {
return next(error);
}
Expand All @@ -15,7 +18,6 @@ module.exports = {
if (req.params.city) {
return res.send(await m.city.findById(req.params.city));
}

return res.render('cities', {
section: 'Cities',
cities: await m.city.find({ 'meta.status': 'active' })
Expand All @@ -30,5 +32,16 @@ module.exports = {
} catch (error) {
return next(error);
}
},

update: async (req, res, next) => {
try {
const city = await m.city.findById(req.params.city).exec();
await city.update(req.body);
return res.status(200)
.end('success');
} catch (error) {
return next(error);
}
}
};
18 changes: 12 additions & 6 deletions app/core/controllers/users.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,12 @@ const m = attract('core/models');
module.exports = {
create: async (req, res, next) => {
try {
const user = await m.user.create(req.body);
return res.render('users', user);
await m.user.create(req.body);
return res.render('users', {
section: 'Users',
users: await m.user.find({ 'meta.status': 'active' }),
cities: await m.city.find({ 'meta.status': 'active' })
});
} catch (error) {
return next(error);
}
Expand All @@ -15,18 +19,20 @@ module.exports = {
if (req.params.user) {
return res.send(await m.user.findById(req.params.user));
}

return res.render('users', {
section: 'Users',
users: await m.user.find({ 'meta.status': 'active' })
users: await m.user.find({ 'meta.status': 'active' }),
cities: await m.city.find({ 'meta.status': 'active' })
});
},

delete: async (req, res, next) => {
try {
const user = await m.user.findById(req.params.user).exec();
const user = await m.user.findById(req.params.user)
.exec();
await user.remove();
return res.status(200).end();
return res.status(200)

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Response for a DELETE method should be consistent throughout the API. In this case the response is not the same as for DELETE /users.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not change anything significant here, the editor optimized the markup of the code
return res.status(200)
.end();
Only in app/core/controllers/users.js we are adding in request string 'success' , so now I'll add it here (in app/core/controllers/users.js).

.end('success');
} catch (error) {
return next(error);
}
Expand Down
4 changes: 2 additions & 2 deletions app/core/routes/cities.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module.exports = (router, controller) => {
router.route('/cities/:city?')
.get(controller.read)
.post(controller.create)
.delete(controller.delete);

.delete(controller.delete)
.put(controller.update);
return router;
};
2 changes: 2 additions & 0 deletions app/core/views/_components/html.pug
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,5 @@ mixin head()
mixin body()
body
block
script(src='https://code.jquery.com/jquery-3.3.1.min.js', integrity='sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=', crossorigin='anonymous')
script(src='/js/boilerplate.min.js', type='text/javascript')
33 changes: 33 additions & 0 deletions app/core/views/cities/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,36 @@ include ../_components/html
h3= section
p
a(href='/') Home
br
a(href='/users') Users
br

-let n = 1;

.container
table(id='list-cities' width='20%' border='1')
tbody
tr
td №
td City name
td
td
each item in cities
tr(class='row_table')
td= n
td
input(class='city_name_'+n, type='text', name='cityname' value=item.name)
td
button(class='delete-city', width='100%', height='100%', type='submit', _id=item._id) Delete
td
button(class='update-city', width='100%', height='100%', type='submit', _id=item._id , _idd=n++, _city=item.name) Update

.container
form(action='/cities', method='post')
p.search
.create-container
b Сreate new city:
input(type='text', size='50' name='name' placeholder='enter city name')
input(type='submit' value='Create')


38 changes: 38 additions & 0 deletions app/core/views/users/index.pug
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,41 @@ include ../_components/html
h3= section
p
a(href='/') Home
br
a(href='/cities') Cities
br

-let n = 1;

b User information:
.container
table(id='users-table' width='20%' border='1')
tbody
tr
td №
td User name
td User email
td
each item in users
tr(class='user-info')
td= n++
td= item.username
td= item.email
td
button(class='delete-user', width='100%', height='100%' , _id=item._id ) Delete
br
b Create new user:
.container
form(action='/users', method='post', id='create-form')
.flex-container
input(type='text', name='username' placeholder='enter user name')
input(type='email', name='email' placeholder='enter user email')
select(id='city-list', name='city', form='create-form')
each item in cities
option(value=item._id)= item.name
input(type='submit' value='Create')





2 changes: 2 additions & 0 deletions app/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ require('attract')({ basePath: __dirname });
const bodyParser = require('body-parser');
const compression = require('compression');
const express = require('express');
const logger = require('morgan');
const powered = require('powered');
const serveFavicon = require('serve-favicon');

Expand All @@ -25,6 +26,7 @@ m.load(config.mongo).then(() => {
app.set('views', `${__dirname}/core/views`);
app.set('view engine', 'pug');
app.use(
logger('dev'),
powered(),
compression(),
express.static(`${__dirname}/public`),
Expand Down
1 change: 0 additions & 1 deletion grunt/watch.task.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
module.exports = (grunt, path) => {
grunt.registerTask('watch', ['watch']);
return {
scripts: {
files: [
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
"body-parser": "^1.18.2",
"compression": "^1.7.2",
"express": "^4.16.2",
"mongoose": "^5.0.7",
"mongoose": "^5.0.6",
"morgan": "^1.9.0",
"powered": "^1.0.1",
"pug": "^2.0.0-beta11",
"serve-favicon": "^2.4.5",
Expand All @@ -37,6 +38,7 @@
"grunt": "^1.0.2",
"grunt-contrib-cssmin": "^2.2.1",
"grunt-contrib-uglify-es": "git://github.com/gruntjs/grunt-contrib-uglify.git#harmony",
"grunt-contrib-watch": "^1.0.0",
"grunt-eslint": "^20.1.0",
"grunt-nodemon": "^0.4.2"
},
Expand Down
87 changes: 71 additions & 16 deletions source/css/home.css
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
html {
min-height: 100%;
position: relative;
min-height: 100%;
position: relative;
}

body {
font-family: 'Lato', sans-serif;
color: #fff;
background-color: #383837;
padding: 0;
margin: 0;
font-family: 'Lato', sans-serif;
color: #fff;
background-color: #383837;
padding: 0;
margin: 0;
font-size: 18px;
}

h3, p {
width: 100%;
text-align: center;
font-size: 1.7rem;
padding: 50px 0 0;
margin: 0;
h3 {
width: 100%;
text-align: center;
font-size: 1.7rem;
padding: 50px 0 0;
margin: 0;
}

p.search {
font-size: 1rem;
margin: 15px 5px 0 0;
padding: 0;
}

p {
font-size: 1rem;
margin: 0;
padding: 0;
text-align: center;
}

a {
Expand All @@ -38,3 +43,53 @@ a:hover {
.actions {
margin-top: 30px;
}

.flex-container {
display: flex;
flex-direction: column;
}

.flex-container input, .flex-container select, .create-container input {
outline: none;
border: 1px solid grey;
padding: 4px;
width: 200px;
max-width: 100%;
height: 35px;
border-radius: 5px;
}

.flex-container input[type='submit'] {
width: 210px;
}

.create-container {
display: flex;
flex-direction: column;
margin-left: 15px;
}

.create-container input {
width: 316px;
}

.create-container input[type='submit'] {
width: 327px;
height: 43px;
}

.container {
margin-left: 15px;
}

b {
margin-left: 15px;
}

td {
padding: 5px;
}

#city-list {
width: 210px;
}
32 changes: 32 additions & 0 deletions source/js/aj_logic.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
$(document)
.ready(() => {
$('body .delete-user').click((ev) => {
$.ajax({
url: `/users/${$(ev.target).attr('_id')}`,
type: 'DELETE',
success() {
$(ev.target).closest('tr').remove();
}
});
});
$('body .delete-city').click((ev) => {
$.ajax({
url: `/cities/${$(ev.target).attr('_id')}`,
type: 'DELETE',
success() {
$(ev.target).closest('tr').remove();
}
});
});
$('body .update-city').click((ev) => {
const cityId = $(ev.target).attr('_idd');
const cityname = $(`.city_name_${cityId}`).val();
$.ajax({
url: `/cities/${$(ev.target).attr('_id')}`,
type: 'PUT',
data: {
name: cityname
}
});
});
});