Файл: Модель клиент-сервер (Применение модели «клиент-сервер» в разработке web-приложения).pdf
Добавлен: 26.04.2023
Просмотров: 487
Скачиваний: 1
СОДЕРЖАНИЕ
1.1. Понятие клиента и сервера
1.1.3 Понятие архитектуры клиент-сервер
1.2 Двухуровневая архитектура клиент-сервер
1.3. Многоуровневая архитектура клиент-сервер
1.4. Преимущества и недостатки
2. Применение модели «клиент-сервер» в разработке web-приложения
2.2. Алгоритм реализации решения
2.3. Описание необходимых элементов проекта
2.4. Создание и настройка проекта
2.5. Реализация серверной части
2.6. Реализация клиентской части
})
.then(console.log);
} else {
res.render('main', { title: 'Widget app', message: 'Manage widgets', widgets_code: '<div class="alert alert-warning" role="alert">No widgets yet</div>' });
}
});
})
// Add widget page
app.get('/widget/add', function (req, res) {
res.set('Content-Type', 'text/html');
res.render('addwidget', {
title: 'Widget app',
message: 'Add widget',
cityNames: cityNames,
forecastDurations: forecastDurations,
widgetTypes: widgetTypes })
})
// Process Add widget page
app.post('/widget/add', function (req, res) {
addUpdateWidget(req,function(reply){
console.log(reply);
res.redirect('/');
});
})
// Edit widget page
app.get('/widget/edit', function (req, res) {
res.set('Content-Type', 'text/html');
client.hgetall(req.query.id, function (err, obj) {
if (err || obj===null) res.send('Widget not found!'); else {
obj.id = req.query.id;
res.render('editwidget', {
title: 'Widget app',
message: 'Edit widget',
id: obj.id.replace('widget_',''),
name: obj.name,
city: obj.city,
days: obj.days,
type: obj.type,
cityNames: cityNames,
forecastDurations: forecastDurations,
widgetTypes: widgetTypes
});
}
});
})
// Process Edit widget page
app.post('/widget/edit', function (req, res) {
addUpdateWidget(req,function(reply){
console.log(reply);
res.redirect('/');
});
})
// widget code script
app.get('/widget/show', function (req, res) {
res.set('Content-Type', 'text/javascript');
res.send(`function defer(method){if (window.jQuery) {method();}else{setTimeout(function() { defer(method) }, 50);}}
defer(function () {
if($('#weatherwidgetstyle').length<1) $('head').append('<link id="weatherwidgetstyle" rel="stylesheet" type="text/css" href="http://localhost:3033/widget.css"/>');
$(function(){
var widget_xhr = $.post( "http://localhost:3033/widget/get?id=`+req.query.id+`", function(data) {
console.log( "widget loaded" );
$("#weatherwidget_`+req.query.id+`").html(data);
}, 'text')
.fail(function(xhr, status, error) {
console.log( xhr, status, error, "error - widget not loaded" );
});
});
});`);
});
// widget code ajax content
app.post('/widget/get', function (req, res) {
res.set('Content-Type', 'text/javascript');
var output = "";
var view = "";
if (req.query.id !== null) {
let promise = new Promise(function (resolve) {
client.hgetall(req.query.id, function (err, obj) {
if (err || obj===null) res.send('Widget not found!'); else {
obj.id = req.query.id;
resolve(obj);
}
});
});
promise.then(function (obj) {
var url = openWeatherMapApiUri +
"APPID=" + openWeatherMapApiKey +
"&id=" + obj.city +
"&units=metric&cnt=" + obj.days;
request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
let weatherdata = body;
weatherdata = weatherdata.list;
let daysweather_code = "";
for (var key in weatherdata) {
if (weatherdata.hasOwnProperty(key)) {
date = new Date(weatherdata[key].dt * 1000),
datevalues = [
date.getFullYear(),
date.getMonth()+1,
date.getDate(),
],
todaydate = new Date(),
todaydatevalues = [
todaydate.getFullYear(),
todaydate.getMonth()+1,
todaydate.getDate(),
],
daytitle=date.getDate()+' '+monthNames[date.getMonth()];
if (datevalues.toString()==todaydatevalues.toString()) daytitle = 'Today';
pug.renderFile('views/widgetviewday.pug', {
daytitle: daytitle,
city: cityNames[obj.city],
weathertitle: weatherdata[key].weather[0].description,
daytemp: weatherdata[key].temp.day>0?'+'+weatherdata[key].temp.day:weatherdata[key].temp.day,
nighttemp: weatherdata[key].temp.night>0?'+'+weatherdata[key].temp.night:weatherdata[key].temp.night
}, function (empty, res) {
daysweather_code += res;
});
}
}
view = pug.renderFile('views/widgetview.pug', {
city: cityNames[obj.city],
daysweather_code: daysweather_code,
type: obj.type
}, function (empty, res) {
output = res;
});
res.send(output);
} else {
res.send('Too many requests to openweathermap.org api, try later...');
}
});
return true;
}).then(function (value) {
// null
});
} else {
res.send('Widget ID is not defined');
}
})
// delete widget
app.get('/widget/delete', function (req, res) {
console.log(req.query.id+' deleted');
client.del(req.query.id);
res.redirect('/');
});
Приложение Б
widget.css
.days-container--horizontal .card {
display: inline-block !important;
margin-right: 10px !important;
}
.card{
margin-bottom: 20px;
}
layout.pug
doctype html
html
head
title= title
link(href='https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css' rel='stylesheet')
body
div.container
h1= message
block content
script(src='https://code.jquery.com/jquery-2.2.4.min.js')
script(src='https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js')
main.pug
extends layout.pug
block append content
p.
<a href="/widget/add" class="btn btn-primary" role="button">Add widget</a>
div.widgets!= widgets_code
h3 Widget example:
// insert here widget code for testing, example:
// <div id="weatherwidget_widget_test"></div><script type="text/javascript" src="http://localhost:3033/widget/show?id=widget_test"></script>
<div id="weatherwidget_widget_1"></div><script type="text/javascript" src="http://localhost:3033/widget/show?id=widget_1"></script>
addwidget.pug
extends layout.pug
block append content
p.
<a href="/" class="btn btn-secondary" role="button">Back</a>
<form method="POST" action="/widget/add">
<div class="form-group">
<label>Widget ID</label>
<input type="text" class="form-control" name="id" placeholder="Unique ID" required>
</div>
<div class="form-group">
<label>Name</label>
<input type="text" class="form-control" name="name" placeholder="Widget name" required>
</div>
<div class="form-group">
<label>City</label>
<select class="form-control" name="city" required>
each val, index in cityNames
option(value=index)= val
</select>
</div>
<div class="form-group">
<label>Days count</label>
<select class="form-control" name="days" required>
each val, index in forecastDurations
option(value=index)= val
</select>
</div>
<div class="form-group">
<label>View type</label>
each val, index in widgetTypes
div.radio
label
input(type="radio", name="type", value=index, required=true)
span= val
</div>
<button type="submit" class="btn btn-primary">Save</button>
</form>
editwidget.pug
extends layout.pug
block append content
p.
<a href="/" class="btn btn-secondary" role="button">Back</a>
form(method="POST", action="/widget/edit?id="+id)
<div class="form-group">
<label>Widget ID</label>
input(type="text", class="form-control", name="id", value=id, placeholder="Unique ID")
</div>
<div class="form-group">
<label>Name</label>
input(type="text", class="form-control", name="name", value=name, placeholder="Widget name")
</div>
<div class="form-group">
<label>City</label>
<select class="form-control" name="city">
each val, index in cityNames
option(value=index, selected=index==city?true:false)= val
</select>
</div>
<div class="form-group">
<label>Days count</label>