mirror of
https://github.com/kevachat/webapp.git
synced 2025-01-24 05:24:19 +00:00
implement new room submit feature
This commit is contained in:
parent
df68a3aa91
commit
7c51f3d57a
21
.env
21
.env
@ -19,7 +19,7 @@ APP_ENV=dev
|
|||||||
APP_SECRET=EDIT_ME
|
APP_SECRET=EDIT_ME
|
||||||
###< symfony/framework-bundle ###
|
###< symfony/framework-bundle ###
|
||||||
|
|
||||||
APP_VERSION=1.3.1
|
APP_VERSION=1.4.0
|
||||||
|
|
||||||
APP_NAME=KevaChat
|
APP_NAME=KevaChat
|
||||||
|
|
||||||
@ -61,23 +61,32 @@ APP_KEVACOIN_ROOM_NAMESPACE_DEFAULT=EDIT_ME
|
|||||||
# Online session expiration timeout
|
# Online session expiration timeout
|
||||||
APP_SESSION_ONLINE_TIMEOUT=900
|
APP_SESSION_ONLINE_TIMEOUT=900
|
||||||
|
|
||||||
|
# Moderators IP with extra permissions, separated with |
|
||||||
|
APP_MODERATOR_REMOTE_IP=
|
||||||
|
|
||||||
# Allow remotes to create new rooms (namespaces)
|
# Allow remotes to create new rooms (namespaces)
|
||||||
APP_ADD_ROOM_REMOTE_IP_REGEX=/.*/
|
APP_ADD_ROOM_REMOTE_IP_REGEX=/.*/
|
||||||
|
|
||||||
|
# Time quota delay for new room submit ability per IP (seconds)
|
||||||
|
APP_ADD_ROOM_REMOTE_IP_DELAY=86400
|
||||||
|
|
||||||
|
# Skip access limits for banned IPs separated by |
|
||||||
|
APP_ADD_ROOM_REMOTE_IP_DENIED=
|
||||||
|
|
||||||
|
# Room name rules (for kevacoin _KEVA_NS_, max length 520)
|
||||||
|
APP_ADD_ROOM_KEVA_NS_VALUE_REGEX=/^[\w\s_-]{2,140}$/ui
|
||||||
|
|
||||||
# Allow remotes to create new posts (submit key/values)
|
# Allow remotes to create new posts (submit key/values)
|
||||||
APP_ADD_POST_REMOTE_IP_REGEX=/.*/
|
APP_ADD_POST_REMOTE_IP_REGEX=/.*/
|
||||||
|
|
||||||
# Time quota for remote publications by IP (seconds)
|
# Time quota delay for post publications per IP (seconds)
|
||||||
APP_ADD_POST_REMOTE_IP_DELAY=60
|
APP_ADD_POST_REMOTE_IP_DELAY=60
|
||||||
|
|
||||||
# Skip access limits for following IPs separated by |
|
|
||||||
APP_ADD_POST_REMOTE_IP_MODERATORS=
|
|
||||||
|
|
||||||
# Skip access limits for banned IPs separated by |
|
# Skip access limits for banned IPs separated by |
|
||||||
APP_ADD_POST_REMOTE_IP_DENIED=
|
APP_ADD_POST_REMOTE_IP_DENIED=
|
||||||
|
|
||||||
# Post ID rules (for kevacoin key) do not change to keep external KevaChat nodes compatibility
|
# Post ID rules (for kevacoin key) do not change to keep external KevaChat nodes compatibility
|
||||||
APP_ADD_POST_KEY_REGEX=/^([\d]+)@([A-z0-9\.\:\[\]]+)$/
|
APP_ADD_POST_KEY_REGEX=/^([\d]+)@([A-z0-9\.\:\[\]]+)$/
|
||||||
|
|
||||||
# Post content rules (for kevacoin value)
|
# Post content rules (for kevacoin value, max length 3072)
|
||||||
APP_ADD_POST_VALUE_REGEX=/^[\w\s\:\.\,\'\"\/\!\?\@\#\%\(\)\[\]\+\-\*\$\%]{2,3072}$/ui
|
APP_ADD_POST_VALUE_REGEX=/^[\w\s\:\.\,\'\"\/\!\?\@\#\%\(\)\[\]\+\-\*\$\%]{2,3072}$/ui
|
12
composer.lock
generated
12
composer.lock
generated
@ -132,16 +132,16 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "kevachat/kevacoin",
|
"name": "kevachat/kevacoin",
|
||||||
"version": "1.4.2",
|
"version": "1.5.0",
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/kevachat/kevacoin-php.git",
|
"url": "https://github.com/kevachat/kevacoin-php.git",
|
||||||
"reference": "b6e5416c58d379fd197bbd6d1039a30042ea0481"
|
"reference": "44608e688f69ff1545f2a3103c4504bfb3294831"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/kevachat/kevacoin-php/zipball/b6e5416c58d379fd197bbd6d1039a30042ea0481",
|
"url": "https://api.github.com/repos/kevachat/kevacoin-php/zipball/44608e688f69ff1545f2a3103c4504bfb3294831",
|
||||||
"reference": "b6e5416c58d379fd197bbd6d1039a30042ea0481",
|
"reference": "44608e688f69ff1545f2a3103c4504bfb3294831",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"type": "library",
|
"type": "library",
|
||||||
@ -156,9 +156,9 @@
|
|||||||
],
|
],
|
||||||
"support": {
|
"support": {
|
||||||
"issues": "https://github.com/kevachat/kevacoin-php/issues",
|
"issues": "https://github.com/kevachat/kevacoin-php/issues",
|
||||||
"source": "https://github.com/kevachat/kevacoin-php/tree/1.4.2"
|
"source": "https://github.com/kevachat/kevacoin-php/tree/1.5.0"
|
||||||
},
|
},
|
||||||
"time": "2023-12-06T09:20:08+00:00"
|
"time": "2023-12-09T18:55:04+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "league/commonmark",
|
"name": "league/commonmark",
|
||||||
|
@ -24,12 +24,15 @@ parameters:
|
|||||||
app.kevacoin.mine.solo.url: '%env(APP_KEVACOIN_MINE_SOLO_URL)%'
|
app.kevacoin.mine.solo.url: '%env(APP_KEVACOIN_MINE_SOLO_URL)%'
|
||||||
app.session.online.timeout: '%env(APP_SESSION_ONLINE_TIMEOUT)%'
|
app.session.online.timeout: '%env(APP_SESSION_ONLINE_TIMEOUT)%'
|
||||||
app.add.room.remote.ip.regex: '%env(APP_ADD_ROOM_REMOTE_IP_REGEX)%'
|
app.add.room.remote.ip.regex: '%env(APP_ADD_ROOM_REMOTE_IP_REGEX)%'
|
||||||
|
app.add.room.remote.ip.delay: '%env(APP_ADD_ROOM_REMOTE_IP_DELAY)%'
|
||||||
|
app.add.room.remote.ip.denied: '%env(APP_ADD_ROOM_REMOTE_IP_DENIED)%'
|
||||||
|
app.add.room.keva.ns.value.regex: '%env(APP_ADD_ROOM_KEVA_NS_VALUE_REGEX)%'
|
||||||
app.add.post.remote.ip.regex: '%env(APP_ADD_POST_REMOTE_IP_REGEX)%'
|
app.add.post.remote.ip.regex: '%env(APP_ADD_POST_REMOTE_IP_REGEX)%'
|
||||||
app.add.post.remote.ip.delay: '%env(APP_ADD_POST_REMOTE_IP_DELAY)%'
|
app.add.post.remote.ip.delay: '%env(APP_ADD_POST_REMOTE_IP_DELAY)%'
|
||||||
app.add.post.remote.ip.moderators: '%env(APP_ADD_POST_REMOTE_IP_MODERATORS)%'
|
|
||||||
app.add.post.remote.ip.denied: '%env(APP_ADD_POST_REMOTE_IP_DENIED)%'
|
app.add.post.remote.ip.denied: '%env(APP_ADD_POST_REMOTE_IP_DENIED)%'
|
||||||
app.add.post.key.regex: '%env(APP_ADD_POST_KEY_REGEX)%'
|
app.add.post.key.regex: '%env(APP_ADD_POST_KEY_REGEX)%'
|
||||||
app.add.post.value.regex: '%env(APP_ADD_POST_VALUE_REGEX)%'
|
app.add.post.value.regex: '%env(APP_ADD_POST_VALUE_REGEX)%'
|
||||||
|
app.moderator.remote.ip: '%env(APP_MODERATOR_REMOTE_IP)%'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
# default configuration for services in *this* file
|
# default configuration for services in *this* file
|
||||||
|
@ -155,6 +155,7 @@ footer > form
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
footer > form > input[type="text"],
|
||||||
footer > form > textarea
|
footer > form > textarea
|
||||||
{
|
{
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -99,18 +99,27 @@ class ModuleController extends AbstractController
|
|||||||
Request $request
|
Request $request
|
||||||
): Response
|
): Response
|
||||||
{
|
{
|
||||||
$client = new \Kevachat\Kevacoin\Client(
|
// Create rooms list
|
||||||
$this->getParameter('app.kevacoin.protocol'),
|
$list = [];
|
||||||
$this->getParameter('app.kevacoin.host'),
|
|
||||||
$this->getParameter('app.kevacoin.port'),
|
|
||||||
$this->getParameter('app.kevacoin.username'),
|
|
||||||
$this->getParameter('app.kevacoin.password')
|
|
||||||
);
|
|
||||||
|
|
||||||
|
foreach ((array) explode('|', $this->getParameter('app.kevacoin.room.namespaces.pinned')) as $room)
|
||||||
|
{
|
||||||
|
$list[] = $room;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append custom valid namespace to the rooms list menu
|
||||||
|
if (!in_array($request->get('namespace'), $list) && preg_match('/^[A-z0-9]{34}$/', $request->get('namespace')))
|
||||||
|
{
|
||||||
|
$list[] = $request->get('namespace');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the template
|
||||||
return $this->render(
|
return $this->render(
|
||||||
'default/module/rooms.html.twig',
|
'default/module/rooms.html.twig',
|
||||||
[
|
[
|
||||||
'list' => (array) explode('|', $this->getParameter('app.kevacoin.room.namespaces.pinned')),
|
'list' => array_unique(
|
||||||
|
$list
|
||||||
|
),
|
||||||
'form' =>
|
'form' =>
|
||||||
[
|
[
|
||||||
'namespace' =>
|
'namespace' =>
|
||||||
@ -178,4 +187,17 @@ class ModuleController extends AbstractController
|
|||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function room(
|
||||||
|
Request $request
|
||||||
|
): Response
|
||||||
|
{
|
||||||
|
return $this->render(
|
||||||
|
'default/module/room.html.twig',
|
||||||
|
[
|
||||||
|
'name' => $request->get('name'),
|
||||||
|
'error' => $request->get('error')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
@ -95,9 +95,9 @@ class RoomController extends AbstractController
|
|||||||
array_multisort(
|
array_multisort(
|
||||||
array_column(
|
array_column(
|
||||||
$list,
|
$list,
|
||||||
'name'
|
'total'
|
||||||
),
|
),
|
||||||
SORT_ASC,
|
SORT_DESC,
|
||||||
$list
|
$list
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -165,7 +165,7 @@ class RoomController extends AbstractController
|
|||||||
$feed = [];
|
$feed = [];
|
||||||
|
|
||||||
// Get pending paradise
|
// Get pending paradise
|
||||||
foreach ((array) $client->kevaPending() as $pending)
|
foreach ((array) $client->kevaPending() as $pending) // @TODO relate to this room
|
||||||
{
|
{
|
||||||
// Ignore pending posts from other rooms
|
// Ignore pending posts from other rooms
|
||||||
if ($pending['namespace'] !== $request->get('namespace'))
|
if ($pending['namespace'] !== $request->get('namespace'))
|
||||||
@ -347,7 +347,7 @@ class RoomController extends AbstractController
|
|||||||
$this->getParameter('app.kevacoin.password')
|
$this->getParameter('app.kevacoin.password')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Check namespace defined in config
|
// Check namespace available on this wallet
|
||||||
$rooms = [];
|
$rooms = [];
|
||||||
|
|
||||||
foreach ((array) $client->kevaListNamespaces() as $value)
|
foreach ((array) $client->kevaListNamespaces() as $value)
|
||||||
@ -373,7 +373,7 @@ class RoomController extends AbstractController
|
|||||||
// Ignore this rule for is moderators
|
// Ignore this rule for is moderators
|
||||||
!in_array(
|
!in_array(
|
||||||
$request->getClientIp(),
|
$request->getClientIp(),
|
||||||
(array) explode('|', $this->getParameter('app.add.post.remote.ip.moderators'))
|
(array) explode('|', $this->getParameter('app.moderator.remote.ip'))
|
||||||
) &&
|
) &&
|
||||||
|
|
||||||
// Check namespace writable or user is moderator
|
// Check namespace writable or user is moderator
|
||||||
@ -401,7 +401,10 @@ class RoomController extends AbstractController
|
|||||||
[
|
[
|
||||||
'namespace' => $request->get('namespace'),
|
'namespace' => $request->get('namespace'),
|
||||||
'message' => $request->get('message'),
|
'message' => $request->get('message'),
|
||||||
'error' => $translator->trans('Access denied for this IP!')
|
'error' => sprintf(
|
||||||
|
$translator->trans('Access denied for host %s!'),
|
||||||
|
$request->getClientIp()
|
||||||
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -414,7 +417,10 @@ class RoomController extends AbstractController
|
|||||||
[
|
[
|
||||||
'namespace' => $request->get('namespace'),
|
'namespace' => $request->get('namespace'),
|
||||||
'message' => $request->get('message'),
|
'message' => $request->get('message'),
|
||||||
'error' => $translator->trans('Access not allowed for this IP!')
|
'error' => sprintf(
|
||||||
|
$translator->trans('Access restricted for host %s!'),
|
||||||
|
$request->getClientIp()
|
||||||
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -445,7 +451,7 @@ class RoomController extends AbstractController
|
|||||||
'namespace' => $request->get('namespace'),
|
'namespace' => $request->get('namespace'),
|
||||||
'message' => $request->get('message'),
|
'message' => $request->get('message'),
|
||||||
'error' => sprintf(
|
'error' => sprintf(
|
||||||
$translator->trans('Please wait for %s seconds before post new message!'),
|
$translator->trans('Please wait %s seconds before post new message!'),
|
||||||
(int) $this->getParameter('app.add.post.remote.ip.delay') - (time() - $delay)
|
(int) $this->getParameter('app.add.post.remote.ip.delay') - (time() - $delay)
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
@ -462,7 +468,7 @@ class RoomController extends AbstractController
|
|||||||
'message' => $request->get('message'),
|
'message' => $request->get('message'),
|
||||||
'error' => sprintf(
|
'error' => sprintf(
|
||||||
$translator->trans('Insufficient funds, wallet: %s'),
|
$translator->trans('Insufficient funds, wallet: %s'),
|
||||||
$this->getParameter('app.kevacoin.mine.address')
|
$this->getParameter('app.kevacoin.boost.address')
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
@ -510,6 +516,187 @@ class RoomController extends AbstractController
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route(
|
||||||
|
'/room/add',
|
||||||
|
name: 'room_add',
|
||||||
|
methods:
|
||||||
|
[
|
||||||
|
'POST'
|
||||||
|
]
|
||||||
|
)]
|
||||||
|
public function add(
|
||||||
|
Request $request,
|
||||||
|
TranslatorInterface $translator
|
||||||
|
): Response
|
||||||
|
{
|
||||||
|
// Check maintenance mode disabled
|
||||||
|
if ($this->getParameter('app.maintenance'))
|
||||||
|
{
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_namespace',
|
||||||
|
[
|
||||||
|
'namespace' => $request->get('namespace'),
|
||||||
|
'message' => $request->get('message'),
|
||||||
|
'error' => $this->getParameter('app.maintenance')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Connect memcached
|
||||||
|
$memcached = new \Memcached();
|
||||||
|
$memcached->addServer(
|
||||||
|
$this->getParameter('app.memcached.host'),
|
||||||
|
$this->getParameter('app.memcached.port')
|
||||||
|
);
|
||||||
|
|
||||||
|
$memory = md5(
|
||||||
|
sprintf(
|
||||||
|
'%s.RoomController::add:add.room.remote.ip.delay:%s',
|
||||||
|
__DIR__,
|
||||||
|
$request->getClientIp(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
// Connect kevacoin
|
||||||
|
$client = new \Kevachat\Kevacoin\Client(
|
||||||
|
$this->getParameter('app.kevacoin.protocol'),
|
||||||
|
$this->getParameter('app.kevacoin.host'),
|
||||||
|
$this->getParameter('app.kevacoin.port'),
|
||||||
|
$this->getParameter('app.kevacoin.username'),
|
||||||
|
$this->getParameter('app.kevacoin.password')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Trim extra spaces from room name
|
||||||
|
$name = trim(
|
||||||
|
$request->get('name')
|
||||||
|
);
|
||||||
|
|
||||||
|
// Validate room name regex
|
||||||
|
if (!preg_match($this->getParameter('app.add.room.keva.ns.value.regex'), $name))
|
||||||
|
{
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => sprintf(
|
||||||
|
$translator->trans('Room name does not match node requirements: %s'),
|
||||||
|
$this->getParameter('app.add.room.keva.ns.value.regex')
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check room name not added before
|
||||||
|
$rooms = [];
|
||||||
|
|
||||||
|
foreach ((array) $client->kevaListNamespaces() as $value)
|
||||||
|
{
|
||||||
|
$rooms[$value['namespaceId']] = $value['displayName'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (in_array($name, $rooms))
|
||||||
|
{
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => $translator->trans('Room with same name already exists on this node!')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Deny requests from banned remote hosts
|
||||||
|
if (in_array($request->getClientIp(), (array) explode('|', $this->getParameter('app.add.room.remote.ip.denied'))))
|
||||||
|
{
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => sprintf(
|
||||||
|
$translator->trans('Access denied for host %s!'),
|
||||||
|
$request->getClientIp()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate remote IP regex
|
||||||
|
if (!preg_match($this->getParameter('app.add.room.remote.ip.regex'), $request->getClientIp()))
|
||||||
|
{
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => sprintf(
|
||||||
|
$translator->trans('Access restricted for host %s!'),
|
||||||
|
$request->getClientIp()
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate remote IP limits
|
||||||
|
if ($delay = (int) $memcached->get($memory))
|
||||||
|
{
|
||||||
|
// Error
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => sprintf(
|
||||||
|
$translator->trans('Please wait for %s seconds before add new room!'),
|
||||||
|
(int) $this->getParameter('app.add.room.remote.ip.delay') - (time() - $delay)
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Validate funds available yet
|
||||||
|
if (1 > $client->getBalance())
|
||||||
|
{
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => sprintf(
|
||||||
|
$translator->trans('Insufficient funds, wallet: %s'),
|
||||||
|
$this->getParameter('app.kevacoin.boost.address')
|
||||||
|
)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Send message to DHT
|
||||||
|
if ($namespace = $client->kevaNamespace($name))
|
||||||
|
{
|
||||||
|
// Register event time
|
||||||
|
$memcached->set(
|
||||||
|
$memory,
|
||||||
|
time(),
|
||||||
|
(int) $this->getParameter('app.add.room.remote.ip.delay') // auto remove on cache expire
|
||||||
|
);
|
||||||
|
|
||||||
|
// Redirect to new room
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_namespace',
|
||||||
|
[
|
||||||
|
'namespace' => $namespace['namespaceId'],
|
||||||
|
'error' => null,
|
||||||
|
'message' => null
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something went wrong, return error message
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
'room_list',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'error' => $translator->trans('Internal error! Please feedback')
|
||||||
|
]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
private function _post(array $data): ?object
|
private function _post(array $data): ?object
|
||||||
{
|
{
|
||||||
// Validate key format allowed in settings
|
// Validate key format allowed in settings
|
||||||
|
7
templates/default/module/room.html.twig
Normal file
7
templates/default/module/room.html.twig
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<form name="room" action="{{ path('room_add') }}" method="post">
|
||||||
|
{% if error %}
|
||||||
|
<output name="error" for="form-room-name">{{ error }}</output>
|
||||||
|
{% endif %}
|
||||||
|
<input type="text" name="name" id="form-room-name" value="{{ name }}" placeholder="{{ 'enter new room name...' | trans }}" />
|
||||||
|
<button type="submit">{{ 'add' | trans }}</button>
|
||||||
|
</form>
|
@ -1,4 +1,4 @@
|
|||||||
<form name="room" action="{{ path('room_index') }}" method="get">
|
<form name="rooms" action="{{ path('room_index') }}" method="get">
|
||||||
<input type="text" name="namespace" value="{{ form.namespace.value }}" placeholder="{{ 'join room by kevacoin namespace...' | trans }}" />
|
<input type="text" name="namespace" value="{{ form.namespace.value }}" placeholder="{{ 'join room by kevacoin namespace...' | trans }}" />
|
||||||
</form>
|
</form>
|
||||||
{% if list %}
|
{% if list %}
|
||||||
|
@ -43,4 +43,16 @@
|
|||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% endblock %}
|
||||||
|
{% block footer_content %}
|
||||||
|
{{
|
||||||
|
render(
|
||||||
|
controller(
|
||||||
|
'App\\Controller\\ModuleController::room',
|
||||||
|
{
|
||||||
|
request: request
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}}
|
||||||
{% endblock %}
|
{% endblock %}
|
Loading…
x
Reference in New Issue
Block a user