Update
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*node_modules*
|
||||||
17
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"type": "node",
|
||||||
|
"request": "launch",
|
||||||
|
"name": "Launch Program",
|
||||||
|
"skipFiles": [
|
||||||
|
"<node_internals>/**"
|
||||||
|
],
|
||||||
|
"program": "${file}"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
167
app.js
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
var express = require('express');
|
||||||
|
var multer = require("multer");
|
||||||
|
|
||||||
|
var bodyParser = require('body-parser');
|
||||||
|
var fs = require('fs');
|
||||||
|
const { Console } = require('console');
|
||||||
|
|
||||||
|
var app = express();
|
||||||
|
var jsonParser = bodyParser.json();
|
||||||
|
app.use(express.static(__dirname + '/public'));
|
||||||
|
|
||||||
|
// получение списка данных
|
||||||
|
app.get('/api/users', function (req, res) {
|
||||||
|
var content = fs.readFileSync('users.json', 'utf8');
|
||||||
|
var users = JSON.parse(content);
|
||||||
|
|
||||||
|
res.send(users);
|
||||||
|
});
|
||||||
|
|
||||||
|
// получение одного пользователя по id
|
||||||
|
app.get('/api/users/:id', function (req, res) {
|
||||||
|
var id = req.params.id; // получаем id
|
||||||
|
var content = fs.readFileSync('users.json', 'utf8');
|
||||||
|
var users = JSON.parse(content);
|
||||||
|
var user = null;
|
||||||
|
|
||||||
|
// находим в массиве пользователя по id
|
||||||
|
for (var i = 0; i < users.length; i++) {
|
||||||
|
if (users[i].id == id) {
|
||||||
|
user = users[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// отправляем пользователя
|
||||||
|
if (user) {
|
||||||
|
res.send(user);
|
||||||
|
} else {
|
||||||
|
res.status(404).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Скачивание изображения
|
||||||
|
const storage = multer.diskStorage({
|
||||||
|
destination: function (req, file, cb) {
|
||||||
|
cb(null, __dirname + '/public/images')
|
||||||
|
},
|
||||||
|
|
||||||
|
filename: function (req, file, cb) {
|
||||||
|
var fileName = file.originalname;
|
||||||
|
cb(null, fileName)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const upload = multer({storage: storage});
|
||||||
|
app.post('/imageLoad', upload.single('image'), function (req, res, next) {
|
||||||
|
res.redirect("/")
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// получение отправленных данных
|
||||||
|
app.post('/api/users', jsonParser, function (req, res, next) {
|
||||||
|
if (!req.body) return res.sendStatus(400);
|
||||||
|
|
||||||
|
var userName = req.body.name;
|
||||||
|
var userAge = req.body.age;
|
||||||
|
var userImage = req.body.image;
|
||||||
|
var user = { name: userName, age: userAge, image: userImage};
|
||||||
|
|
||||||
|
var data = fs.readFileSync('users.json', 'utf8');
|
||||||
|
var users = JSON.parse(data);
|
||||||
|
|
||||||
|
// находим максимальный id
|
||||||
|
var id = Math.max.apply(
|
||||||
|
Math,
|
||||||
|
users.map(function (o) {
|
||||||
|
return o.id;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// увеличиваем его на единицу
|
||||||
|
if (id == -Infinity) {
|
||||||
|
id = 0
|
||||||
|
user.id = id
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
user.id = id + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// добавляем пользователя в массив
|
||||||
|
users.push(user);
|
||||||
|
var data = JSON.stringify(users);
|
||||||
|
|
||||||
|
// перезаписываем файл с новыми данными
|
||||||
|
fs.writeFileSync('users.json', data);
|
||||||
|
res.send(user);
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
|
// удаление пользователя по id
|
||||||
|
app.delete('/api/users/:id', function (req, res) {
|
||||||
|
var id = req.params.id;
|
||||||
|
var data = fs.readFileSync('users.json', 'utf8');
|
||||||
|
var users = JSON.parse(data);
|
||||||
|
var index = -1;
|
||||||
|
|
||||||
|
// находим индекс пользователя в массиве
|
||||||
|
for (var i = 0; i < users.length; i++) {
|
||||||
|
if (users[i].id == id) {
|
||||||
|
index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (index > -1) {
|
||||||
|
|
||||||
|
// удаляем пользователя из массива по индексу
|
||||||
|
var user = users.splice(index, 1)[0];
|
||||||
|
var data = JSON.stringify(users);
|
||||||
|
fs.writeFileSync('users.json', data);
|
||||||
|
|
||||||
|
// отправляем удаленного пользователя
|
||||||
|
res.send(user);
|
||||||
|
} else {
|
||||||
|
res.status(404).send();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// изменение пользователя
|
||||||
|
app.put('/api/users', jsonParser, function (req, res) {
|
||||||
|
if (!req.body) return res.sendStatus(400);
|
||||||
|
var userAge = req.body.age;
|
||||||
|
var userName = req.body.name;
|
||||||
|
var userImage = req.body.image;
|
||||||
|
|
||||||
|
if (userName == "" || userAge == "" ) {return};
|
||||||
|
// if (userName.length < 3 || Number(userAge) > 130 || userImage == "") {return};
|
||||||
|
|
||||||
|
var userId = req.body.id;
|
||||||
|
|
||||||
|
var data = fs.readFileSync('users.json', 'utf8');
|
||||||
|
var users = JSON.parse(data);
|
||||||
|
var user;
|
||||||
|
for (var i = 0; i < users.length; i++) {
|
||||||
|
if (users[i].id == userId) {
|
||||||
|
user = users[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// изменяем данные у пользователя
|
||||||
|
if (user) {
|
||||||
|
user.age = userAge;
|
||||||
|
user.name = userName;
|
||||||
|
if (userImage != "") {
|
||||||
|
user.image = userImage;
|
||||||
|
}
|
||||||
|
var data = JSON.stringify(users);
|
||||||
|
fs.writeFileSync('users.json', data);
|
||||||
|
res.send(user);
|
||||||
|
} else {
|
||||||
|
res.status(404).send(user);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
app.listen(3000, function () {
|
||||||
|
console.log('Сервер ожидает подключения...');
|
||||||
|
});
|
||||||
3
operations.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
module.exports.multiply = function (x, y) {
|
||||||
|
return x * y;
|
||||||
|
};
|
||||||
11
operations.test.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
var operations = require('./operations');
|
||||||
|
|
||||||
|
it('should multiply two numbers', function () {
|
||||||
|
var expectedResult = 15;
|
||||||
|
var result = operations.multiply(3, 5);
|
||||||
|
if (result !== expectedResult) {
|
||||||
|
throw new Error(
|
||||||
|
`Expected ${expectedResult}, but got ${result}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
1724
package-lock.json
generated
Normal file
15
package.json
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"name": "webapp",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"dependencies": {
|
||||||
|
"body-parser": "^1.16.0",
|
||||||
|
"express": "^4.14.0",
|
||||||
|
"multer": "^1.4.5-lts.1"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "mocha *.test.js"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"mocha": "^10.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
public/images/13131.jpg
Normal file
|
After Width: | Height: | Size: 57 KiB |
BIN
public/images/21213.png
Normal file
|
After Width: | Height: | Size: 6.6 KiB |
BIN
public/images/73218c16-6a35-5017-b8f4-b20eb5882528.jpeg
Normal file
|
After Width: | Height: | Size: 80 KiB |
BIN
public/images/Map_Test.png
Normal file
|
After Width: | Height: | Size: 6.2 KiB |
BIN
public/images/chi2.png
Normal file
|
After Width: | Height: | Size: 406 KiB |
BIN
public/images/cotembo.png
Normal file
|
After Width: | Height: | Size: 6.7 KiB |
BIN
public/images/image.png
Normal file
|
After Width: | Height: | Size: 334 KiB |
BIN
public/images/j.jpg
Normal file
|
After Width: | Height: | Size: 113 KiB |
BIN
public/images/kapa.png
Normal file
|
After Width: | Height: | Size: 903 KiB |
BIN
public/images/scream.png
Normal file
|
After Width: | Height: | Size: 4.4 MiB |
BIN
public/images/ÐезÑмÑннÑй.png
Normal file
|
After Width: | Height: | Size: 903 KiB |
220
public/index.html
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8" />
|
||||||
|
<meta name="viewport" content="width=device-width"/>
|
||||||
|
<title>Список пользователей</title>
|
||||||
|
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
|
||||||
|
<script src="https://code.jquery.com/jquery-2.2.4.min.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<h2>Список пользователей</h2>
|
||||||
|
<input id='id' type="hidden" value="0"/>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="name">Имя:</label>
|
||||||
|
<input id="name" class="form-control"/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="age">Возраст:</label>
|
||||||
|
<input id="age" class="form-control" name="age"/>
|
||||||
|
</div>
|
||||||
|
<form action="/imageLoad" method="post" enctype="multipart/form-data">
|
||||||
|
<label>Файл</label><br>
|
||||||
|
<input type="file" id="img" name="image" accept=".png, .jpg, .svg, .jpeg"/><br><br>
|
||||||
|
|
||||||
|
<button type="submit" id="save" class="btn btn-sm btn-primary">Сохранить изменения в таблице</button>
|
||||||
|
<button type="submit" class="btn btn-sm btn-primary">Сохранить изображение</button>
|
||||||
|
<a id="reset" class="btn btn-sm btn-primary">Сбросить</a>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<table class="table table-condensed table-striped table-bordered">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Id</th>
|
||||||
|
<th>Имя</th>
|
||||||
|
<th>возраст</th>
|
||||||
|
<th>картинка</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody></tbody>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
|
||||||
|
// Получение всех пользователей
|
||||||
|
function GetUsers() {
|
||||||
|
$.ajax({
|
||||||
|
url: '/api/users',
|
||||||
|
type: 'GET',
|
||||||
|
contentType: 'application/json',
|
||||||
|
success: function (users) {
|
||||||
|
var rows = '';
|
||||||
|
$.each(users, function (
|
||||||
|
index,
|
||||||
|
user
|
||||||
|
) {
|
||||||
|
// добавляем полученные элементы в таблицу
|
||||||
|
rows += row(user);
|
||||||
|
});
|
||||||
|
$('table tbody').append(rows);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Получение одного пользователя
|
||||||
|
function GetUser(id) {
|
||||||
|
$.ajax({
|
||||||
|
url: '/api/users/' + id,
|
||||||
|
type: 'GET',
|
||||||
|
contentType: 'application/json',
|
||||||
|
success: function (user) {
|
||||||
|
$('#id').val(user.id);
|
||||||
|
$('#name').val(user.name);
|
||||||
|
$('#age').val(user.age);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// загрузка data изображения
|
||||||
|
var imageData = null;
|
||||||
|
$('input[type=file]').on('change', function(){
|
||||||
|
imageData = this.files;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Добавление пользователя
|
||||||
|
function CreateUser(userName, userAge, userImage) {
|
||||||
|
if ($('input[type=file]').val() == "" || $('#name').val()== "" || $('#age').val() == "") {return};
|
||||||
|
if (imageData == null || imageData['0'].size <= 10 * 1024 * 1024 ) { //10мб
|
||||||
|
$.ajax({
|
||||||
|
url: 'api/users',
|
||||||
|
contentType: 'application/json',
|
||||||
|
method: 'POST',
|
||||||
|
|
||||||
|
data: JSON.stringify({
|
||||||
|
name: userName,
|
||||||
|
age: userAge,
|
||||||
|
image: userImage,
|
||||||
|
}),
|
||||||
|
success: function (user) {
|
||||||
|
if (user.id == null) {
|
||||||
|
user.id = 0
|
||||||
|
}
|
||||||
|
reset();
|
||||||
|
$('table tbody').append(row(user));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Изменение пользователя
|
||||||
|
function EditUser(userId, userName, userAge, userImage) {
|
||||||
|
if (imageData == null || imageData['0'].size <= 10 * 1024 * 1024) { //10мб
|
||||||
|
$.ajax({
|
||||||
|
url: 'api/users',
|
||||||
|
contentType: 'application/json',
|
||||||
|
method: 'PUT',
|
||||||
|
data: JSON.stringify({
|
||||||
|
id: userId,
|
||||||
|
name: userName,
|
||||||
|
age: userAge,
|
||||||
|
image: userImage,
|
||||||
|
}),
|
||||||
|
success: function (user) {
|
||||||
|
reset();
|
||||||
|
$("tr[data-rowid='" + user.id + "']").replaceWith(row(user));
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// сброс формы
|
||||||
|
function reset() {
|
||||||
|
$('#id').val(0);
|
||||||
|
$('#name').val("");
|
||||||
|
$('#age').val("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Удаление пользователя
|
||||||
|
function DeleteUser(id) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'api/users/' + id,
|
||||||
|
contentType: 'application/json',
|
||||||
|
method: 'DELETE',
|
||||||
|
success: function (user) {
|
||||||
|
$(
|
||||||
|
"tr[data-rowid='" +
|
||||||
|
user.id +
|
||||||
|
"']"
|
||||||
|
).remove();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// создание строки для таблицы
|
||||||
|
var row = function (user) {
|
||||||
|
return (
|
||||||
|
"<tr data-rowid='" +
|
||||||
|
user.id +
|
||||||
|
"'><td>" +
|
||||||
|
user.id +
|
||||||
|
'</td>' +
|
||||||
|
'<td>' +
|
||||||
|
user.name +
|
||||||
|
'</td> <td>' +
|
||||||
|
user.age +
|
||||||
|
'</td> <td><img class="logo" style="width:100px; height:100px;" src="http://localhost:3000/images/' + user.image + '">' + '</td>' +
|
||||||
|
"<td><a class='editLink' data-id='" +
|
||||||
|
user.id +
|
||||||
|
"'>Изменить</a> | " +
|
||||||
|
"<a class='removeLink' data-id='" +
|
||||||
|
user.id +
|
||||||
|
"'>Удалить</a></td></tr>"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// сохранение данных
|
||||||
|
$('#save').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
var id = $('#id').val();
|
||||||
|
var name = $('#name').val();
|
||||||
|
var age = $('#age').val();
|
||||||
|
var image = $('input[type=file]').val()
|
||||||
|
image = image.replace("C:\\fakepath\\","")
|
||||||
|
|
||||||
|
if (id == 0){
|
||||||
|
CreateUser(name, age, image);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
EditUser(id, name, age, image);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// сброс значений формы
|
||||||
|
$('#reset').click(function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
// нажимаем на ссылку Изменить
|
||||||
|
$('body').on('click', '.editLink', function () {
|
||||||
|
var id = $(this).data('id');
|
||||||
|
GetUser(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// нажимаем на ссылку Удалить
|
||||||
|
$('body').on(
|
||||||
|
'click',
|
||||||
|
'.removeLink',
|
||||||
|
function () {
|
||||||
|
var id = $(this).data('id');
|
||||||
|
DeleteUser(id);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// загрузка пользователей
|
||||||
|
GetUsers();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
1
users.json
Normal file
@@ -0,0 +1 @@
|
|||||||
|
[{"name":"Cotambo","age":"34","image":"cotembo.png","id":0},{"name":"Angela","age":"24","image":"13131.jpg","id":1},{"name":"Scream","age":"67","image":"scream.png","id":3},{"name":"Ella","age":"21","image":"j.jpg","id":4},{"name":"Sprite","age":"2","image":"Map_Test.png","id":5},{"name":"Капибара-Гуль","age":"1000-7","image":"kapa.png","id":6}]
|
||||||