rework entities
This commit is contained in:
parent
d128fa4c57
commit
ac248697ff
11 changed files with 110 additions and 158 deletions
|
@ -1,54 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
|
||||||
*/
|
|
||||||
final class Version20240212201659 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this up() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, started_by VARCHAR(30) NOT NULL, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('CREATE TABLE menu_item (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, vendor_id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, price INTEGER NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_D754D550F603EE73 FOREIGN KEY (vendor_id) REFERENCES vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_D754D550F603EE73 ON menu_item (vendor_id)');
|
|
||||||
$this->addSql('CREATE TABLE menu_item_alias (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, menu_item_id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id), CONSTRAINT FK_EA66C4969AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_EA66C4969AB44FE0 ON menu_item_alias (menu_item_id)');
|
|
||||||
$this->addSql('CREATE TABLE order_item (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, food_order_id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, menu_item_id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, PRIMARY KEY(id), CONSTRAINT FK_52EA1F09A5D24A7A FOREIGN KEY (food_order_id) REFERENCES food_order (id) NOT DEFERRABLE INITIALLY IMMEDIATE, CONSTRAINT FK_52EA1F099AB44FE0 FOREIGN KEY (menu_item_id) REFERENCES menu_item (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('CREATE INDEX IDX_52EA1F09A5D24A7A ON order_item (food_order_id)');
|
|
||||||
$this->addSql('CREATE UNIQUE INDEX UNIQ_52EA1F099AB44FE0 ON order_item (menu_item_id)');
|
|
||||||
$this->addSql('CREATE TABLE vendor (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, name VARCHAR(50) NOT NULL, PRIMARY KEY(id))');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('DROP TABLE food_order');
|
|
||||||
$this->addSql('DROP TABLE menu_item');
|
|
||||||
$this->addSql('DROP TABLE menu_item_alias');
|
|
||||||
$this->addSql('DROP TABLE order_item');
|
|
||||||
$this->addSql('DROP TABLE vendor');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
<?php
|
|
||||||
|
|
||||||
declare(strict_types=1);
|
|
||||||
|
|
||||||
namespace DoctrineMigrations;
|
|
||||||
|
|
||||||
use Doctrine\DBAL\Schema\Schema;
|
|
||||||
use Doctrine\Migrations\AbstractMigration;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Auto-generated Migration: Please modify to your needs!
|
|
||||||
*/
|
|
||||||
final class Version20240212202919 extends AbstractMigration
|
|
||||||
{
|
|
||||||
public function getDescription(): string
|
|
||||||
{
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
|
|
||||||
public function up(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this up() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, closed_at, started_by, started_at FROM food_order');
|
|
||||||
$this->addSql('DROP TABLE food_order');
|
|
||||||
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, vendor_id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, started_by VARCHAR(30) NOT NULL, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, PRIMARY KEY(id), CONSTRAINT FK_4485672F603EE73 FOREIGN KEY (vendor_id) REFERENCES vendor (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
|
|
||||||
$this->addSql('INSERT INTO food_order (id, closed_at, started_by, started_at) SELECT id, closed_at, started_by, started_at FROM __temp__food_order');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_order');
|
|
||||||
$this->addSql('CREATE INDEX IDX_4485672F603EE73 ON food_order (vendor_id)');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function down(Schema $schema): void
|
|
||||||
{
|
|
||||||
// this down() migration is auto-generated, please modify it to your needs
|
|
||||||
$this->addSql('CREATE TEMPORARY TABLE __temp__food_order AS SELECT id, closed_at, started_by, started_at FROM food_order');
|
|
||||||
$this->addSql('DROP TABLE food_order');
|
|
||||||
$this->addSql('CREATE TABLE food_order (id BLOB NOT NULL --(DC2Type:ulid)
|
|
||||||
, closed_at DATETIME DEFAULT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, started_by VARCHAR(30) NOT NULL, started_at DATETIME NOT NULL --(DC2Type:datetime_immutable)
|
|
||||||
, PRIMARY KEY(id))');
|
|
||||||
$this->addSql('INSERT INTO food_order (id, closed_at, started_by, started_at) SELECT id, closed_at, started_by, started_at FROM __temp__food_order');
|
|
||||||
$this->addSql('DROP TABLE __temp__food_order');
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,6 +5,7 @@ namespace App\Controller;
|
||||||
use App\Entity\FoodOrder;
|
use App\Entity\FoodOrder;
|
||||||
use App\Entity\MenuItem;
|
use App\Entity\MenuItem;
|
||||||
use App\Entity\OrderItem;
|
use App\Entity\OrderItem;
|
||||||
|
use App\Form\OrderItemType;
|
||||||
use Doctrine\ORM\EntityManagerInterface;
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
use Symfony\Component\HttpFoundation\Request;
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
@ -51,7 +52,7 @@ class FoodOrderController extends AbstractController
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route(
|
#[Route(
|
||||||
'/{foodOrder}/add',
|
'/{foodOrder}/add/{menuItem}',
|
||||||
name: self::APP_FOODORDER_ADD_ITEM,
|
name: self::APP_FOODORDER_ADD_ITEM,
|
||||||
methods: [Request::METHOD_GET, Request::METHOD_POST],
|
methods: [Request::METHOD_GET, Request::METHOD_POST],
|
||||||
)]
|
)]
|
||||||
|
@ -59,8 +60,33 @@ class FoodOrderController extends AbstractController
|
||||||
FoodOrder $foodOrder,
|
FoodOrder $foodOrder,
|
||||||
MenuItem $menuItem,
|
MenuItem $menuItem,
|
||||||
EntityManagerInterface $entityManager,
|
EntityManagerInterface $entityManager,
|
||||||
|
Request $request,
|
||||||
): Response {
|
): Response {
|
||||||
return new Response('lol');
|
$orderItem = new OrderItem();
|
||||||
|
$orderItem->setFoodOrder($foodOrder);
|
||||||
|
$orderItem->setMenuItem($menuItem);
|
||||||
|
|
||||||
|
$form = $this->createForm(OrderItemType::class, $orderItem);
|
||||||
|
$form->handleRequest($request);
|
||||||
|
if ($form->isSubmitted() && $form->isValid()) {
|
||||||
|
$entityManager->persist($orderItem);
|
||||||
|
$entityManager->flush();
|
||||||
|
return $this->redirectToRoute(
|
||||||
|
FoodOrderController::APP_FOOD_ORDER_SHOW,
|
||||||
|
[
|
||||||
|
'id' => $foodOrder->getId(),
|
||||||
|
],
|
||||||
|
Response::HTTP_SEE_OTHER,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->render(
|
||||||
|
'food_order/orderitem.html.twig',
|
||||||
|
[
|
||||||
|
'form' => $form,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[Route(
|
#[Route(
|
||||||
|
@ -78,7 +104,7 @@ class FoodOrderController extends AbstractController
|
||||||
return $this->redirectToRoute(
|
return $this->redirectToRoute(
|
||||||
self::APP_FOOD_ORDER_SHOW,
|
self::APP_FOOD_ORDER_SHOW,
|
||||||
[
|
[
|
||||||
'id' => $foodOrder->id,
|
'id' => $foodOrder->getId(),
|
||||||
],
|
],
|
||||||
Response::HTTP_SEE_OTHER,
|
Response::HTTP_SEE_OTHER,
|
||||||
);
|
);
|
||||||
|
|
|
@ -16,27 +16,58 @@ final class AppFixture extends Fixture
|
||||||
{
|
{
|
||||||
$this->faker = \Faker\Factory::create();
|
$this->faker = \Faker\Factory::create();
|
||||||
foreach (range(0, 20) as $vendorCount) {
|
foreach (range(0, 20) as $vendorCount) {
|
||||||
$vendor = new Vendor();
|
$this->createVendorAndMenuItems($manager);
|
||||||
$vendor->setName($this->faker->name);
|
|
||||||
$manager->persist($vendor);
|
|
||||||
|
|
||||||
foreach (range(0, 10) as $itemCount) {
|
|
||||||
$menuItem = new MenuItem();
|
|
||||||
$menuItem->setVendor($vendor);
|
|
||||||
$menuItem->setPrice(random_int(500, 2000));
|
|
||||||
$manager->persist($menuItem);
|
|
||||||
$menuItemAliasOne = new MenuItemAlias();
|
|
||||||
$menuItemAliasOne->setName($this->faker->word);
|
|
||||||
$menuItem->addMenuItemAlias($menuItemAliasOne);
|
|
||||||
$manager->persist($menuItemAliasOne);
|
|
||||||
$menuItemAliasTwo = new MenuItemAlias();
|
|
||||||
$menuItemAliasTwo->setName($this->faker->word);
|
|
||||||
$menuItem->addMenuItemAlias($menuItemAliasTwo);
|
|
||||||
$manager->persist($menuItemAliasTwo);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$manager->flush();
|
$manager->flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param MenuItem $menuItem
|
||||||
|
* @param ObjectManager $manager
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function addMenuItemAliases(MenuItem $menuItem, ObjectManager $manager): void
|
||||||
|
{
|
||||||
|
$menuItemAliasOne = new MenuItemAlias();
|
||||||
|
$menuItemAliasOne->setName($this->faker->word);
|
||||||
|
$menuItem->addMenuItemAlias($menuItemAliasOne);
|
||||||
|
$manager->persist($menuItemAliasOne);
|
||||||
|
$menuItemAliasTwo = new MenuItemAlias();
|
||||||
|
$menuItemAliasTwo->setName($this->faker->word);
|
||||||
|
$menuItem->addMenuItemAlias($menuItemAliasTwo);
|
||||||
|
$manager->persist($menuItemAliasTwo);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param Vendor $vendor
|
||||||
|
* @param ObjectManager $manager
|
||||||
|
* @return void
|
||||||
|
* @throws \Random\RandomException
|
||||||
|
*/
|
||||||
|
public function createMenuItem(Vendor $vendor, ObjectManager $manager): void
|
||||||
|
{
|
||||||
|
$menuItem = new MenuItem();
|
||||||
|
$menuItem->setVendor($vendor);
|
||||||
|
$menuItem->setPrice(random_int(500, 2000));
|
||||||
|
$manager->persist($menuItem);
|
||||||
|
$this->addMenuItemAliases($menuItem, $manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param ObjectManager $manager
|
||||||
|
* @return void
|
||||||
|
* @throws \Random\RandomException
|
||||||
|
*/
|
||||||
|
public function createVendorAndMenuItems(ObjectManager $manager): void
|
||||||
|
{
|
||||||
|
$vendor = new Vendor();
|
||||||
|
$vendor->setName($this->faker->name);
|
||||||
|
$manager->persist($vendor);
|
||||||
|
|
||||||
|
foreach (range(0, 10) as $itemCount) {
|
||||||
|
$this->createMenuItem($vendor, $manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -33,10 +33,14 @@ class MenuItem
|
||||||
)]
|
)]
|
||||||
private Collection $menuItemAliases;
|
private Collection $menuItemAliases;
|
||||||
|
|
||||||
|
#[ORM\OneToMany(mappedBy: 'menuItem', targetEntity: ItemExtra::class, orphanRemoval: true)]
|
||||||
|
private Collection $itemExtras;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->id = new Ulid;
|
$this->id = new Ulid;
|
||||||
$this->menuItemAliases = new ArrayCollection;
|
$this->menuItemAliases = new ArrayCollection;
|
||||||
|
$this->itemExtras = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): Ulid
|
public function getId(): Ulid
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
namespace App\Entity;
|
namespace App\Entity;
|
||||||
|
|
||||||
use App\Repository\OrderItemRepository;
|
use App\Repository\OrderItemRepository;
|
||||||
|
use Doctrine\Common\Collections\ArrayCollection;
|
||||||
|
use Doctrine\Common\Collections\Collection;
|
||||||
use Doctrine\ORM\Mapping as ORM;
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
|
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
|
||||||
use Symfony\Bridge\Doctrine\Types\UlidType;
|
use Symfony\Bridge\Doctrine\Types\UlidType;
|
||||||
|
@ -21,13 +23,17 @@ class OrderItem
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private FoodOrder|null $foodOrder = null;
|
private FoodOrder|null $foodOrder = null;
|
||||||
|
|
||||||
#[ORM\OneToOne(cascade: ['persist', 'remove'])]
|
#[ORM\ManyToOne]
|
||||||
#[ORM\JoinColumn(nullable: false)]
|
#[ORM\JoinColumn(nullable: false)]
|
||||||
private MenuItem|null $menuItem = null;
|
private ?MenuItem $menuItem = null;
|
||||||
|
|
||||||
|
#[ORM\OneToMany(mappedBy: 'orderItem', targetEntity: ItemExtra::class)]
|
||||||
|
private Collection $extras;
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->id = new Ulid;
|
$this->id = new Ulid;
|
||||||
|
$this->extras = new ArrayCollection();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getId(): Ulid
|
public function getId(): Ulid
|
||||||
|
@ -46,14 +52,16 @@ class OrderItem
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMenuItem(): MenuItem|null
|
public function getMenuItem(): ?MenuItem
|
||||||
{
|
{
|
||||||
return $this->menuItem;
|
return $this->menuItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function setMenuItem(MenuItem $menuItem): static
|
public function setMenuItem(?MenuItem $menuItem): static
|
||||||
{
|
{
|
||||||
$this->menuItem = $menuItem;
|
$this->menuItem = $menuItem;
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,16 +14,6 @@ class OrderItemType extends AbstractType
|
||||||
{
|
{
|
||||||
public function buildForm(FormBuilderInterface $builder, array $options): void
|
public function buildForm(FormBuilderInterface $builder, array $options): void
|
||||||
{
|
{
|
||||||
$builder
|
|
||||||
->add('foodOrder', EntityType::class, [
|
|
||||||
'class' => FoodOrder::class,
|
|
||||||
'choice_label' => 'id',
|
|
||||||
])
|
|
||||||
->add('menuItem', EntityType::class, [
|
|
||||||
'class' => MenuItem::class,
|
|
||||||
'choice_label' => 'id',
|
|
||||||
])
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function configureOptions(OptionsResolver $resolver): void
|
public function configureOptions(OptionsResolver $resolver): void
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
Henlo {{ username }} (<a href="{{ url('app_name') }}">change name</a>) |
|
Henlo {{ username }} (<a href="{{ url('app_name') }}">change name</a>) |
|
||||||
<a href="{{ url('app_index') }}">index</a>
|
<a href="{{ url('app_index') }}">index</a>
|
||||||
</p>
|
</p>
|
||||||
|
<hr />
|
||||||
</header>
|
</header>
|
||||||
<main>
|
<main>
|
||||||
{% block body %}{% endblock %}
|
{% block body %}{% endblock %}
|
||||||
|
|
6
templates/food_order/orderitem.html.twig
Normal file
6
templates/food_order/orderitem.html.twig
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
{% extends 'base.html.twig' %}
|
||||||
|
|
||||||
|
{% block body %}
|
||||||
|
{{ include('_form.html.twig') }}
|
||||||
|
{% endblock %}
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
|
|
||||||
{{ lel.item.menuItem.aliases|map(i => i.name)|join(' / ') }}
|
{{ lel.item.menuItem.menuItemAliases|map(i => i.name)|join(' / ') }}
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{{ lel.item.menuItem.price|cents_to_eur }}
|
{{ lel.item.menuItem.price|cents_to_eur }}
|
||||||
|
@ -58,7 +58,6 @@
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</tbody>
|
</tbody>
|
||||||
</tbody>
|
|
||||||
</table>
|
</table>
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead>
|
<thead>
|
||||||
|
@ -79,29 +78,17 @@
|
||||||
<td>
|
<td>
|
||||||
{% if food_order.closedAt is null %}
|
{% if food_order.closedAt is null %}
|
||||||
<a
|
<a
|
||||||
href="#"
|
href="{{ path(
|
||||||
data-menuitem-id="{{ item.id }}"
|
'app_foodorder_add_item',
|
||||||
|
{
|
||||||
|
foodOrder: food_order.id,
|
||||||
|
menuItem: item.id
|
||||||
|
}
|
||||||
|
) }}"
|
||||||
>add</a>
|
>add</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</table>
|
</table>
|
||||||
<script>
|
|
||||||
document.querySelectorAll('a[data-menuitem-id]').forEach((link) => {
|
|
||||||
link.addEventListener('click', (event) => {
|
|
||||||
// Prevent the default action of the link
|
|
||||||
event.preventDefault();
|
|
||||||
|
|
||||||
// Get the `data-menuitem-id` attribute of the clicked link
|
|
||||||
let menuItemId = link.getAttribute('data-menuitem-id');
|
|
||||||
|
|
||||||
// Select the corresponding dialog with the same `data-menuitem-id`. Assuming each dialog's id is the same as `data-menuitem-id`, please update the code to use proper id or class as needed.
|
|
||||||
let dialog = document.querySelector(`dialog[data-menuitem-id="${menuItemId}"]` );
|
|
||||||
|
|
||||||
// Open the dialog
|
|
||||||
dialog.showModal();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
<tbody>
|
<tbody>
|
||||||
{% for order in orders %}
|
{% for order in orders %}
|
||||||
<tr>
|
<tr>
|
||||||
<td>{{ order.startedByName }}</td>
|
<td>{{ order.startedBy }}</td>
|
||||||
<td>{{ order.vendor.name }}</td>
|
<td>{{ order.vendor.name }}</td>
|
||||||
<td>{{ order.startedAt|date("Y-m-d H:i") }}</td>
|
<td>{{ order.startedAt|date("Y-m-d H:i") }}</td>
|
||||||
<td><a href="{{ path('app_food_order_show', {'id': order.id}) }}">show</a></td>
|
<td><a href="{{ path('app_food_order_show', {'id': order.id}) }}">show</a></td>
|
||||||
|
|
Loading…
Reference in a new issue