Projekt

Obecné

Profil

« Předchozí | Další » 

Revize d5a16eb6

Přidáno uživatelem Filip Jani před asi 6 roky(ů)

Re #7330 grid pro správu uživatelů a formuláře

Zobrazit rozdíly:

app/AdminModule/component/User/UserEditForm.latte
1
<div class="row">
2
    <div class="col-4">
3
        {form form class=> 'form'}
4
            <div class="alert alert-danger" n:if="$form->hasErrors()">
5
                <ul class="ul-alert">
6
                    <li n:foreach="$form->errors as $error">{$error}</li>
7
                </ul>
8
            </div>
9

  
10
            <div class="row mt-2">
11
                <div class="col-4">
12
                    {label \App\Model\Repository\UserRepository::COLUMN_USERNAME class => 'label-required'}
13
                </div>
14
                <div class="col-8">
15
                    {input \App\Model\Repository\UserRepository::COLUMN_USERNAME class => 'form-control'}
16
                </div>
17
            </div>
18
            <div class="row mt-2">
19
                <div class="col-4">
20
                    {label \App\Model\Repository\UserRepository::COLUMN_LOGIN class => 'label-required'}
21
                </div>
22
                <div class="col-8">
23
                    {input \App\Model\Repository\UserRepository::COLUMN_LOGIN class => 'form-control'}
24
                </div>
25
            </div>
26
            <div class="row mt-2">
27
                <div class="col-4">
28
                    {label \App\Model\Repository\UserRepository::COLUMN_PASSWORD class => 'label-required'}
29
                </div>
30
                <div class="col-8">
31
                    {input \App\Model\Repository\UserRepository::COLUMN_PASSWORD class => 'form-control'}
32
                </div>
33
            </div>
34
            <div class="row mt-2">
35
                <div class="col-4">
36
                    {label \App\AdminModule\Components\UserEditForm::PASSWORD_CONFIRM class => 'label-required'}
37
                </div>
38
                <div class="col-8">
39
                    {input \App\AdminModule\Components\UserEditForm::PASSWORD_CONFIRM class => 'form-control'}
40
                </div>
41
            </div>
42
            <div class="row mt-2">
43
                <div class="col-4">
44
                    {label \App\Model\Repository\UserRoleRepository::COLUMN_ROLE_ID  class => 'label-required'}
45
                </div>
46
                <div class="col-8">
47
                    {input \App\Model\Repository\UserRoleRepository::COLUMN_ROLE_ID class => 'form-control'}
48
                </div>
49
            </div>
50
            <div class="row mt-2">
51
                <div class="col-4">
52
                    {label \App\Model\Repository\UserRepository::COLUMN_EMAIL}
53
                </div>
54
                <div class="col-8">
55
                    {input \App\Model\Repository\UserRepository::COLUMN_EMAIL class => 'form-control'}
56
                </div>
57
            </div>
58

  
59
            <div class="row">
60
                <div class="col-8 offset-4">
61
                    {input submit class => 'form-control btn btn-success mt-4'}
62
                </div>
63
            </div>
64
        {/form}
65
    </div>
66
</div>
app/AdminModule/component/User/UserEditForm.php
1
<?php
2

  
3

  
4
namespace App\AdminModule\Components;
5

  
6

  
7
use App\Enum\EFlashMessage;
8
use App\Model\Facade\UserFacade;
9
use App\Model\Repository\RoleRepository;
10
use App\Model\Repository\UserRepository;
11
use App\Model\Repository\UserRoleRepository;
12
use Nette\Application\UI\Control;
13
use Nette\Application\UI\Form;
14

  
15
class UserEditForm extends Control
16
{
17
    const PASSWORD_CONFIRM = 'password_confirm';
18

  
19
    /** @var Form  */
20
    private $form;
21

  
22
    /** @var int ID uživatele */
23
    private $userId;
24

  
25
    /**
26
     * @var UserRepository
27
     */
28
    private $userRepository;
29
    /**
30
     * @var UserRoleRepository
31
     */
32
    private $userRoleRepository;
33
    /**
34
     * @var RoleRepository
35
     */
36
    private $roleRepository;
37
    /**
38
     * @var UserFacade
39
     */
40
    private $userFacade;
41

  
42
    public function __construct(UserRepository $userRepository,
43
                                UserRoleRepository $userRoleRepository,
44
                                RoleRepository $roleRepository,
45
                                UserFacade $userFacade
46
    )
47
    {
48
        parent::__construct();
49

  
50
        $this->roleRepository = $roleRepository;
51

  
52
        $this->userId = NULL;
53
        $this->form = new Form;
54
        $this->userRepository = $userRepository;
55
        $this->userRoleRepository = $userRoleRepository;
56
        $this->userFacade = $userFacade;
57
    }
58

  
59
    public function render()
60
    {
61
        $this->template->setFile(__DIR__ . '/UserEditForm.latte');
62
        $this->template->render();
63
    }
64

  
65
    public function createComponentForm()
66
    {
67
        $this->form->addText(UserRepository::COLUMN_USERNAME, 'Uživatelské jméno');
68
        $this->form->addText(UserRepository::COLUMN_LOGIN, 'Login')
69
            ->setRequired(TRUE);
70

  
71
        $password = $this->form->addPassword(UserRepository::COLUMN_PASSWORD, 'Heslo');
72
        $passwordConfirm = $this->form->addPassword(self::PASSWORD_CONFIRM, 'Potvrzení hesla')
73
            ->addRule(Form::EQUAL, 'Hesla se musejí shodovat.', $this->form[UserRepository::COLUMN_PASSWORD]);
74

  
75
        if (empty($this->userId))
76
        {
77
            $password->setRequired(TRUE);
78
            $passwordConfirm->setRequired(TRUE);
79
        } else
80
        {
81
            $password->setRequired(FALSE);
82
            $passwordConfirm->setRequired(FALSE);
83
        }
84

  
85
        $this->form->addSelect(UserRoleRepository::COLUMN_ROLE_ID, 'Role uživatele', $this->getRoles())
86
            ->setPrompt('- Vyberte roli -')
87
            ->addRule(Form::REQUIRED, '%label musí být vybrána.', TRUE);
88
        $this->form->addText(UserRepository::COLUMN_EMAIL, 'E-mail')
89
            ->addRule(Form::EMAIL, 'Prvek %label musí obsahovat validní e-mail.')
90
            ->setRequired(FALSE);
91

  
92
        $this->form->setDefaults($this->getDefaults());
93

  
94
        $submitText = empty($this->userId) ? 'Přidat uživatele' : 'Upravit uživatele';
95
        $this->form->addSubmit('submit', $submitText);
96

  
97
        $this->form->onValidate[] = [$this, 'formValidate'];
98
        $this->form->onSuccess[] = [$this, 'formSuccess'];
99

  
100
        return $this->form;
101
    }
102

  
103
    /**
104
     * Validace formuláře
105
     *
106
     * @param Form $form
107
     */
108
    public function formValidate(Form $form)
109
    {
110
        $values = $form->getValues();
111

  
112
        // Vkládáme nového uživatele - kontrola existujícího loginu
113
        if (empty($this->userId))
114
        {
115
            if ($this->userRepository->findByLogin($values->{UserRepository::COLUMN_LOGIN}))
116
            {
117
                $form->addError('Uživatel se zadaným loginem již existuje.');
118
            }
119
        }
120
    }
121

  
122
    public function formSuccess(Form $form)
123
    {
124
        $result = $this->userFacade->saveUser($form->getValues(true), $this->userId);
125

  
126
        if ($result)
127
        {
128
            $this->presenter->flashMessage('Uživatel byl úspěšně upraven.', EFlashMessage::SUCCESS);
129
            $this->presenter->redirect('User:edit', ['id' => $result->{UserRepository::COLUMN_ID}]);
130
        } else
131
        {
132
            $this->presenter->flashMessage('Uživatele se nepodařilo upravit.', EFlashMessage::ERROR);
133
        }
134
    }
135

  
136
    /**
137
     * Nastaví uživatele do formuláře, pro předvyplnění hodnot formuláře
138
     *
139
     * @param int $userId
140
     */
141
    public function setUser(int $userId)
142
    {
143
        $this->userId = $userId;
144
    }
145

  
146
    /**
147
     * Vrací hodnoty z databáze při upravování existujícího uživatele
148
     *
149
     * @return array
150
     */
151
    private function getDefaults()
152
    {
153
        $defaultValues = array();
154

  
155
        if(!empty($this->userId))
156
        {
157
            $userSelection = $this->userRepository->findById($this->userId);
158
            $userRow = $userSelection->fetch();
159

  
160
            if ($userRow)
161
            {
162
                $defaultValues = $userRow->toArray();
163
                $roleRow = $userRow->related(UserRoleRepository::TABLE_NAME, UserRoleRepository::COLUMN_USER_ID)->fetch();
164

  
165
                $defaultValues[UserRoleRepository::COLUMN_ROLE_ID] = $roleRow ? $roleRow->{UserRoleRepository::COLUMN_ROLE_ID} : NULL;
166
            }
167
        }
168

  
169
        return $defaultValues;
170
    }
171

  
172
    /**
173
     * Vrací možné role uživatele
174
     *
175
     * @return array
176
     */
177
    private function getRoles()
178
    {
179
        return $this->roleRepository->findAll()->fetchPairs(RoleRepository::COLUMN_ID, RoleRepository::COLUMN_NAME);
180
    }
181
}
182

  
183
interface IUserEditFormFactory
184
{
185
    /**
186
     * @return UserEditForm
187
     */
188
    public function create();
189
}
app/AdminModule/component/User/UserGrid.php
1
<?php
2

  
3

  
4
namespace App\AdminModule\Components;
5

  
6

  
7
use App\Model\Repository\UserRepository;
8
use App\Utils\DataGrid\DataGrid;
9
use Ublaboo\DataGrid\Exception\DataGridException;
10

  
11
class UserGrid extends DataGrid
12
{
13
    /**
14
     * @var UserRepository
15
     */
16
    private $userRepository;
17

  
18
    public function __construct(UserRepository $userRepository)
19
    {
20
        $this->userRepository = $userRepository;
21

  
22
        parent::__construct(NULL, NULL);
23
    }
24

  
25
    /**
26
     * Abstraktní metoda, slouží k nastavení primárního klíče a nastavení datasource
27
     *  1. $this->setPrimaryKey();
28
     *  2. $this->setDataSource();
29
     *
30
     * @throws DataGridException
31
     */
32
    public function init()
33
    {
34
        $this->setPrimaryKey(UserRepository::COLUMN_ID);
35
        $this->setDataSource($this->userRepository->findAll());
36
    }
37

  
38
    /**
39
     * Definice sloupečků, akcí, vyhledávácích filtrů gridu
40
     *
41
     * @throws DataGridException
42
     */
43
    public function define()
44
    {
45
        // Definice sloupečků
46
        $this->addColumnNumber(UserRepository::COLUMN_ID, 'ID')->setDefaultHide(TRUE);
47
        $this->addColumnText(UserRepository::COLUMN_USERNAME, 'Uživatel');
48
        $this->addColumnText(UserRepository::COLUMN_LOGIN, 'Login');
49
        $this->addColumnText(UserRepository::COLUMN_EMAIL, 'Email');
50

  
51
        // Definice filtrů
52
        $this->addFilterText(UserRepository::COLUMN_USERNAME, 'Uživatel');
53
        $this->addFilterText(UserRepository::COLUMN_LOGIN, 'Login');
54
        $this->addFilterText(UserRepository::COLUMN_EMAIL, 'Email');
55

  
56
        // Akce
57
        $this->addAction('edit', 'upravit', 'User:edit', ['id' => UserRepository::COLUMN_ID])
58
            ->setTitle('Editovat');
59

  
60
        $this->addAction('delete', 'smazat', 'deleteUser!', ['id' => UserRepository::COLUMN_ID])
61
            ->setConfirm('Opravdu chcete uživatele "%s" odstranit?', UserRepository::COLUMN_LOGIN)
62
            ->setTitle('Odstranit')
63
            ->setClass('btn btn-xs btn-danger ajax');
64

  
65
        $this->setDefaultPerPage(20);
66
    }
67
}
68

  
69
interface IUserGridFactory
70
{
71
    /**
72
     * @return UserGrid
73
     */
74
    public function create();
75
}
app/AdminModule/presenters/UserPresenter.php
1
<?php
2

  
3

  
4
namespace App\AdminModule\Presenters;
5

  
6

  
7
use App\AdminModule\Components\IUserEditFormFactory;
8
use App\AdminModule\Components\IUserGridFactory;
9
use App\Model\Facade\UserFacade;
10

  
11
class UserPresenter extends BaseAdminPresenter
12
{
13
    /**
14
     * @var IUserGridFactory
15
     */
16
    private $userGridFactory;
17
    /**
18
     * @var IUserEditFormFactory
19
     */
20
    private $userEditFormFactory;
21
    /**
22
     * @var UserFacade
23
     */
24
    private $userFacade;
25

  
26
    public function __construct(IUserGridFactory $userGridFactory,
27
                                IUserEditFormFactory $userEditFormFactory,
28
                                UserFacade $userFacade
29
    )
30
    {
31
        parent::__construct();
32

  
33
        $this->userGridFactory = $userGridFactory;
34
        $this->userEditFormFactory = $userEditFormFactory;
35
        $this->userFacade = $userFacade;
36
    }
37

  
38
    public function actionAdd(){}
39

  
40
    public function actionEdit(int $id)
41
    {
42
        $this['userEditForm']->setUser($id);
43
    }
44

  
45
    public function handleDeleteUser(int $id)
46
    {
47
        if ($this->isAjax())
48
        {
49
            $this->userFacade->deleteUser($id);
50
            $this['userGrid']->reload();
51
        }
52
    }
53

  
54
    public function createComponentUserGrid()
55
    {
56
        return $this->userGridFactory->create();
57
    }
58

  
59
    public function createComponentUserEditForm()
60
    {
61
        return $this->userEditFormFactory->create();
62
    }
63
}
app/AdminModule/templates/@layout.latte
6 6
    <title>{ifset title}{include title|stripHtml} | {/ifset}Old Babylonian Text Corpus</title>
7 7

  
8 8
    <!-- jQuery -->
9
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
10
            integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
9
    <script src="https://code.jquery.com/jquery-3.4.0.min.js"
10
            integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg="
11 11
            crossorigin="anonymous"></script>
12 12

  
13 13
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.js"
......
96 96
    <!-- <li class="nav-item"><a n:href="Default:default" n:class="nav-link, $presenter->isLinkCurrent('Default:*') ? active" title="Users">
97 97
            Users </a></li> -->
98 98

  
99
    <li class="nav-item"><a href="#" class="nav-link" title="Users">
99
    <li class="nav-item"><a n:href="User:default" n:class="nav-link, $presenter->isLinkCurrent('User:*') ? active" title="Users">
100 100
            Users </a></li>
101
    <li class="nav-item"><a href="#" class="nav-link active" title="Groups">
101
    <li class="nav-item"><a href="#" class="nav-link" title="Groups">
102 102
            Groups </a></li>
103 103
    <li class="nav-item"><a href="#" class="nav-link" title="Rules">
104 104
            Rules </a></li>
......
126 126

  
127 127
<!--Content-->
128 128
<div class="content">
129
    <div n:foreach="$flashes as $flash" n:class="alert, 'alert-' . $flash->type">{$flash->message}</div>
129
    <div n:foreach="$flashes as $flash" n:class="alert, 'alert-' . $flash->type, alert-dismissible, fade, show" role="alert">
130
        {$flash->message}
131
        <button type="button" class="close" data-dismiss="alert" aria-label="Close">
132
            <span aria-hidden="true">&times;</span>
133
        </button>
134
    </div>
130 135

  
131 136
    {include content}
132 137
</div>
app/AdminModule/templates/User/add.latte
1
{block content}
2
<div class="row">
3
    <div class="col-11">
4
        <h4>Administrace - Nový uživatel</h4>
5
    </div>
6
    <div class="col-1">
7
        <a n:href="User:default" class="btn btn-sm btn-success"><span class="fa fa-fw fa-list"></span> Seznam uživatelů</a>
8
    </div>
9
</div>
10
{control userEditForm}
app/AdminModule/templates/User/default.latte
1
{block content}
2
<div class="row">
3
    <div class="col-11">
4
        <h4>Administrace - Seznam uživatelů</h4>
5
    </div>
6
    <div class="col-1">
7
        <a n:href="User:add" class="btn btn-sm btn-success"><span class="fa fa-fw fa-plus"></span> Přidat uživatele</a>
8
    </div>
9
</div>
10
<div class="row">
11
    <div class="col-10 offset-1">
12
        {control userGrid}
13
    </div>
14
</div>
app/AdminModule/templates/User/edit.latte
1
{block content}
2
<div class="row">
3
    <div class="col-11">
4
        <h4>Administrace - Editace uživatele</h4>
5
    </div>
6
    <div class="col-1">
7
        <a n:href="User:default" class="btn btn-sm btn-success"><span class="fa fa-fw fa-list"></span> Seznam uživatelů</a>
8
    </div>
9
</div>
10
{control userEditForm}
app/FrontModule/component/Login/LoginForm.latte
1
<div class="col-3">
2
    {form form class => 'form'}
3
        {label \App\Model\Repository\UserRepository::COLUMN_LOGIN}
4
        {input \App\Model\Repository\UserRepository::COLUMN_LOGIN class => 'form-control'}
1
<div class="row">
2
    <div class="col-3">
3
        {form form class => 'form'}
4
            {label \App\Model\Repository\UserRepository::COLUMN_LOGIN}
5
            {input \App\Model\Repository\UserRepository::COLUMN_LOGIN class => 'form-control'}
5 6

  
6
        {label \App\Model\Repository\UserRepository::COLUMN_PASSWORD}
7
        {input \App\Model\Repository\UserRepository::COLUMN_PASSWORD class => 'form-control'}
7
            {label \App\Model\Repository\UserRepository::COLUMN_PASSWORD}
8
            {input \App\Model\Repository\UserRepository::COLUMN_PASSWORD class => 'form-control'}
8 9

  
9
        {input submit class => 'form-control btn btn-success mt-4'}
10
    {/form}
10
            {input submit class => 'form-control btn btn-success mt-4'}
11
        {/form}
12
    </div>
11 13
</div>
app/FrontModule/templates/@layout.latte
6 6
    <title>{ifset title}{include title|stripHtml} | {/ifset}Old Babylonian Text Corpus</title>
7 7

  
8 8
    <!-- jQuery -->
9
    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js"
10
            integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo"
9
    <script src="https://code.jquery.com/jquery-3.4.0.min.js"
10
            integrity="sha256-BJeo0qm959uMBGb65z40ejJYGSgR7REI4+CW1fNKwOg="
11 11
            crossorigin="anonymous"></script>
12 12

  
13 13
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.js"
app/config/components.neon
1 1
services:
2 2
    # Gridy
3 3
    - App\FrontModule\Components\IExampleGirdFactory
4
    - App\AdminModule\Components\IUserGridFactory
4 5

  
5 6
    # Formuláře
6
    - App\FrontModule\Components\ILoginFormFactory
7
    - App\FrontModule\Components\ILoginFormFactory
8
    - App\AdminModule\Components\IUserEditFormFactory
app/config/model.neon
14 14
    - App\Model\Repository\TransliterationRepository
15 15
    - App\Model\Repository\UserLogRepository
16 16
    - App\Model\Repository\UserRepository
17
    - App\Model\Repository\UserRoleRepository
17
    - App\Model\Repository\UserRoleRepository
18

  
19
    - App\Model\Facade\UserFacade
app/model/facade/UserFacade.php
1
<?php
2

  
3

  
4
namespace App\Model\Facade;
5

  
6
use App\AdminModule\Components\UserEditForm;
7
use App\Model\Repository\UserRepository;
8
use App\Model\Repository\UserRoleRepository;
9
use Nette\Utils\ArrayHash;
10

  
11
class UserFacade
12
{
13
    /**
14
     * @var UserRepository
15
     */
16
    private $userRepository;
17
    /**
18
     * @var UserRoleRepository
19
     */
20
    private $userRoleRepository;
21

  
22
    public function __construct(UserRepository $userRepository,
23
                                UserRoleRepository $userRoleRepository
24
    )
25
    {
26
        $this->userRepository = $userRepository;
27
        $this->userRoleRepository = $userRoleRepository;
28
    }
29

  
30
    /**
31
     * Uloží informace o uživateli do DB
32
     *
33
     * @param array $values : hodnoty z formuláře UserEditForm
34
     * @param int|null $userId : ID uživatele, pokud se edituje
35
     * @return bool|false|int|\Nette\Database\Table\ActiveRow
36
     */
37
    public function saveUser(array $values, int $userId = NULL)
38
    {
39
        $roleId = $values[UserRoleRepository::COLUMN_ROLE_ID];
40
        unset($values[UserRoleRepository::COLUMN_ROLE_ID]);
41
        unset($values[UserEditForm::PASSWORD_CONFIRM]);
42

  
43
        if (empty($values[UserRepository::COLUMN_PASSWORD]))
44
        {
45
            unset($values[UserRepository::COLUMN_PASSWORD]);
46
        } else
47
        {
48
            $values[UserRepository::COLUMN_PASSWORD] = md5($values[UserRepository::COLUMN_PASSWORD]);
49
        }
50

  
51
        if (!empty($userId))
52
        {
53
            $userRow = $this->userRepository->findById($userId)->fetch();
54

  
55
            if ($userRow)
56
            {
57
                $userRow->update($values);
58
            }
59

  
60
            $roleRow = $userRow->related(UserRoleRepository::TABLE_NAME, UserRoleRepository::COLUMN_USER_ID)->fetch();
61

  
62
            if ($roleRow)
63
            {
64
                $roleRow->update([UserRoleRepository::COLUMN_ROLE_ID => $roleId]);
65
            }
66
        } else
67
        {
68
            $userRow = $this->userRepository->insert($values);
69
            $this->userRoleRepository->addNew($userRow->{UserRepository::COLUMN_ID}, $roleId);
70
        }
71

  
72
        return $userRow;
73
    }
74

  
75
    /**
76
     * Odstraní uživatele
77
     *
78
     * @param int $userId
79
     * @return int
80
     */
81
    public function deleteUser(int $userId)
82
    {
83
        return $this->userRepository->delete($userId);
84
    }
85
}
app/model/repository/UserRepository.php
34 34
    {
35 35
        return $this->findBy([self::COLUMN_LOGIN => $login])->fetch();
36 36
    }
37

  
38
    /**
39
     * Nalezne uživatele v DB podle jeho ID
40
     *
41
     * @param int $id
42
     * @return \Nette\Database\Table\Selection
43
     */
44
    public function findById(int $id)
45
    {
46
        return $this->findBy([self::COLUMN_ID => $id]);
47
    }
37 48
}
app/model/repository/UserRoleRepository.php
16 16
    /** Sloupečky tabulky */
17 17
    const COLUMN_USER_ID = 'user_id';
18 18
    const COLUMN_ROLE_ID = 'role_id';
19

  
20
    /**
21
     * Přiřadí roli novému uživateli
22
     *
23
     * @param int $userId
24
     * @param int $roleId
25
     * @return bool|int|\Nette\Database\Table\ActiveRow
26
     */
27
    public function addNew(int $userId, int $roleId)
28
    {
29
        return $this->insert(
30
            [
31
                UserRoleRepository::COLUMN_USER_ID => $userId,
32
                UserRoleRepository::COLUMN_ROLE_ID => $roleId
33
            ]
34
        );
35
    }
19 36
}
www/css/admin/style.css
106 106
    background-color: #003366;
107 107
    border-color: #003366;
108 108
    color: #FAFAFA;
109
}
110

  
111
.label-required{
112
    font-weight: bold;
113
}
114

  
115
.ul-alert{
116
    margin-bottom: 0;
109 117
}

Také k dispozici: Unified diff