Этот коммит содержится в:
Igor V Belousov 2019-11-12 01:45:36 +03:00
родитель e2ac280221
Коммит 50e81a1298
19 изменённых файлов: 569 добавлений и 97 удалений

Просмотреть файл

@ -21,6 +21,63 @@ a:visited {
border-bottom: .0625rem solid rgba(207, 0, 207, .3);
}
.clear-fix {
clear: both !important;
}
.d-inline-block {
display: inline-block !important;
}
.f-right {
float: right !important;
}
.f-left {
float: left !important;
}
.m-0 {
margin: 0 !important;
}
.mb-0 {
margin-bottom: 0 !important;
}
.mr-0 {
margin-right: 0 !important;
}
.ml-0 {
margin-left: 0 !important;
}
.mt-0 {
margin-top: 0 !important;
}
.m-1 {
margin: 1rem !important;
}
.mb-1 {
margin-bottom: 1rem !important;
}
.mr-1 {
margin-right: 1rem !important;
}
.ml-1 {
margin-left: 1rem !important;
}
.mt-1 {
margin-top: 1rem !important;
}
body {
font-family: Verdana, "Geneva CY", "DejaVu Sans", sans-serif;
font-size: 1rem;
@ -56,6 +113,7 @@ body {
.navigate {
background: black;
margin-top: 1.25rem;
margin-bottom: 2.625rem;
}
.navigate ul {
@ -72,6 +130,7 @@ body {
.navigate ul li a {
color: white;
text-decoration: none;
border-bottom: none;
}
.navigate ul li a:hover {
@ -84,6 +143,7 @@ body {
padding-top: 1rem;
padding-bottom: 1rem;
}
.footer::before {
width: 100%;
display: block;
@ -94,5 +154,66 @@ body {
}
table {
border-spacing: 0;
border-collapse: collapse;
width: 100%;
}
td, th {
border: .0625rem solid rgba(0, 0, 0, .3);
padding: 0.375rem;
}
.form {
border-radius: .375rem;
border: .0625rem solid rgba(0, 0, 0, .3);
max-width: 22.5rem;
padding: .875rem;
}
.form__element {
margin-bottom: .375rem;
}
.form__submit {
margin-top: .5rem;
}
.form__submit, .btn {
background-color: #fff;
border-radius: .125rem;
border: .0625rem solid rgba(0, 0, 0, .3);
padding: .25rem;
cursor: pointer;
}
a.btn, a.btn:hover, a.btn:focus {
color: #000;
border: .0625rem solid rgba(0, 0, 0, .3);
}
.btn:hover, .btn:focus,
.form__submit:hover,
.form__submit:focus {
background-color: rgba(0, 0, 0, .4);
}
.form-element {
padding: .25rem 0;
}
.form-element__data {
min-width: 15rem;
padding-left: .1875rem;
}
.form-element__label {
min-width: 5rem;
display: inline-block;
}
select {
height: 1.5rem;
padding-left: 0 !important;
}

23
public/assets/js/script.js Обычный файл
Просмотреть файл

@ -0,0 +1,23 @@
let d = document;
let removeModel = (id, url) => {
let formData = new FormData();
formData.append("id", id || 0);
let xhr = new XMLHttpRequest();
xhr.open("POST", url);
xhr.send(formData);
xhr.onload = () => location.reload();
};
let deleteEvent = (v, message, url) => {
v.addEventListener("click", e => {
if (confirm(message))
removeModel(e.target.dataset.id, url)
});
};
d.querySelectorAll('.js-group-btn-delete').forEach(v => {
deleteEvent(v, "You're sure to delete this group?", "/groups/delete")
});
d.querySelectorAll(".js-server-btn-delete").forEach(v => {
deleteEvent(v, "You're sure to delete this server?", "/servers/delete")
});

Просмотреть файл

@ -3,8 +3,9 @@
namespace MyApp\Controller;
use MyApp\Core\Controller;
use MyApp\Model\GroupsModel as Model;
use MyApp\View\GroupsView as View;
use MyApp\Service\GroupsService;
use MyApp\Service\GroupsService as Service;
class GroupsController extends Controller
{
@ -13,29 +14,62 @@ class GroupsController extends Controller
*/
public function index()
{
$this->htmlResponse((new View())->index((new GroupsService())->getTableData()));
$this->htmlResponse((new View())->index((new Service())->getTableData()));
}
/**
* @RouteRegExp = "|^/groups/add$|"
* @HttpMethod = "GET,POST"
*/
public function add()
{
$service = new Service();
if (!empty($_POST)) {
/** @var Model $model */
$model = $service->addGroup((string) $_POST['name'],
(int) $_POST['parent']);
if ($model) {
$this->redirect('/groups/edit/'.$model->getId());
}
}
$select = $service->sortForSelect($service->getTableData());
$this->htmlResponse((new View())->add($select));
}
/**
* @RouteRegExp = "|^/groups/delete$|"
* @HttpMethod = "POST"
*/
public function delete()
{
if (!empty($_POST)) {
(new Service())->deleteGroup((int) $_POST['id']);
}
}
/**
* @RouteRegExp = "|^/groups/edit/(?<id>\d+)$|"
* @HttpMethod = "GET,POST"
*
* @param $id
*
* @throws \Exception
*/
public function edit($id)
{
$group_service = new GroupsService();
$service = new Service();
$model = $group_service->getGroup($id);
$model = !empty($_POST) ? $service->updateGroup((int) $id,
(string) $_POST['name'],
(int) $_POST['parent']) : $service->getGroup((int) $id);
if ($model) {
$this->htmlResponse((new View())->edit($group_service->getGroup($id),
$group_service->getTableData()));
$select = $service->sortForSelect($service->getTableData());
$this->htmlResponse((new View())->edit($model, $select));
} else {
$this->redirect('/groups');
}

Просмотреть файл

@ -3,6 +3,9 @@
namespace MyApp\Controller;
use MyApp\Core\Controller;
use MyApp\View\ServersView as View;
use MyApp\Service\ServersService as Service;
use MyApp\Service\GroupsService;
class ServersController extends Controller
{
@ -11,20 +14,62 @@ class ServersController extends Controller
*/
public function index()
{
$this->htmlResponse((new View())->index((new Service())->getTableData()));
}
/**
* @RouteRegExp = "|^/servers/add$|"
* @HttpMethod = "GET,POST"
*/
public function add()
{
$service = new Service();
if (!empty($_POST)) {
/** @var \MyApp\Model\ServersModel $model */
$model = $service->addServer((string) $_POST['name'],
(string) $_POST['ip'], (int) $_POST['group']);
if ($model) {
$this->redirect('/servers/edit/'.$model->getId());
}
}
$group_service = new GroupsService();
$select = $group_service->sortForSelect($group_service->getTableData());
$this->htmlResponse((new View())->add($select));
}
/**
* @RouteRegExp = "|^/servers/edit/(?<id>\d+)$|"
* @HttpMethod = "GET,POST"
*/
public function edit($id)
{
$service = new Service();
$model = !empty($_POST) ? $service->updateServer((int) $id,
(string) $_POST['name'], (string) $_POST['ip'],
(int) $_POST['group']) : $service->getServer((int) $id);
if ($model) {
$group_service = new GroupsService();
$select = $group_service->sortForSelect($group_service->getTableData());
$this->htmlResponse((new View())->edit($model, $select));
} else {
$this->redirect('/servers');
}
}
/**
* @RouteRegExp = "|^/servers/delete$|"
* @HttpMethod = "POST"
*/
public function delete()
{
if (!empty($_POST)) {
(new Service())->deleteServer((int) $_POST['id']);
}
}
}

Просмотреть файл

@ -332,6 +332,12 @@ class Model
}
$query->execute();
if (!$update_mode) {
(function () use ($table_map, $db) {
$this->{$table_map['id']} = $db->lastInsertId();
})->call($model);
}
}
}
$db->commit();

Просмотреть файл

@ -1,12 +1,11 @@
<?php
namespace MyApp\Model;
use MyApp\Core\Model;
/**
* Class GroupsModel
* Class GroupsModel.
*
* @TableName = "groups"
*
@ -58,9 +57,10 @@ class GroupsModel extends Model
*
* @return GroupsModel
*/
public function setName(string $name): self
public function setName(?string $name): self
{
$this->name = $name;
return $this;
}
@ -69,9 +69,10 @@ class GroupsModel extends Model
*
* @return GroupsModel
*/
public function setParent(int $parent): self
public function setParent(?int $parent): self
{
$this->parent = $parent;
return $this;
}

Просмотреть файл

@ -8,8 +8,6 @@ use MyApp\Core\Model;
* Class ServersModel.
*
* @TableName = "servers"
*
* @package MyApp\Model
*/
class ServersModel extends Model
{
@ -94,7 +92,7 @@ class ServersModel extends Model
/**
* @return int
*/
public function getGroup(): int
public function getGroup(): ?int
{
return $this->group;
}
@ -104,7 +102,7 @@ class ServersModel extends Model
*
* @return ServersModel
*/
public function setGroup(int $group): self
public function setGroup(?int $group): self
{
$this->group = $group;

Просмотреть файл

@ -1,9 +1,9 @@
<?php
namespace MyApp\Service;
use MyApp\Model\GroupsModel;
use MyApp\Core\Model;
use Exception;
class GroupsService
@ -20,7 +20,7 @@ class GroupsService
return $models;
}
public function getGroup($id): ? GroupsModel
public function getGroup(int $id): ?GroupsModel
{
/** @var GroupsModel[] $model */
$model = GroupsModel::find([$id], null, null, [], '', '1');
@ -31,4 +31,49 @@ class GroupsService
return null;
}
public function sortForSelect($models, $parent_id = null, $level = 1)
{
$out = [];
foreach ($models as $item) {
/** GroupsModel $item */
if (
$item->getParent() === $parent_id) {
$item->{'select-level'} = str_repeat('-', $level);
$out[] = $item;
$out = array_merge($out,
$this->sortForSelect($models, $item->getId(), $level + 1));
}
}
return $out;
}
public function updateGroup(int $id, string $name, int $parent): ?Model
{
if ($model = $this->getGroup($id)) {
$model->setName($name)
->setParent($parent ? $parent : null);
Model::save([$model]);
}
return $model;
}
public function deleteGroup(int $id): void
{
if ($model = $this->getGroup($id)) {
$arr = [$model];
Model::delete($arr);
}
}
public function addGroup(string $name, int $parent): ?Model
{
$model = (new GroupsModel())->setName($name)
->setParent($parent ? $parent : null);
Model::save([$model]);
return $model;
}
}

85
src/services/ServersService.php Обычный файл
Просмотреть файл

@ -0,0 +1,85 @@
<?php
namespace MyApp\Service;
use MyApp\Model\ServersModel;
use MyApp\Model\GroupsModel;
use MyApp\Core\Model;
use Exception;
class ServersService
{
/**
* @return ServersModel[]|null
*
* @throws Exception
*/
public function getTableData(): ?array
{
$models = ServersModel::find(null, null, '1 = 1');
$records = [];
foreach ($models as $model) {
/** @var ServersModel $model */
if ($group_id = $model->getGroup()) {
$records[] = $group_id;
}
}
if (count($records)) {
if ($groups = GroupsModel::find($records)) {
$groups_names = [];
/** @var GroupsModel $group */
foreach ($groups as $group) {
$groups_names[$group->getId()] = $group->getName();
}
foreach ($models as $model) {
if (array_key_exists($model->getGroup(), $groups_names)) {
$model->{'group_name'} = $groups_names[$model->getGroup()];
}
}
}
}
return $models;
}
public function getServer($id): ?ServersModel
{
$model = ServersModel::find([$id], null, null, [], '', '1');
if (!empty($model)) {
return $model[0];
}
return null;
}
public function updateServer(int $id, string $name, string $ip, int $group)
{
if ($model = $this->getServer($id)) {
$model->setName($name)
->setIp($ip)
->setGroup($group ? $group : null);
Model::save([$model]);
}
return $model;
}
public function deleteServer(int $id): void
{
if ($model = $this->getServer($id)) {
$arr = [$model];
Model::delete($arr);
}
}
public function addServer(string $name, string $ip, int $group)
{
$model = (new ServersModel())->setName($name)
->setIp($ip)
->setGroup($group ? $group : null);
Model::save([$model]);
return $model;
}
}

Просмотреть файл

@ -1,7 +1,27 @@
<?php
require __DIR__ . '/../shared/head.php'; ?>
<form action="">
require __DIR__ . '/../shared/head.php';
?>
<form action="" method="post" class="form">
<div class="form__element form-element">
<label class="form-element__label" for="parent">Parent:</label>
<select name="parent" id="parent" class="form-element__data select">
<option value="null" class="select__option">
Root
</option>
<?php foreach ($this->select as $item): ?>
<option value="<?= $item->getId() ?>" class="select__option">
<?= $item->{"select-level"} ?><?= $item->getName() ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form__element form-element">
<label class="form-element__label" for="name">Name:</label>
<input type="text" name="name" id="name"
class="form-element__data">
</div>
<button type="submit" class="form__submit">Submit</button>
</form>
<?php
require __DIR__ . '/../shared/footer.php';

Просмотреть файл

@ -3,49 +3,31 @@ require __DIR__ . '/../shared/head.php';
/** @var \MyApp\Model\GroupsModel $model */
$model = $this->model;
function getTree($table, $parent_id = null, $level = 1)
{
$out = [];
foreach ($table as $item) {
/** @var \MyApp\Model\GroupsModel $item */
if (
$item->getParent() === $parent_id) {
$item->{"select-level"} = str_repeat("-", $level);
$out[] = $item;
$out = array_merge($out,
getTree($table, $item->getId(), $level + 1));
}
}
return $out;
}
?>
<br>
<form action="" method="post">
<input type="hidden" value="<?= $model->getId() ?>" name="id">
<div>
<label for="parent">Parent:</label>
<select name="parent" id="parent">
<option value="null"
<form action="" method="post" class="form">
<div class="form__element form-element">
<label class="form-element__label" for="parent">Parent:</label>
<select name="parent" id="parent" class="form-element__data select">
<option value="null" class="select__option"
<?php if (is_null($model->getParent())): ?>selected<?php endif; ?>>
Root
</option>
<?php foreach (getTree($this->table) as $item): ?>
<option value="<?= $item->getId() ?>"
<?php foreach ($this->select as $item): ?>
<?php if ($item->getId() !== $model->getId()): ?>
<option value="<?= $item->getId() ?>" class="select__option"
<?php if ($item->getId() === $model->getParent()): ?>selected<?php endif; ?>>
<?= $item->{"select-level"} ?><?= $item->getName() ?>
</option>
<?php endif; ?>
<?php endforeach; ?>
</select>
</div>
<div>
<label for="name">Name:</label>
<input type="text" value="<?= $model->getName() ?>" name="name" id="name">
<div class="form__element form-element">
<label class="form-element__label" for="name">Name:</label>
<input type="text" value="<?= $model->getName() ?>" name="name" id="name"
class="form-element__data">
</div>
<button type="submit">Submit</button>
<button type="submit" class="form__submit">Submit</button>
</form>
<?php
require __DIR__ . '/../shared/footer.php';

Просмотреть файл

@ -1,8 +1,10 @@
<?php
require __DIR__ . '/../shared/head.php'; ?>
<a href="/groups/add" class="btn d-inline-block f-right mb-1">Add new
group</a>
<div class="clear-fix"></div>
<?php if ($this->table): ?>
<br>
<table border="1" width="100%">
<table>
<tr>
<th>Id</th>
<th>Name</th>
@ -14,7 +16,9 @@ require __DIR__ . '/../shared/head.php'; ?>
<td><?= $item->getId() ?></td>
<td><?= $item->getName() ?></td>
<td><?= $item->getParent() ?></td>
<td><a href="/groups/edit/<?= $item->getId() ?>">edit</a></td>
<td><a href="/groups/edit/<?= $item->getId() ?>" class="btn">edit</a>
<span class="btn js-group-btn-delete"
data-id="<?= $item->getId() ?>">delete</span></td>
</tr>
<?php endforeach; ?>

Просмотреть файл

@ -1,7 +1,32 @@
<?php
require __DIR__ . '/../shared/head.php'; ?>
<form action="">
require __DIR__ . '/../shared/head.php';
?>
<form action="" method="post" class="form">
<div class="form__element form-element">
<label class="form-element__label" for="name">Name:</label>
<input type="text" value="" name="name" id="name"
class="form-element__data">
</div>
<div class="form__element form-element">
<label class="form-element__label" for="ip">IP Ver. 4:</label>
<input type="text" value="" name="ip" id="ip"
class="form-element__data">
</div>
<div class="form__element form-element">
<label class="form-element__label" for="group">Group:</label>
<select name="group" id="group" class="form-element__data select">
<option value="null" class="select__option">
Root
</option>
<?php foreach ($this->select as $item): ?>
<option value="<?= $item->getId() ?>" class="select__option">
<?= $item->{"select-level"} ?><?= $item->getName() ?>
</option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" class="form__submit">Submit</button>
</form>
<?php
require __DIR__ . '/../shared/footer.php';

37
src/templates/servers/edit.tpl.php Обычный файл
Просмотреть файл

@ -0,0 +1,37 @@
<?php
require __DIR__ . '/../shared/head.php';
/** @var \MyApp\Model\ServersModel $model */
$model = $this->model;
?>
<form action="" method="post" class="form">
<div class="form__element form-element">
<label class="form-element__label" for="name">Name:</label>
<input type="text" value="<?= $model->getName() ?>" name="name" id="name"
class="form-element__data">
</div>
<div class="form__element form-element">
<label class="form-element__label" for="ip">IP Ver. 4:</label>
<input type="text" value="<?= $model->getIp() ?>" name="ip" id="ip"
class="form-element__data">
</div>
<div class="form__element form-element">
<label class="form-element__label" for="group">Group:</label>
<select name="group" id="group" class="form-element__data select">
<option value="null" class="select__option"
<?php if (is_null($model->getGroup())): ?>selected<?php endif; ?>>
Root
</option>
<?php foreach ($this->select as $item): ?>
<option value="<?= $item->getId() ?>" class="select__option"
<?php if ($item->getId() === $model->getGroup()): ?>selected<?php endif; ?>>
<?= $item->{"select-level"} ?><?= $item->getName() ?>
</option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" class="form__submit">Submit</button>
</form>
<?php
require __DIR__ . '/../shared/footer.php';

Просмотреть файл

@ -1,7 +1,30 @@
<?php
require __DIR__ . '/../shared/head.php'; ?>
<a href="/servers/add" class="btn d-inline-block f-right mb-1">Add new
server</a>
<div class="clear-fix"></div>
<?php if ($this->table): ?>
<table>
<tr>
<th>Id</th>
<th>Name</th>
<th>IP Address</th>
<th>Group</th>
<th>Actions</th>
</tr>
<?php foreach ($this->table as $item): ?>
<tr>
<td><?= $item->getId() ?></td>
<td><?= $item->getName() ?></td>
<td><?= $item->getIp() ?></td>
<td><?= $item->{"group_name"} ?? 'Root' ?></td>
<td><a href="/servers/edit/<?= $item->getId() ?>" class="btn">edit</a>
<span class="btn js-server-btn-delete"
data-id="<?= $item->getId() ?>">delete</span></td>
</tr>
<?php endforeach; ?>
</table>
<?php endif; ?>
<?php
require __DIR__ . '/../shared/footer.php';

Просмотреть файл

@ -3,5 +3,6 @@
<br>
<a href="https://belousovv.ru" target="_blank">Belousovv.ru</a>
</footer>
<script src="/assets/js/script.js"></script>
</body>
</html>

Просмотреть файл

@ -8,6 +8,6 @@ class DefaultView extends View
{
public function index(): string
{
return $this->setTitle('Index')->render('default/index');
return $this->setTitle('Home')->render('default/index');
}
}

Просмотреть файл

@ -1,26 +1,30 @@
<?php
namespace MyApp\View;
use MyApp\Core\View;
class GroupsView extends View
{
public function index(?array $table)
{
$this->{"table"} = $table;
$this->{'table'} = $table;
return $this->setTitle('Edit groups')->render('groups/index');
}
public function edit($model, ?array $table)
public function add(?array $select)
{
$this->{"model"} = $model;
$this->{"table"} = $table;
$this->{'select'} = $select;
return $this->setTitle('Edit groups')->render('groups/edit');
return $this->setTitle('Add new group')->render('groups/add');
}
public function edit($model, ?array $select)
{
$this->{'model'} = $model;
$this->{'select'} = $select;
return $this->setTitle('Edit group')->render('groups/edit');
}
}

Просмотреть файл

@ -1,12 +1,30 @@
<?php
namespace MyApp\View;
use MyApp\Core\View;
class ServersView extends View
{
public function index(?array $table)
{
$this->{'table'} = $table;
return $this->setTitle('Edit servers')->render('servers/index');
}
public function add(?array $select)
{
$this->{'select'} = $select;
return $this->setTitle('Add new server')->render('servers/add');
}
public function edit($model, ?array $select)
{
$this->{'model'} = $model;
$this->{'select'} = $select;
return $this->setTitle('Edit server')->render('servers/edit');
}
}