implement CRUD for Charactertypes (resolves issue #319)
This commit is contained in:
parent
a4ccb74e8c
commit
9b05d99391
12 changed files with 493 additions and 30 deletions
35
agents/intermediate/CharactertypesAgent.inc
Normal file
35
agents/intermediate/CharactertypesAgent.inc
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Legend of Z
|
||||||
|
*
|
||||||
|
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
|
||||||
|
* @copyright 2014 Heinrich-Heine-Universität Düsseldorf
|
||||||
|
* @license http://www.gnu.org/licenses/gpl.html
|
||||||
|
* @link https://bitbucket.org/coderkun/the-legend-of-z
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace hhu\z\agents\intermediate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Agent to handle Charactertyes of a Seminary.
|
||||||
|
*
|
||||||
|
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
|
||||||
|
*/
|
||||||
|
class CharactertypesAgent extends \nre\agents\IntermediateAgent
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action: index.
|
||||||
|
*/
|
||||||
|
public function index(\nre\core\Request $request, \nre\core\Response $response)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
@ -211,7 +211,11 @@
|
||||||
),
|
),
|
||||||
'course' => array(
|
'course' => array(
|
||||||
'maxlength' => 128
|
'maxlength' => 128
|
||||||
)
|
),
|
||||||
|
'charactertypename' => array(
|
||||||
|
'minlength' => 1,
|
||||||
|
'maxlength' => 32
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -222,7 +222,7 @@
|
||||||
throw new \nre\exceptions\AccessDeniedException();
|
throw new \nre\exceptions\AccessDeniedException();
|
||||||
}
|
}
|
||||||
catch(\nre\exceptions\IdNotFoundException $e) {
|
catch(\nre\exceptions\IdNotFoundException $e) {
|
||||||
// The should be the case
|
// This should be the case
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -308,6 +308,20 @@
|
||||||
// Get XP-levels
|
// Get XP-levels
|
||||||
$xplevels = $this->Characters->getXPLevelsForSeminary($seminary['id']);
|
$xplevels = $this->Characters->getXPLevelsForSeminary($seminary['id']);
|
||||||
|
|
||||||
|
// Get Avatars
|
||||||
|
if(count($xplevels) > 0)
|
||||||
|
{
|
||||||
|
foreach($types as &$type)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
$type['avatar'] = $this->Avatars->getAvatarByTypeAndLevel($seminary['id'], $type['url'], $xplevels[0]['level']);
|
||||||
|
}
|
||||||
|
catch(\nre\exceptions\IdNotFoundException $e) {
|
||||||
|
// No Avatar available
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Set titile
|
// Set titile
|
||||||
$this->addTitleLocalized('Create Character');
|
$this->addTitleLocalized('Create Character');
|
||||||
|
|
|
||||||
198
controllers/CharactertypesController.inc
Normal file
198
controllers/CharactertypesController.inc
Normal file
|
|
@ -0,0 +1,198 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Legend of Z
|
||||||
|
*
|
||||||
|
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
|
||||||
|
* @copyright 2014 Heinrich-Heine-Universität Düsseldorf
|
||||||
|
* @license http://www.gnu.org/licenses/gpl.html
|
||||||
|
* @link https://bitbucket.org/coderkun/the-legend-of-z
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace hhu\z\controllers;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller of the CharactertypesAgent to handle Charactertyes of a
|
||||||
|
* Seminary.
|
||||||
|
*
|
||||||
|
* @author Oliver Hanraths <oliver.hanraths@uni-duesseldorf.de>
|
||||||
|
*/
|
||||||
|
class CharactertypesController extends \hhu\z\controllers\SeminaryController
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Required components
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $components = array('validation');
|
||||||
|
/**
|
||||||
|
* Required models
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $models = array('charactertypes');
|
||||||
|
/**
|
||||||
|
* User permissions
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
public $permissions = array(
|
||||||
|
'manage' => array('admin', 'moderator', 'user')
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Action: manage.
|
||||||
|
*
|
||||||
|
* Manage Characters.
|
||||||
|
*
|
||||||
|
* @throws IdNotFoundException
|
||||||
|
* @param string $seminaryUrl URL-Title of a Seminary
|
||||||
|
*/
|
||||||
|
public function manage($seminaryUrl)
|
||||||
|
{
|
||||||
|
// Get seminary
|
||||||
|
$seminary = $this->Seminaries->getSeminaryByUrl($seminaryUrl);
|
||||||
|
|
||||||
|
// Check permissions
|
||||||
|
if(
|
||||||
|
(is_null(self::$character) && count(array_intersect(array('admin', 'moderator'), \hhu\z\controllers\IntermediateController::$user['roles'])) == 0) ||
|
||||||
|
(!is_null(self::$character) && count(array_intersect(array('admin', 'moderator'), self::$character['characterroles'])) == 0)
|
||||||
|
) {
|
||||||
|
throw new AccessDeniedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get Charactertypes
|
||||||
|
$charactertypes = $this->Charactertypes->getCharacterTypesForSeminary($seminary['id']);
|
||||||
|
|
||||||
|
// Values
|
||||||
|
$charactertypesNames = array();
|
||||||
|
foreach($charactertypes as &$charactertype) {
|
||||||
|
$charactertypesNames[$charactertype['id']] = $charactertype['name'];
|
||||||
|
}
|
||||||
|
$deleteCharactertypes = null;
|
||||||
|
$charactertypeName = '';
|
||||||
|
$validations = array(
|
||||||
|
'edit-charactertypes' => true,
|
||||||
|
'create-charactertype' => true
|
||||||
|
);
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
$action = null;
|
||||||
|
if($this->request->getRequestMethod() == 'POST')
|
||||||
|
{
|
||||||
|
// Edit and delete Charactertypes
|
||||||
|
if(!is_null($this->request->getPostParam('edit-charactertypes')))
|
||||||
|
{
|
||||||
|
$action = 'edit-charactertypes';
|
||||||
|
|
||||||
|
// Get params and validate them
|
||||||
|
$charactertypesNames = $this->request->getPostParam('charactertypes');
|
||||||
|
$deleteCharactertypes = $this->request->getPostParam('delete-charactertypes');
|
||||||
|
foreach($charactertypes as &$charactertype)
|
||||||
|
{
|
||||||
|
if(!is_null($deleteCharactertypes) && array_key_exists($charactertype['id'], $deleteCharactertypes)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$name = $charactertypesNames[$charactertype['id']];
|
||||||
|
$charactertypeValidation = $this->Validation->validate($name, \nre\configs\AppConfig::$validation['charactertypename']);
|
||||||
|
if($charactertypeValidation !== true)
|
||||||
|
{
|
||||||
|
if(!is_array($validations['edit-charactertypes'])) {
|
||||||
|
$validations['edit-charactertypes'] = array();
|
||||||
|
}
|
||||||
|
if(!array_key_exists($charactertype['id'], $validations['edit-charactertypes']) || !is_array($validations['edit-charactertypes'][$charactertype['id']])) {
|
||||||
|
$validations['edit-charactertypes'][$charactertype['id']] = array();
|
||||||
|
}
|
||||||
|
$validations['edit-charactertypes'][$charactertype['id']] = $this->Validation->addValidationResults($validations['edit-charactertypes'][$charactertype['id']], 'charactertypename', $charactertypeValidation);
|
||||||
|
}
|
||||||
|
if($this->Charactertypes->charactertypeNameExists($seminary['id'], $name, $charactertype['id']))
|
||||||
|
{
|
||||||
|
if(!is_array($validations['edit-charactertypes'])) {
|
||||||
|
$validations['edit-charactertypes'] = array();
|
||||||
|
}
|
||||||
|
if(!array_key_exists($charactertype['id'], $validations['edit-charactertypes']) || !is_array($validations['edit-charactertypes'][$charactertype['id']])) {
|
||||||
|
$validations['edit-charactertypes'][$charactertype['id']] = array();
|
||||||
|
}
|
||||||
|
$validations['edit-charactertypes'][$charactertype['id']] = $this->Validation->addValidationResult($validations['edit-charactertypes'][$charactertype['id']], 'charactertypename', 'exist', true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Edit and delete
|
||||||
|
if($validations['edit-charactertypes'] === true)
|
||||||
|
{
|
||||||
|
foreach($charactertypes as &$charactertype)
|
||||||
|
{
|
||||||
|
// Delete
|
||||||
|
if(!is_null($deleteCharactertypes) && array_key_exists($charactertype['id'], $deleteCharactertypes)) {
|
||||||
|
$this->Charactertypes->deleteCharactertype($charactertype['id']);
|
||||||
|
}
|
||||||
|
// Edit
|
||||||
|
elseif(!is_null($charactertypesNames) && array_key_exists($charactertype['id'], $charactertypesNames))
|
||||||
|
{
|
||||||
|
$name = $charactertypesNames[$charactertype['id']];
|
||||||
|
$this->Charactertypes->editCharactertype($charactertype['id'], $name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect
|
||||||
|
//$this->redirect($this->linker->link(array('seminaries', 'index')));
|
||||||
|
$this->redirect($this->linker->link(null, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create Charactertype
|
||||||
|
if(!is_null($this->request->getPostParam('create-charactertype')))
|
||||||
|
{
|
||||||
|
$action = 'create-charactertype';
|
||||||
|
|
||||||
|
// Get params and validate them
|
||||||
|
$validations[$action] = $this->Validation->validateParams($this->request->getPostParams(), array('charactertypename'));
|
||||||
|
$charactertypeName = $this->request->getPostParam('charactertypename');
|
||||||
|
if($this->Charactertypes->charactertypeNameExists($seminary['id'], $charactertypeName)) {
|
||||||
|
$validations[$action] = $this->Validation->addValidationResult($validations[$action], 'charactertypename', 'exist', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create
|
||||||
|
if($validations[$action] === true)
|
||||||
|
{
|
||||||
|
$this->Charactertypes->createCharactertype(
|
||||||
|
$this->Auth->getUserId(),
|
||||||
|
$seminary['id'],
|
||||||
|
$charactertypeName
|
||||||
|
);
|
||||||
|
$charactertypeName = '';
|
||||||
|
|
||||||
|
// Redirect
|
||||||
|
$this->redirect($this->linker->link(null, 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get validation settings
|
||||||
|
$validationSettings = array(
|
||||||
|
'charactertypename' => \nre\configs\AppConfig::$validation['charactertypename']
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Set titile
|
||||||
|
$this->addTitleLocalized('Manage Charactertypes');
|
||||||
|
$this->addTitle($seminary['title']);
|
||||||
|
|
||||||
|
// Pass data to view
|
||||||
|
$this->set('seminary', $seminary);
|
||||||
|
$this->set('charactertypesNames', $charactertypesNames);
|
||||||
|
$this->set('deleteCharactertypes', $deleteCharactertypes);
|
||||||
|
$this->set('charactertypeName', $charactertypeName);
|
||||||
|
$this->set('action', $action);
|
||||||
|
$this->set('validations', $validations);
|
||||||
|
$this->set('validationSettings', $validationSettings);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
|
|
@ -24,7 +24,7 @@
|
||||||
*
|
*
|
||||||
* @var array
|
* @var array
|
||||||
*/
|
*/
|
||||||
public $models = array('seminaries', 'users', 'characterroles', 'questgroupshierarchy', 'questgroups', 'media');
|
public $models = array('seminaries', 'users', 'characterroles', 'charactertypes', 'questgroupshierarchy', 'questgroups', 'media');
|
||||||
/**
|
/**
|
||||||
* Required components
|
* Required components
|
||||||
*
|
*
|
||||||
|
|
@ -75,6 +75,7 @@
|
||||||
$description = \hhu\z\Utils::shortenString($seminary['description'], 100, 120);
|
$description = \hhu\z\Utils::shortenString($seminary['description'], 100, 120);
|
||||||
$seminary['description'] = $description.(strlen($description) < strlen($seminary['description']) ? ' …' : null);
|
$seminary['description'] = $description.(strlen($description) < strlen($seminary['description']) ? ' …' : null);
|
||||||
$seminary['creator'] = $this->Users->getUserById($seminary['created_user_id']);
|
$seminary['creator'] = $this->Users->getUserById($seminary['created_user_id']);
|
||||||
|
$seminary['charactertypes'] = $this->Charactertypes->getCharacterTypesForSeminary($seminary['id']);
|
||||||
|
|
||||||
// Character of currently logged-in user
|
// Character of currently logged-in user
|
||||||
try {
|
try {
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,8 +1,8 @@
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: The Legend of Z\n"
|
"Project-Id-Version: The Legend of Z\n"
|
||||||
"POT-Creation-Date: 2014-05-28 10:27+0100\n"
|
"POT-Creation-Date: 2014-05-30 10:44+0100\n"
|
||||||
"PO-Revision-Date: 2014-05-28 10:29+0100\n"
|
"PO-Revision-Date: 2014-05-30 10:46+0100\n"
|
||||||
"Last-Translator: \n"
|
"Last-Translator: \n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: de_DE\n"
|
"Language: de_DE\n"
|
||||||
|
|
@ -17,7 +17,7 @@ msgstr ""
|
||||||
"X-Poedit-SearchPath-1: questtypes\n"
|
"X-Poedit-SearchPath-1: questtypes\n"
|
||||||
"X-Poedit-SearchPath-2: controllers\n"
|
"X-Poedit-SearchPath-2: controllers\n"
|
||||||
|
|
||||||
#: controllers/CharactersController.inc:373
|
#: controllers/CharactersController.inc:387
|
||||||
#: controllers/UsersController.inc:312 views/ajax/characters/index.tpl:10
|
#: controllers/UsersController.inc:312 views/ajax/characters/index.tpl:10
|
||||||
#: views/ajax/users/index.tpl:10 views/html/characters/index.tpl:39
|
#: views/ajax/users/index.tpl:10 views/html/characters/index.tpl:39
|
||||||
#: views/html/characters/manage.tpl:35 views/html/characters/manage.tpl:50
|
#: views/html/characters/manage.tpl:35 views/html/characters/manage.tpl:50
|
||||||
|
|
@ -27,7 +27,7 @@ msgstr ""
|
||||||
msgid "Admin"
|
msgid "Admin"
|
||||||
msgstr "Administrator"
|
msgstr "Administrator"
|
||||||
|
|
||||||
#: controllers/CharactersController.inc:379
|
#: controllers/CharactersController.inc:393
|
||||||
#: controllers/UsersController.inc:318 views/ajax/characters/index.tpl:12
|
#: controllers/UsersController.inc:318 views/ajax/characters/index.tpl:12
|
||||||
#: views/ajax/users/index.tpl:12 views/html/characters/index.tpl:40
|
#: views/ajax/users/index.tpl:12 views/html/characters/index.tpl:40
|
||||||
#: views/html/characters/manage.tpl:36 views/html/characters/manage.tpl:51
|
#: views/html/characters/manage.tpl:36 views/html/characters/manage.tpl:51
|
||||||
|
|
@ -37,7 +37,7 @@ msgstr "Administrator"
|
||||||
msgid "Moderator"
|
msgid "Moderator"
|
||||||
msgstr "Moderator"
|
msgstr "Moderator"
|
||||||
|
|
||||||
#: controllers/CharactersController.inc:385
|
#: controllers/CharactersController.inc:399
|
||||||
#: controllers/UsersController.inc:324 views/ajax/characters/index.tpl:14
|
#: controllers/UsersController.inc:324 views/ajax/characters/index.tpl:14
|
||||||
#: views/ajax/users/index.tpl:14 views/html/characters/index.tpl:41
|
#: views/ajax/users/index.tpl:14 views/html/characters/index.tpl:41
|
||||||
#: views/html/characters/manage.tpl:37 views/html/characters/manage.tpl:53
|
#: views/html/characters/manage.tpl:37 views/html/characters/manage.tpl:53
|
||||||
|
|
@ -382,6 +382,8 @@ msgstr "Das Icon ist ungültig"
|
||||||
#: views/html/charactergroups/creategroupsgroup.tpl:22
|
#: views/html/charactergroups/creategroupsgroup.tpl:22
|
||||||
#: views/html/charactergroups/editgroup.tpl:34
|
#: views/html/charactergroups/editgroup.tpl:34
|
||||||
#: views/html/charactergroups/editgroupsgroup.tpl:22
|
#: views/html/charactergroups/editgroupsgroup.tpl:22
|
||||||
|
#: views/html/charactertypes/manage.tpl:29
|
||||||
|
#: views/html/charactertypes/manage.tpl:69
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Name is too short (min. %d chars)"
|
msgid "Name is too short (min. %d chars)"
|
||||||
msgstr "Der Name ist zu kurz (min. %d Zeichen)"
|
msgstr "Der Name ist zu kurz (min. %d Zeichen)"
|
||||||
|
|
@ -390,6 +392,8 @@ msgstr "Der Name ist zu kurz (min. %d Zeichen)"
|
||||||
#: views/html/charactergroups/creategroupsgroup.tpl:24
|
#: views/html/charactergroups/creategroupsgroup.tpl:24
|
||||||
#: views/html/charactergroups/editgroup.tpl:36
|
#: views/html/charactergroups/editgroup.tpl:36
|
||||||
#: views/html/charactergroups/editgroupsgroup.tpl:24
|
#: views/html/charactergroups/editgroupsgroup.tpl:24
|
||||||
|
#: views/html/charactertypes/manage.tpl:31
|
||||||
|
#: views/html/charactertypes/manage.tpl:71
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Name is too long (max. %d chars)"
|
msgid "Name is too long (max. %d chars)"
|
||||||
msgstr "Der Name ist zu lang (max. %d Zeichen)"
|
msgstr "Der Name ist zu lang (max. %d Zeichen)"
|
||||||
|
|
@ -405,6 +409,8 @@ msgstr "Der Name enthält ungültige Zeichen"
|
||||||
#: views/html/charactergroups/creategroupsgroup.tpl:28
|
#: views/html/charactergroups/creategroupsgroup.tpl:28
|
||||||
#: views/html/charactergroups/editgroup.tpl:40
|
#: views/html/charactergroups/editgroup.tpl:40
|
||||||
#: views/html/charactergroups/editgroupsgroup.tpl:28
|
#: views/html/charactergroups/editgroupsgroup.tpl:28
|
||||||
|
#: views/html/charactertypes/manage.tpl:33
|
||||||
|
#: views/html/charactertypes/manage.tpl:73
|
||||||
msgid "Name already exists"
|
msgid "Name already exists"
|
||||||
msgstr "Der Name existiert bereits"
|
msgstr "Der Name existiert bereits"
|
||||||
|
|
||||||
|
|
@ -412,6 +418,8 @@ msgstr "Der Name existiert bereits"
|
||||||
#: views/html/charactergroups/creategroupsgroup.tpl:30
|
#: views/html/charactergroups/creategroupsgroup.tpl:30
|
||||||
#: views/html/charactergroups/editgroup.tpl:42
|
#: views/html/charactergroups/editgroup.tpl:42
|
||||||
#: views/html/charactergroups/editgroupsgroup.tpl:30
|
#: views/html/charactergroups/editgroupsgroup.tpl:30
|
||||||
|
#: views/html/charactertypes/manage.tpl:35
|
||||||
|
#: views/html/charactertypes/manage.tpl:75
|
||||||
msgid "Name invalid"
|
msgid "Name invalid"
|
||||||
msgstr "Der Name ist ungültig"
|
msgstr "Der Name ist ungültig"
|
||||||
|
|
||||||
|
|
@ -441,8 +449,9 @@ msgstr "Icon"
|
||||||
#: views/html/charactergroups/editgroup.tpl:75
|
#: views/html/charactergroups/editgroup.tpl:75
|
||||||
#: views/html/charactergroups/editgroupsgroup.tpl:46
|
#: views/html/charactergroups/editgroupsgroup.tpl:46
|
||||||
#: views/html/charactergroups/editgroupsgroup.tpl:47
|
#: views/html/charactergroups/editgroupsgroup.tpl:47
|
||||||
#: views/html/quests/create.tpl:15 views/html/quests/create.tpl:16
|
#: views/html/charactertypes/manage.tpl:88
|
||||||
#: views/html/users/user.tpl:23
|
#: views/html/charactertypes/manage.tpl:89 views/html/quests/create.tpl:15
|
||||||
|
#: views/html/quests/create.tpl:16 views/html/users/user.tpl:23
|
||||||
msgid "Name"
|
msgid "Name"
|
||||||
msgstr "Name"
|
msgstr "Name"
|
||||||
|
|
||||||
|
|
@ -456,7 +465,8 @@ msgstr "Motto"
|
||||||
#: views/html/charactergroups/creategroup.tpl:77
|
#: views/html/charactergroups/creategroup.tpl:77
|
||||||
#: views/html/charactergroups/creategroupsgroup.tpl:50
|
#: views/html/charactergroups/creategroupsgroup.tpl:50
|
||||||
#: views/html/charactergroupsquests/create.tpl:93
|
#: views/html/charactergroupsquests/create.tpl:93
|
||||||
#: views/html/characters/register.tpl:94 views/html/library/create.tpl:46
|
#: views/html/characters/register.tpl:96
|
||||||
|
#: views/html/charactertypes/manage.tpl:91 views/html/library/create.tpl:46
|
||||||
#: views/html/library/edit.tpl:124 views/html/questgroups/create.tpl:17
|
#: views/html/library/edit.tpl:124 views/html/questgroups/create.tpl:17
|
||||||
#: views/html/quests/create.tpl:43 views/html/seminaries/create.tpl:75
|
#: views/html/quests/create.tpl:43 views/html/seminaries/create.tpl:75
|
||||||
#: views/html/users/create.tpl:96
|
#: views/html/users/create.tpl:96
|
||||||
|
|
@ -486,9 +496,9 @@ msgstr "Soll die %s-Gruppen „%s“ wirklich gelöscht werden?"
|
||||||
#: views/html/charactergroups/deletegroup.tpl:15
|
#: views/html/charactergroups/deletegroup.tpl:15
|
||||||
#: views/html/charactergroups/deletegroupsgroup.tpl:14
|
#: views/html/charactergroups/deletegroupsgroup.tpl:14
|
||||||
#: views/html/charactergroupsquests/delete.tpl:15
|
#: views/html/charactergroupsquests/delete.tpl:15
|
||||||
#: views/html/characters/delete.tpl:17 views/html/library/delete.tpl:14
|
#: views/html/characters/delete.tpl:17 views/html/charactertypes/manage.tpl:48
|
||||||
#: views/html/library/edit.tpl:83 views/html/seminaries/delete.tpl:13
|
#: views/html/library/delete.tpl:14 views/html/library/edit.tpl:83
|
||||||
#: views/html/users/delete.tpl:11
|
#: views/html/seminaries/delete.tpl:13 views/html/users/delete.tpl:11
|
||||||
msgid "delete"
|
msgid "delete"
|
||||||
msgstr "löschen"
|
msgstr "löschen"
|
||||||
|
|
||||||
|
|
@ -744,8 +754,8 @@ msgid "File invalid"
|
||||||
msgstr "Die Datei ist ungültig"
|
msgstr "Die Datei ist ungültig"
|
||||||
|
|
||||||
#: views/html/charactergroupsquests/manage.tpl:66
|
#: views/html/charactergroupsquests/manage.tpl:66
|
||||||
#: views/html/library/edit.tpl:46 views/html/library/edit.tpl:86
|
#: views/html/charactertypes/manage.tpl:52 views/html/library/edit.tpl:46
|
||||||
#: views/html/users/edit.tpl:103
|
#: views/html/library/edit.tpl:86 views/html/users/edit.tpl:103
|
||||||
msgid "save"
|
msgid "save"
|
||||||
msgstr "speichern"
|
msgstr "speichern"
|
||||||
|
|
||||||
|
|
@ -844,12 +854,12 @@ msgstr "Charaktereigenschaften"
|
||||||
msgid "Character name"
|
msgid "Character name"
|
||||||
msgstr "Charaktername"
|
msgstr "Charaktername"
|
||||||
|
|
||||||
#: views/html/characters/edit.tpl:81 views/html/characters/register.tpl:67
|
#: views/html/characters/edit.tpl:81 views/html/characters/register.tpl:69
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "The Seminary field “%s” is invalid"
|
msgid "The Seminary field “%s” is invalid"
|
||||||
msgstr "Das Kursfeld „%s“ ist ungültig"
|
msgstr "Das Kursfeld „%s“ ist ungültig"
|
||||||
|
|
||||||
#: views/html/characters/edit.tpl:86 views/html/characters/register.tpl:72
|
#: views/html/characters/edit.tpl:86 views/html/characters/register.tpl:74
|
||||||
msgid "Seminary fields"
|
msgid "Seminary fields"
|
||||||
msgstr "Kursfelder"
|
msgstr "Kursfelder"
|
||||||
|
|
||||||
|
|
@ -903,6 +913,19 @@ msgstr "Charakter erstellen"
|
||||||
msgid "Please choose an avatar"
|
msgid "Please choose an avatar"
|
||||||
msgstr "Bitte wähle einen Avatar aus"
|
msgstr "Bitte wähle einen Avatar aus"
|
||||||
|
|
||||||
|
#: views/html/charactertypes/manage.tpl:9 views/html/seminaries/index.tpl:38
|
||||||
|
#: views/html/seminaries/seminary.tpl:14
|
||||||
|
msgid "Manage Charactertypes"
|
||||||
|
msgstr "Charakterrassen verwalten"
|
||||||
|
|
||||||
|
#: views/html/charactertypes/manage.tpl:14
|
||||||
|
msgid "Edit Charactertypes"
|
||||||
|
msgstr "Characterrassen bearbeiten"
|
||||||
|
|
||||||
|
#: views/html/charactertypes/manage.tpl:58
|
||||||
|
msgid "Create new Charactertype"
|
||||||
|
msgstr "Neue Characterrasse erstellen"
|
||||||
|
|
||||||
#: views/html/error/index.tpl:5 views/html/error/index.tpl:14
|
#: views/html/error/index.tpl:5 views/html/error/index.tpl:14
|
||||||
#: views/html/introduction/index.tpl:9 views/html/menu/index.tpl:6
|
#: views/html/introduction/index.tpl:9 views/html/menu/index.tpl:6
|
||||||
#: views/html/users/login.tpl:6 views/html/users/login.tpl:20
|
#: views/html/users/login.tpl:6 views/html/users/login.tpl:20
|
||||||
|
|
@ -1111,7 +1134,7 @@ msgstr "Quest"
|
||||||
msgid "Go on"
|
msgid "Go on"
|
||||||
msgstr "Fortfahren"
|
msgstr "Fortfahren"
|
||||||
|
|
||||||
#: views/html/quests/quest.tpl:134 views/html/seminaries/seminary.tpl:36
|
#: views/html/quests/quest.tpl:134 views/html/seminaries/seminary.tpl:43
|
||||||
msgid "Let’s go"
|
msgid "Let’s go"
|
||||||
msgstr "Auf ins Abenteuer!"
|
msgstr "Auf ins Abenteuer!"
|
||||||
|
|
||||||
|
|
@ -1168,7 +1191,7 @@ msgstr "Stimmungsbild"
|
||||||
msgid "Course"
|
msgid "Course"
|
||||||
msgstr "Kurs"
|
msgstr "Kurs"
|
||||||
|
|
||||||
#: views/html/seminaries/delete.tpl:10 views/html/seminaries/seminary.tpl:10
|
#: views/html/seminaries/delete.tpl:10 views/html/seminaries/seminary.tpl:11
|
||||||
msgid "Delete seminary"
|
msgid "Delete seminary"
|
||||||
msgstr "Kurs löschen"
|
msgstr "Kurs löschen"
|
||||||
|
|
||||||
|
|
@ -1177,7 +1200,7 @@ msgstr "Kurs löschen"
|
||||||
msgid "Should the seminary “%s” really be deleted?"
|
msgid "Should the seminary “%s” really be deleted?"
|
||||||
msgstr "Soll der Kurs „%s“ wirklich gelöscht werden?"
|
msgstr "Soll der Kurs „%s“ wirklich gelöscht werden?"
|
||||||
|
|
||||||
#: views/html/seminaries/edit.tpl:10 views/html/seminaries/seminary.tpl:9
|
#: views/html/seminaries/edit.tpl:10 views/html/seminaries/seminary.tpl:10
|
||||||
msgid "Edit seminary"
|
msgid "Edit seminary"
|
||||||
msgstr "Kurs bearbeiten"
|
msgstr "Kurs bearbeiten"
|
||||||
|
|
||||||
|
|
@ -1190,20 +1213,20 @@ msgstr "Neuen Kurs erstellen"
|
||||||
msgid "created by %s on %s"
|
msgid "created by %s on %s"
|
||||||
msgstr "erstellt von %s am %s"
|
msgstr "erstellt von %s am %s"
|
||||||
|
|
||||||
#: views/html/seminaries/index.tpl:35
|
#: views/html/seminaries/index.tpl:36
|
||||||
msgid "Create a Character"
|
msgid "Create a Character"
|
||||||
msgstr "Erstelle einen Charakter"
|
msgstr "Erstelle einen Charakter"
|
||||||
|
|
||||||
#: views/html/seminaries/index.tpl:37
|
#: views/html/seminaries/index.tpl:41
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Your Character “%s” has not been activated yet"
|
msgid "Your Character “%s” has not been activated yet"
|
||||||
msgstr "Dein Charakter „%s“ wurde noch nicht aktiviert"
|
msgstr "Dein Charakter „%s“ wurde noch nicht aktiviert"
|
||||||
|
|
||||||
#: views/html/seminaries/seminary.tpl:11
|
#: views/html/seminaries/seminary.tpl:18
|
||||||
msgid "Show Quests"
|
msgid "Show Quests"
|
||||||
msgstr "Quests anzeigen"
|
msgstr "Quests anzeigen"
|
||||||
|
|
||||||
#: views/html/seminaries/seminary.tpl:12
|
#: views/html/seminaries/seminary.tpl:19
|
||||||
msgid "Recalculate XPs"
|
msgid "Recalculate XPs"
|
||||||
msgstr "XP neuberechnen"
|
msgstr "XP neuberechnen"
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,87 @@
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if a Charactertype name already exists.
|
||||||
|
*
|
||||||
|
* @param int $seminaryId ID of Seminary
|
||||||
|
* @param string $name Charactertype name to check
|
||||||
|
* @param int $charactertypeId Do not check this ID (for editing)
|
||||||
|
* @return boolean Whether Charactertype name exists or not
|
||||||
|
*/
|
||||||
|
public function charactertypeNameExists($seminaryId, $name, $charactertypeId=null)
|
||||||
|
{
|
||||||
|
$data = $this->db->query(
|
||||||
|
'SELECT id '.
|
||||||
|
'FROM charactertypes '.
|
||||||
|
'WHERE seminary_id = ? AND (name = ? OR url = ?)',
|
||||||
|
'iss',
|
||||||
|
$seminaryId,
|
||||||
|
$name,
|
||||||
|
\nre\core\Linker::createLinkParam($name)
|
||||||
|
);
|
||||||
|
|
||||||
|
return (!empty($data) && (is_null($charactertypeId) || $charactertypeId != $data[0]['id']));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Charactertype for a Seminary.
|
||||||
|
*
|
||||||
|
* @param int $userId ID of creating user
|
||||||
|
* @param int $seminaryId ID of Seminary
|
||||||
|
* @param string $name Name for new Charactertype
|
||||||
|
* @return int ID of newly created Charactertype
|
||||||
|
*/
|
||||||
|
public function createCharactertype($userId, $seminaryId, $name)
|
||||||
|
{
|
||||||
|
$this->db->query(
|
||||||
|
'INSERT INTO charactertypes '.
|
||||||
|
'(created_user_id, seminary_id, name, url) '.
|
||||||
|
'VALUES '.
|
||||||
|
'(?, ?, ?, ?) ',
|
||||||
|
'iiss',
|
||||||
|
$userId,
|
||||||
|
$seminaryId,
|
||||||
|
$name,
|
||||||
|
\nre\core\Linker::createLinkParam($name)
|
||||||
|
);
|
||||||
|
|
||||||
|
return $this->db->getInsertId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edit a Charactertype.
|
||||||
|
*
|
||||||
|
* @param int $charactertypeId ID of Charactertype to edit
|
||||||
|
* @param string $name New name of Charactertype
|
||||||
|
*/
|
||||||
|
public function editCharactertype($charactertypeId, $name)
|
||||||
|
{
|
||||||
|
$this->db->query(
|
||||||
|
'UPDATE charactertypes '.
|
||||||
|
'SET name = ?, url = ? '.
|
||||||
|
'WHERE id = ?',
|
||||||
|
'ssi',
|
||||||
|
$name,
|
||||||
|
\nre\core\Linker::createLinkParam($name),
|
||||||
|
$charactertypeId
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delete a Charactertype.
|
||||||
|
*
|
||||||
|
* @param int $charactertypeId ID of Charactertype to delete
|
||||||
|
*/
|
||||||
|
public function deleteCharactertype($charactertypeId)
|
||||||
|
{
|
||||||
|
$this->db->query('DELETE FROM charactertypes WHERE id = ?', 'i', $charactertypeId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,9 @@
|
||||||
<li>
|
<li>
|
||||||
<label for="type-<?=$type['id']?>">
|
<label for="type-<?=$type['id']?>">
|
||||||
<p><?=$type['name']?></p>
|
<p><?=$type['name']?></p>
|
||||||
|
<?php if(array_key_exists('avatar', $type)) : ?>
|
||||||
<img id="avatar" src="<?=$linker->link(array('media','avatar',$seminary['url'],$type['url'],$xplevels[0]['level'],'portrait'))?>" />
|
<img id="avatar" src="<?=$linker->link(array('media','avatar',$seminary['url'],$type['url'],$xplevels[0]['level'],'portrait'))?>" />
|
||||||
|
<?php endif ?>
|
||||||
</label>
|
</label>
|
||||||
<input id="type-<?=$type['id']?>" name="type" type="radio" value="<?=$type['url']?>" <?php if(array_key_exists('selected', $type) && $type['selected']) : ?>checked="checked"<?php endif ?> />
|
<input id="type-<?=$type['id']?>" name="type" type="radio" value="<?=$type['url']?>" <?php if(array_key_exists('selected', $type) && $type['selected']) : ?>checked="checked"<?php endif ?> />
|
||||||
</li>
|
</li>
|
||||||
|
|
|
||||||
92
views/html/charactertypes/manage.tpl
Normal file
92
views/html/charactertypes/manage.tpl
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
<?php if(!is_null($seminary['seminarymedia_id'])) : ?>
|
||||||
|
<div class="moodpic">
|
||||||
|
<img src="<?=$linker->link(array('media','seminarymoodpic',$seminary['url']))?>">
|
||||||
|
</div>
|
||||||
|
<?php endif ?>
|
||||||
|
<ul class="breadcrumbs">
|
||||||
|
<li><a href="<?=$linker->link(array('seminaries',$seminary['url']))?>"><?=$seminary['title']?></a></li>
|
||||||
|
</ul>
|
||||||
|
<h1><?=_('Manage Charactertypes')?></h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2><?=_('Edit Charactertypes')?></h2>
|
||||||
|
<form method="post">
|
||||||
|
<ul>
|
||||||
|
<?php foreach($charactertypesNames as $charactertypeId => &$name) : ?>
|
||||||
|
<li>
|
||||||
|
<?php if($validations['edit-charactertypes'] !== true && array_key_exists($charactertypeId, $validations['edit-charactertypes']) && $validations['edit-charactertypes'][$charactertypeId] !== true) : ?>
|
||||||
|
<ul>
|
||||||
|
<?php foreach($validations['edit-charactertypes'][$charactertypeId] as $field => &$settings) : ?>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<?php foreach($settings as $setting => $value) : ?>
|
||||||
|
<li>
|
||||||
|
<?php switch($field) {
|
||||||
|
case 'charactertypename':
|
||||||
|
switch($setting) {
|
||||||
|
case 'minlength': printf(_('Name is too short (min. %d chars)'), $value);
|
||||||
|
break;
|
||||||
|
case 'maxlength': printf(_('Name is too long (max. %d chars)'), $value);
|
||||||
|
break;
|
||||||
|
case 'exist': echo _('Name already exists');
|
||||||
|
break;
|
||||||
|
default: echo _('Name invalid');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} ?>
|
||||||
|
</li>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif ?>
|
||||||
|
<input id="charactertype-<?=$charactertypeId?>" type="text" name="charactertypes[<?=$charactertypeId?>]" placeholder="<?=$name?>" title="<?=$name?>" required="required" maxlength="<?=$validationSettings['charactertype']['maxlength']?>" value="<?=$name?>" <?=($validations['edit-charactertypes'] !== true && array_key_exists($charactertypeId, $validations['edit-charactertypes']) && $validations['edit-charactertypes'][$charactertypeId] !== true && array_key_exists('charactertypename', $validations['edit-charactertypes'][$charactertypeId])) ? 'class="invalid"' : null?>/>
|
||||||
|
<input id="charactertype-<?=$charactertypeId?>-delete" type="checkbox" name="delete-charactertypes[<?=$charactertypeId?>]" <?php if(!is_null($deleteCharactertypes) && array_key_exists($charactertypeId, $deleteCharactertypes)) : ?>checked="checked"<?php endif ?> />
|
||||||
|
<label for="charactertype-<?=$charactertypeId?>-delete"><?=_('delete')?></label><br />
|
||||||
|
</li>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</ul>
|
||||||
|
<input type="submit" name="edit-charactertypes" value="<?=_('save')?>" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h2><?=_('Create new Charactertype')?></h2>
|
||||||
|
<?php if($validations['create-charactertype'] !== true) : ?>
|
||||||
|
<ul>
|
||||||
|
<?php foreach($validations['create-charactertype'] as $field => &$settings) : ?>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<?php foreach($settings as $setting => $value) : ?>
|
||||||
|
<li>
|
||||||
|
<?php switch($field) {
|
||||||
|
case 'charactertypename':
|
||||||
|
switch($setting) {
|
||||||
|
case 'minlength': printf(_('Name is too short (min. %d chars)'), $value);
|
||||||
|
break;
|
||||||
|
case 'maxlength': printf(_('Name is too long (max. %d chars)'), $value);
|
||||||
|
break;
|
||||||
|
case 'exist': echo _('Name already exists');
|
||||||
|
break;
|
||||||
|
default: echo _('Name invalid');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} ?>
|
||||||
|
</li>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
<?php endforeach ?>
|
||||||
|
</ul>
|
||||||
|
<?php endif ?>
|
||||||
|
<form method="post">
|
||||||
|
<fieldset>
|
||||||
|
<label for="charactertypename"><?=_('Name')?>:</legend>
|
||||||
|
<input id="charactertypename" type="text" name="charactertypename" placeholder="<?=_('Name')?>" title="<?=_('Name')?>" required="required" maxlength="<?=$validationSettings['charactertypename']['maxlength']?>" value="<?=$charactertypeName?>" <?=($validations['create-charactertype'] !== true && array_key_exists('title', $validations['create-charactertype'])) ? 'class="invalid"' : null?> />
|
||||||
|
</fieldset>
|
||||||
|
<input type="submit" name="create-charactertype" value="<?=_('create')?>" />
|
||||||
|
</form>
|
||||||
|
|
@ -32,10 +32,16 @@
|
||||||
<p><?=\hhu\z\Utils::t($seminary['description'])?></p>
|
<p><?=\hhu\z\Utils::t($seminary['description'])?></p>
|
||||||
<p><small><?=sprintf(_('created by %s on %s'), $seminary['creator']['username'], $dateFormatter->format(new \DateTime($seminary['created'])))?></small></p>
|
<p><small><?=sprintf(_('created by %s on %s'), $seminary['creator']['username'], $dateFormatter->format(new \DateTime($seminary['created'])))?></small></p>
|
||||||
<?php if(!array_key_exists('usercharacter', $seminary)) : ?>
|
<?php if(!array_key_exists('usercharacter', $seminary)) : ?>
|
||||||
<a href="<?=$linker->link(array('characters','register',$seminary['url']))?>" class="cta orange"><?=_('Create a Character')?></a>
|
<?php if(count($seminary['charactertypes']) > 0) : ?>
|
||||||
|
<a class="cta orange" href="<?=$linker->link(array('characters','register',$seminary['url']))?>"><?=_('Create a Character')?></a>
|
||||||
|
<?php elseif(count(array_intersect(array('admin', 'moderator'), \hhu\z\controllers\IntermediateController::$user['roles'])) > 0) : ?>
|
||||||
|
<a class="cta orange" href="<?=$linker->link(array('charactertypes','manage',$seminary['url']))?>"><?=_('Manage Charactertypes')?></a>
|
||||||
|
<?php endif ?>
|
||||||
<?php elseif(count($seminary['usercharacter']['characterroles']) == 0) : ?>
|
<?php elseif(count($seminary['usercharacter']['characterroles']) == 0) : ?>
|
||||||
<p><?=sprintf(_('Your Character “%s” has not been activated yet'), $seminary['usercharacter']['name'])?></p>
|
<p><?=sprintf(_('Your Character “%s” has not been activated yet'), $seminary['usercharacter']['name'])?></p>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
|
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
</li>
|
</li>
|
||||||
<?php endforeach ?>
|
<?php endforeach ?>
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,18 @@
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<h1><?=$seminary['title']?></h1>
|
<h1><?=$seminary['title']?></h1>
|
||||||
<?php if(count(array_intersect(array('admin', 'moderator'), \hhu\z\controllers\SeminaryController::$character['characterroles'])) > 0) : ?>
|
<?php if(count(array_intersect(array('admin', 'moderator'), \hhu\z\controllers\SeminaryController::$character['characterroles'])) > 0) : ?>
|
||||||
|
<?php if(in_array('admin', \hhu\z\controllers\SeminaryController::$character['characterroles'])) : ?>
|
||||||
<nav class="admin">
|
<nav class="admin">
|
||||||
<?php if(in_array('admin', \hhu\z\controllers\SeminaryController::$character['characterroles'])) : ?><li><a href="<?=$linker->link('edit', 3)?>"><?=_('Edit seminary')?></a></li><?php endif ?>
|
<li><a href="<?=$linker->link('edit', 3)?>"><?=_('Edit seminary')?></a></li>
|
||||||
<?php if(in_array('admin', \hhu\z\controllers\SeminaryController::$character['characterroles'])) : ?><li><a href="<?=$linker->link('delete', 3)?>"><?=_('Delete seminary')?></a></li><?php endif ?>
|
<li><a href="<?=$linker->link('delete', 3)?>"><?=_('Delete seminary')?></a></li>
|
||||||
<?php if(count(array_intersect(array('admin','moderator'), \hhu\z\controllers\SeminaryController::$character['characterroles'])) > 0) : ?><li><a href="<?=$linker->link(array('quests','index',$seminary['url']))?>"><?=_('Show Quests')?></a></li><?php endif ?>
|
</nav>
|
||||||
<?php if(count(array_intersect(array('admin','moderator'), \hhu\z\controllers\SeminaryController::$character['characterroles'])) > 0) : ?><li><a href="<?=$linker->link(array('calculatexps',$seminary['url']),1)?>"><?=_('Recalculate XPs')?></a></li><?php endif ?>
|
<nav class="admin">
|
||||||
|
<li><a href="<?=$linker->link(array('charactertypes','manage',$seminary['url']))?>"><?=_('Manage Charactertypes')?></a></li>
|
||||||
|
</nav>
|
||||||
|
<?php endif ?>
|
||||||
|
<nav class="admin">
|
||||||
|
<li><a href="<?=$linker->link(array('quests','index',$seminary['url']))?>"><?=_('Show Quests')?></a></li>
|
||||||
|
<li><a href="<?=$linker->link(array('calculatexps',$seminary['url']),1)?>"><?=_('Recalculate XPs')?></a></li>
|
||||||
</nav>
|
</nav>
|
||||||
<?php endif ?>
|
<?php endif ?>
|
||||||
<p><?=\hhu\z\Utils::t($seminary['description'])?></p>
|
<p><?=\hhu\z\Utils::t($seminary['description'])?></p>
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue