Merge pull request 'feature/views' (#8) from feature/views into main
Reviewed-on: #8feature/comunication-ogagent
commit
2e856947f2
|
@ -30,6 +30,7 @@
|
||||||
"symfony/runtime": "6.4.*",
|
"symfony/runtime": "6.4.*",
|
||||||
"symfony/security-bundle": "6.4.*",
|
"symfony/security-bundle": "6.4.*",
|
||||||
"symfony/serializer": "6.4.*",
|
"symfony/serializer": "6.4.*",
|
||||||
|
"symfony/translation": "6.4.*",
|
||||||
"symfony/twig-bundle": "6.4.*",
|
"symfony/twig-bundle": "6.4.*",
|
||||||
"symfony/validator": "6.4.*",
|
"symfony/validator": "6.4.*",
|
||||||
"symfony/yaml": "6.4.*"
|
"symfony/yaml": "6.4.*"
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "e953b0066fb773aaf6b3835086280c86",
|
"content-hash": "bf1165324e27bddd1a412f25e438fc4c",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "api-platform/core",
|
"name": "api-platform/core",
|
||||||
|
@ -6061,6 +6061,101 @@
|
||||||
],
|
],
|
||||||
"time": "2024-05-31T14:49:08+00:00"
|
"time": "2024-05-31T14:49:08+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/translation",
|
||||||
|
"version": "v6.4.8",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/translation.git",
|
||||||
|
"reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/translation/zipball/a002933b13989fc4bd0b58e04bf7eec5210e438a",
|
||||||
|
"reference": "a002933b13989fc4bd0b58e04bf7eec5210e438a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=8.1",
|
||||||
|
"symfony/deprecation-contracts": "^2.5|^3",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0",
|
||||||
|
"symfony/translation-contracts": "^2.5|^3.0"
|
||||||
|
},
|
||||||
|
"conflict": {
|
||||||
|
"symfony/config": "<5.4",
|
||||||
|
"symfony/console": "<5.4",
|
||||||
|
"symfony/dependency-injection": "<5.4",
|
||||||
|
"symfony/http-client-contracts": "<2.5",
|
||||||
|
"symfony/http-kernel": "<5.4",
|
||||||
|
"symfony/service-contracts": "<2.5",
|
||||||
|
"symfony/twig-bundle": "<5.4",
|
||||||
|
"symfony/yaml": "<5.4"
|
||||||
|
},
|
||||||
|
"provide": {
|
||||||
|
"symfony/translation-implementation": "2.3|3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"nikic/php-parser": "^4.18|^5.0",
|
||||||
|
"psr/log": "^1|^2|^3",
|
||||||
|
"symfony/config": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/console": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/dependency-injection": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/finder": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/http-client-contracts": "^2.5|^3.0",
|
||||||
|
"symfony/http-kernel": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/intl": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/polyfill-intl-icu": "^1.21",
|
||||||
|
"symfony/routing": "^5.4|^6.0|^7.0",
|
||||||
|
"symfony/service-contracts": "^2.5|^3",
|
||||||
|
"symfony/yaml": "^5.4|^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"Resources/functions.php"
|
||||||
|
],
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\Translation\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Provides tools to internationalize your application",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/translation/tree/v6.4.8"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-05-31T14:49:08+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/translation-contracts",
|
"name": "symfony/translation-contracts",
|
||||||
"version": "v3.5.0",
|
"version": "v3.5.0",
|
||||||
|
|
|
@ -0,0 +1,30 @@
|
||||||
|
resources:
|
||||||
|
App\Entity\View:
|
||||||
|
processor: App\State\Processor\ViewProcessor
|
||||||
|
input: App\Dto\Input\ViewInput
|
||||||
|
output: App\Dto\Output\ViewOutput
|
||||||
|
normalizationContext:
|
||||||
|
groups: ['default', 'view:read']
|
||||||
|
denormalizationContext:
|
||||||
|
groups: ['view:write']
|
||||||
|
operations:
|
||||||
|
ApiPlatform\Metadata\GetCollection:
|
||||||
|
provider: App\State\Provider\ViewProvider
|
||||||
|
filters:
|
||||||
|
- 'api_platform.filter.view.order'
|
||||||
|
- 'api_platform.filter.view.search'
|
||||||
|
ApiPlatform\Metadata\Get:
|
||||||
|
provider: App\State\Provider\ViewProvider
|
||||||
|
ApiPlatform\Metadata\Put:
|
||||||
|
provider: App\State\Provider\ViewProvider
|
||||||
|
ApiPlatform\Metadata\Patch:
|
||||||
|
provider: App\State\Provider\ViewProvider
|
||||||
|
ApiPlatform\Metadata\Post: ~
|
||||||
|
ApiPlatform\Metadata\Delete: ~
|
||||||
|
|
||||||
|
properties:
|
||||||
|
App\Entity\View:
|
||||||
|
id:
|
||||||
|
identifier: false
|
||||||
|
uuid:
|
||||||
|
identifier: true
|
|
@ -1,6 +1,6 @@
|
||||||
api_platform:
|
api_platform:
|
||||||
title: 'OgCore API'
|
title: 'OgCore Api'
|
||||||
description: 'API Documentation for OgCore'
|
description: 'Api Documentation for OgCore'
|
||||||
version: 1.0.0
|
version: 1.0.0
|
||||||
path_segment_name_generator: 'api_platform.path_segment_name_generator.dash'
|
path_segment_name_generator: 'api_platform.path_segment_name_generator.dash'
|
||||||
formats:
|
formats:
|
||||||
|
|
|
@ -11,7 +11,7 @@ security:
|
||||||
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
pattern: ^/(_(profiler|wdt)|css|images|js)/
|
||||||
security: false
|
security: false
|
||||||
main:
|
main:
|
||||||
stateless: true
|
stateless: false
|
||||||
provider: app_user_provider
|
provider: app_user_provider
|
||||||
entry_point: jwt
|
entry_point: jwt
|
||||||
json_login:
|
json_login:
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
framework:
|
||||||
|
default_locale: es
|
||||||
|
translator:
|
||||||
|
default_path: '%kernel.project_dir%/translations'
|
||||||
|
fallbacks:
|
||||||
|
- en
|
||||||
|
- es
|
||||||
|
providers:
|
|
@ -21,6 +21,12 @@ services:
|
||||||
- { name: api_platform.doctrine.orm.query_extension.collection }
|
- { name: api_platform.doctrine.orm.query_extension.collection }
|
||||||
- { name: api_platform.doctrine.orm.query_extension.item }
|
- { name: api_platform.doctrine.orm.query_extension.item }
|
||||||
|
|
||||||
|
App\EventListener\LocaleSubscriber:
|
||||||
|
arguments:
|
||||||
|
$defaultLocale: '%kernel.default_locale%'
|
||||||
|
tags:
|
||||||
|
- { name: kernel.event_subscriber }
|
||||||
|
|
||||||
App\OpenApi\OpenApiFactory:
|
App\OpenApi\OpenApiFactory:
|
||||||
decorates: 'api_platform.openapi.factory'
|
decorates: 'api_platform.openapi.factory'
|
||||||
arguments: [ '@App\OpenApi\OpenApiFactory.inner' ]
|
arguments: [ '@App\OpenApi\OpenApiFactory.inner' ]
|
||||||
|
@ -90,3 +96,8 @@ services:
|
||||||
bind:
|
bind:
|
||||||
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
||||||
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
||||||
|
|
||||||
|
App\State\Provider\ViewProvider:
|
||||||
|
bind:
|
||||||
|
$collectionProvider: '@api_platform.doctrine.orm.state.collection_provider'
|
||||||
|
$itemProvider: '@api_platform.doctrine.orm.state.item_provider'
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?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 Version20240717094811 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 view (id INT AUTO_INCREMENT NOT NULL, uuid CHAR(36) NOT NULL COMMENT \'(DC2Type:uuid)\', migration_id VARCHAR(255) DEFAULT NULL, created_at DATETIME NOT NULL, updated_at DATETIME NOT NULL, created_by VARCHAR(255) DEFAULT NULL, updated_by VARCHAR(255) DEFAULT NULL, favourite TINYINT(1) NOT NULL, filters JSON DEFAULT NULL COMMENT \'(DC2Type:json)\', name VARCHAR(255) NOT NULL, UNIQUE INDEX UNIQ_FEFDAB8ED17F50A6 (uuid), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE `utf8mb4_unicode_ci` ENGINE = InnoDB');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('DROP TABLE view');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?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 Version20240718064611 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('ALTER TABLE client ADD position JSON DEFAULT NULL COMMENT \'(DC2Type:json)\'');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE client DROP position');
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
<?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 Version20240801130155 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('ALTER TABLE view ADD user_id INT DEFAULT NULL');
|
||||||
|
$this->addSql('ALTER TABLE view ADD CONSTRAINT FK_FEFDAB8EA76ED395 FOREIGN KEY (user_id) REFERENCES user (id)');
|
||||||
|
$this->addSql('CREATE INDEX IDX_FEFDAB8EA76ED395 ON view (user_id)');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(Schema $schema): void
|
||||||
|
{
|
||||||
|
// this down() migration is auto-generated, please modify it to your needs
|
||||||
|
$this->addSql('ALTER TABLE view DROP FOREIGN KEY FK_FEFDAB8EA76ED395');
|
||||||
|
$this->addSql('DROP INDEX IDX_FEFDAB8EA76ED395 ON view');
|
||||||
|
$this->addSql('ALTER TABLE view DROP user_id');
|
||||||
|
}
|
||||||
|
}
|
|
@ -62,6 +62,7 @@ class MigrateClientsCommand extends Command
|
||||||
$clientEntity->setNetdriver($client['netdriver']);
|
$clientEntity->setNetdriver($client['netdriver']);
|
||||||
$clientEntity->setMac($client['mac']);
|
$clientEntity->setMac($client['mac']);
|
||||||
$clientEntity->setIp($client['ip']);
|
$clientEntity->setIp($client['ip']);
|
||||||
|
$clientEntity->setPosition(['x' => 0, 'y' => 0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$migrationId = $client['ordenadores.grupoid'] === 0 ? $client['ordenadores.idaula'] : $client['ordenadores.grupoid'];
|
$migrationId = $client['ordenadores.grupoid'] === 0 ? $client['ordenadores.idaula'] : $client['ordenadores.grupoid'];
|
||||||
|
|
|
@ -14,7 +14,7 @@ use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
#[AsCommand(name: 'opengnsys:migrate-hardware-profile', description: 'Migrate hardware and hardware profile data')]
|
#[AsCommand(name: 'opengnsys:migration:hardware-profile', description: 'Migrate hardware and hardware profile data')]
|
||||||
class MigrateHardwareAndHardwareProfileCommand extends Command
|
class MigrateHardwareAndHardwareProfileCommand extends Command
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Command\Migration;
|
||||||
|
|
||||||
|
use App\Entity\Client;
|
||||||
|
use App\Entity\HardwareProfile;
|
||||||
|
use App\Entity\OperativeSystem;
|
||||||
|
use App\Entity\OrganizationalUnit;
|
||||||
|
use App\Entity\Partition;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Doctrine\ORM\Query\ResultSetMapping;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
use Symfony\Component\Console\Attribute\AsCommand;
|
||||||
|
use Symfony\Component\Console\Command\Command;
|
||||||
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
|
#[AsCommand(name: 'opengnsys:migration:partition', description: 'Migrate os data')]
|
||||||
|
class MigratePartitionClientCommand extends Command
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private readonly EntityManagerInterface $entityManager,
|
||||||
|
private readonly ManagerRegistry $doctrine
|
||||||
|
)
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function execute(InputInterface $input, OutputInterface $output): int
|
||||||
|
{
|
||||||
|
ini_set('memory_limit', '512M');
|
||||||
|
|
||||||
|
/** @var EntityManagerInterface $oldDatabaseEntityManager */
|
||||||
|
$oldDatabaseEntityManager = $this->doctrine->getManager('og_1');
|
||||||
|
|
||||||
|
$clientRepository = $this->entityManager->getRepository(Client::class);
|
||||||
|
$operativeSystemRepository = $this->entityManager->getRepository(OperativeSystem::class);
|
||||||
|
|
||||||
|
/** Obtener las particiones de los clientes de la base de datos antigua **/
|
||||||
|
$rsmPartitions = new ResultSetMapping();
|
||||||
|
$rsmPartitions->addScalarResult('idordenador', 'idordenador');
|
||||||
|
$rsmPartitions->addScalarResult('idnombreso', 'idnombreso');
|
||||||
|
$rsmPartitions->addScalarResult('numdisk', 'numdisk');
|
||||||
|
$rsmPartitions->addScalarResult('numpar', 'numpar');
|
||||||
|
$rsmPartitions->addScalarResult('codpar', 'codpar');
|
||||||
|
$rsmPartitions->addScalarResult('tamano', 'tamano');
|
||||||
|
$rsmPartitions->addScalarResult('uso', 'uso');
|
||||||
|
|
||||||
|
$partitionQuery = $oldDatabaseEntityManager->createNativeQuery('SELECT idordenador, idnombreso, numdisk, numpar, codpar, tamano, uso FROM ordenadores_particiones', $rsmPartitions);
|
||||||
|
$partitions = $partitionQuery->getResult();
|
||||||
|
|
||||||
|
/** Particiones **/
|
||||||
|
$output->writeln("PARTICIONES TOTAL: ". count($partitions));
|
||||||
|
foreach ($partitions as $partition){
|
||||||
|
$clientEntity = $clientRepository->findOneBy(['migrationId' => $partition['idordenador']]);
|
||||||
|
if(!$clientEntity){
|
||||||
|
$output->writeln("No se ha encontrado el cliente con id: ". $partition['idordenador']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$operativeSystemEntity = $operativeSystemRepository->findOneBy(['migrationId' => $partition['idnombreso']]);
|
||||||
|
if(!$operativeSystemEntity){
|
||||||
|
$output->writeln("No se ha encontrado el sistema operativo con id: ". $partition['idnombreso']);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$partitionEntity = new Partition();
|
||||||
|
$partitionEntity->setDiskNumber($partition['numdisk']);
|
||||||
|
$partitionEntity->setPartitionNumber($partition['numpar']);
|
||||||
|
$partitionEntity->setPartitionCode($partition['codpar']);
|
||||||
|
$partitionEntity->setSize($partition['tamano']);
|
||||||
|
$partitionEntity->setMemoryUsage($partition['uso']);
|
||||||
|
$partitionEntity->setClient($clientEntity);
|
||||||
|
$partitionEntity->setOperativeSystem($operativeSystemEntity);
|
||||||
|
|
||||||
|
$this->entityManager->persist($partitionEntity);
|
||||||
|
$this->entityManager->flush();
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ use Symfony\Component\Console\Command\Command;
|
||||||
use Symfony\Component\Console\Input\InputInterface;
|
use Symfony\Component\Console\Input\InputInterface;
|
||||||
use Symfony\Component\Console\Output\OutputInterface;
|
use Symfony\Component\Console\Output\OutputInterface;
|
||||||
|
|
||||||
#[AsCommand(name: 'opengnsys:migrate-software-profile', description: 'Migrate software and software profile data')]
|
#[AsCommand(name: 'opengnsys:migration:software-profile', description: 'Migrate software and software profile data')]
|
||||||
class MigrateSoftwareAndSoftwareProfileCommand extends Command
|
class MigrateSoftwareAndSoftwareProfileCommand extends Command
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
|
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Controller\Api;
|
||||||
|
|
||||||
|
use App\Entity\Client;
|
||||||
|
use Doctrine\ORM\EntityManagerInterface;
|
||||||
|
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||||
|
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||||
|
use Symfony\Component\HttpFoundation\Request;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Component\Routing\Attribute\Route;
|
||||||
|
|
||||||
|
class SearchController extends AbstractController
|
||||||
|
{
|
||||||
|
#[Route('/search', methods: ['GET'])]
|
||||||
|
public function index(Request $request, EntityManagerInterface $entityManager): Response
|
||||||
|
{
|
||||||
|
$filters = $request->query->get('filters');
|
||||||
|
if ($filters) {
|
||||||
|
$filters = json_decode($filters, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
$repository = $entityManager->getRepository(Client::class);
|
||||||
|
$queryBuilder = $repository->createQueryBuilder('e');
|
||||||
|
|
||||||
|
if (!empty($filters)) {
|
||||||
|
foreach ($filters as $field => $value) {
|
||||||
|
$queryBuilder->andWhere("e.$field = :$field")
|
||||||
|
->setParameter($field, $value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$results = $queryBuilder->getQuery()->getResult();
|
||||||
|
|
||||||
|
return new JsonResponse($results);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Doctrine;
|
||||||
|
|
||||||
|
use ApiPlatform\Doctrine\Orm\Extension\QueryCollectionExtensionInterface;
|
||||||
|
use ApiPlatform\Doctrine\Orm\Extension\QueryItemExtensionInterface;
|
||||||
|
use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
|
||||||
|
use ApiPlatform\Metadata\Operation;
|
||||||
|
use App\Entity\User;
|
||||||
|
use App\Entity\View;
|
||||||
|
use Doctrine\ORM\QueryBuilder;
|
||||||
|
use Symfony\Bundle\SecurityBundle\Security;
|
||||||
|
|
||||||
|
final readonly class UserViewExtension implements QueryCollectionExtensionInterface, QueryItemExtensionInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private Security $security,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
|
||||||
|
{
|
||||||
|
$this->addWhere($queryBuilder, $resourceClass);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, ?Operation $operation = null, array $context = []): void
|
||||||
|
{
|
||||||
|
$this->addWhere($queryBuilder, $resourceClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function addWhere(QueryBuilder $queryBuilder, string $resourceClass): void
|
||||||
|
{
|
||||||
|
if (View::class !== $resourceClass ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @var User $user */
|
||||||
|
$user = $this->security->getUser();
|
||||||
|
|
||||||
|
$rootAlias = $queryBuilder->getRootAliases()[0];
|
||||||
|
$queryBuilder->andWhere(sprintf('%s.user = :current_user', $rootAlias));
|
||||||
|
$queryBuilder->setParameter('current_user', $user->getId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,46 +12,75 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
final class ClientInput
|
final class ClientInput
|
||||||
{
|
{
|
||||||
#[Assert\NotBlank]
|
#[Assert\NotBlank(message: 'validators.client.name.not_blank')]
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
#[ApiProperty(description: 'The name of the client', example: "Client 1")]
|
#[ApiProperty(
|
||||||
|
description: 'El nombre del cliente',
|
||||||
|
example: 'Cliente 1',
|
||||||
|
)]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
#[ApiProperty(description: 'The serial number of the client', example: "123456")]
|
#[ApiProperty(
|
||||||
|
description: 'La descripción del cliente',
|
||||||
|
example: 'Cliente descripcion 1',
|
||||||
|
)]
|
||||||
public ?string $serialNumber = null;
|
public ?string $serialNumber = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
#[ApiProperty(description: 'The network interface of the client', example: "eth0")]
|
#[ApiProperty(
|
||||||
|
description: 'La interfaz de red del cliente',
|
||||||
|
example: 'eth0'
|
||||||
|
)]
|
||||||
public ?string $netiface = null;
|
public ?string $netiface = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
#[ApiProperty(description: 'The network driver of the client', example: "e1000e")]
|
#[ApiProperty(
|
||||||
|
description: 'El driver de red del cliente',
|
||||||
|
example: 'e1000e'
|
||||||
|
)]
|
||||||
public ?string $netDriver = null;
|
public ?string $netDriver = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
#[ApiProperty(description: 'The MAC address of the client', example: "00:11:22:33:44:55")]
|
#[ApiProperty(
|
||||||
|
description: 'La dirección MAC del cliente',
|
||||||
|
example: '00:00:00:00:00:00'
|
||||||
|
)]
|
||||||
public ?string $mac = null;
|
public ?string $mac = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
#[Assert\Ip]
|
#[Assert\Ip(message: 'validators.ip_address.invalid')]
|
||||||
#[ApiProperty(description: 'The IP address of the client', example: "127.0.0.1")]
|
#[ApiProperty(
|
||||||
|
description: 'La dirección IP del cliente',
|
||||||
|
example: '192.168.1.1'
|
||||||
|
)]
|
||||||
public ?string $ip = null;
|
public ?string $ip = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Assert\NotNull(message: 'validators.organizational_unit.not_null')]
|
||||||
public ?string $status = null;
|
|
||||||
|
|
||||||
#[Assert\NotNull]
|
|
||||||
#[Groups(['client:write', 'client:patch'])]
|
#[Groups(['client:write', 'client:patch'])]
|
||||||
#[ApiProperty(description: 'The organizational unit of the client')]
|
#[ApiProperty(
|
||||||
|
description: 'La unidad organizativa del cliente'
|
||||||
|
)]
|
||||||
public ?OrganizationalUnitOutput $organizationalUnit = null;
|
public ?OrganizationalUnitOutput $organizationalUnit = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
|
#[ApiProperty(
|
||||||
|
description: 'El menú del cliente'
|
||||||
|
)]
|
||||||
public ?MenuOutput $menu = null;
|
public ?MenuOutput $menu = null;
|
||||||
|
|
||||||
#[Groups(['client:write'])]
|
#[Groups(['client:write'])]
|
||||||
|
#[ApiProperty(
|
||||||
|
description: 'El perfil de hardware del cliente'
|
||||||
|
)]
|
||||||
public ?HardwareProfileOutput $hardwareProfile = null;
|
public ?HardwareProfileOutput $hardwareProfile = null;
|
||||||
|
|
||||||
|
#[Groups(['client:write'])]
|
||||||
|
#[ApiProperty(
|
||||||
|
description: 'descriptions.client.validation'
|
||||||
|
)]
|
||||||
|
public ?array $position = ['x' => 0, 'y' => 0];
|
||||||
|
|
||||||
public function __construct(?Client $client = null)
|
public function __construct(?Client $client = null)
|
||||||
{
|
{
|
||||||
if (!$client) {
|
if (!$client) {
|
||||||
|
@ -65,7 +94,7 @@ final class ClientInput
|
||||||
$this->netDriver = $client->getNetDriver();
|
$this->netDriver = $client->getNetDriver();
|
||||||
$this->mac = $client->getMac();
|
$this->mac = $client->getMac();
|
||||||
$this->ip = $client->getIp();
|
$this->ip = $client->getIp();
|
||||||
$this->status = $client->getStatus();
|
$this->position = $client->getPosition();
|
||||||
|
|
||||||
if ($client->getMenu()) {
|
if ($client->getMenu()) {
|
||||||
$this->menu = new MenuOutput($client->getMenu());
|
$this->menu = new MenuOutput($client->getMenu());
|
||||||
|
@ -89,9 +118,9 @@ final class ClientInput
|
||||||
$client->setNetDriver($this->netDriver);
|
$client->setNetDriver($this->netDriver);
|
||||||
$client->setMac($this->mac);
|
$client->setMac($this->mac);
|
||||||
$client->setIp($this->ip);
|
$client->setIp($this->ip);
|
||||||
$client->setStatus($this->status);
|
|
||||||
$client->setMenu($this->menu?->getEntity());
|
$client->setMenu($this->menu?->getEntity());
|
||||||
$client->setHardwareProfile($this->hardwareProfile?->getEntity());
|
$client->setHardwareProfile($this->hardwareProfile?->getEntity());
|
||||||
|
$client->setPosition($this->position);
|
||||||
|
|
||||||
return $client;
|
return $client;
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
final class HardwareInput
|
final class HardwareInput
|
||||||
{
|
{
|
||||||
#[Assert\NotBlank]
|
#[Assert\NotBlank(message: 'validators.hardware.name.not_blank')]
|
||||||
#[Groups(['hardware:write'])]
|
#[Groups(['hardware:write'])]
|
||||||
#[ApiProperty(description: 'The name of the hardware', example: "Hardware 1")]
|
#[ApiProperty(description: 'The name of the hardware', example: "Hardware 1")]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
@ -19,7 +19,7 @@ final class HardwareInput
|
||||||
#[ApiProperty(description: 'The description of the hardware', example: "Hardware 1 description")]
|
#[ApiProperty(description: 'The description of the hardware', example: "Hardware 1 description")]
|
||||||
public ?string $description = null;
|
public ?string $description = null;
|
||||||
|
|
||||||
#[Assert\NotNull]
|
#[Assert\NotNull(message: 'validators.hardware.type.not_null')]
|
||||||
#[Groups(['hardware:write'])]
|
#[Groups(['hardware:write'])]
|
||||||
#[ApiProperty(description: 'The type of the hardware', example: "Server")]
|
#[ApiProperty(description: 'The type of the hardware', example: "Server")]
|
||||||
public ?HardwareTypeOutput $type = null;
|
public ?HardwareTypeOutput $type = null;
|
||||||
|
|
|
@ -8,7 +8,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class HardwareTypeInput
|
class HardwareTypeInput
|
||||||
{
|
{
|
||||||
#[Assert\NotBlank]
|
#[Assert\NotBlank(message: 'validators.hardware_type.name.not_blank')]
|
||||||
#[Groups(['hardware-type:write'])]
|
#[Groups(['hardware-type:write'])]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
final class ImageInput
|
final class ImageInput
|
||||||
{
|
{
|
||||||
#[Assert\NotBlank]
|
#[Assert\NotBlank(message: 'validators.image.name.not_blank')]
|
||||||
#[Groups(['image:write'])]
|
#[Groups(['image:write'])]
|
||||||
#[ApiProperty(description: 'The name of the image', example: "Image 1")]
|
#[ApiProperty(description: 'The name of the image', example: "Image 1")]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
|
@ -18,11 +18,11 @@ class NetworkSettingsInput
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?string $proxy = null;
|
public ?string $proxy = null;
|
||||||
|
|
||||||
#[Assert\Ip()]
|
#[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?string $dns = null;
|
public ?string $dns = null;
|
||||||
|
|
||||||
#[Assert\Ip()]
|
#[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?string $netmask = null;
|
public ?string $netmask = null;
|
||||||
|
|
||||||
|
@ -36,15 +36,15 @@ class NetworkSettingsInput
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?string $p2pMode = null;
|
public ?string $p2pMode = null;
|
||||||
|
|
||||||
#[Assert\GreaterThan(0)]
|
#[Assert\GreaterThan(0, message: 'validators.network_settings.p2p_time.invalid')]
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?int $p2pTime = null;
|
public ?int $p2pTime = null;
|
||||||
|
|
||||||
#[Assert\Ip()]
|
#[Assert\Ip(message: 'validators.network_settings.ip_address.invalid')]
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?string $mcastIp = null;
|
public ?string $mcastIp = null;
|
||||||
|
|
||||||
#[Assert\GreaterThan(0)]
|
#[Assert\GreaterThan(0, message: 'validators.network_settings.mcast_speed.invalid')]
|
||||||
#[Groups(['organizational-write:write'])]
|
#[Groups(['organizational-write:write'])]
|
||||||
public ?int $mcastSpeed = null;
|
public ?int $mcastSpeed = null;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
class OperativeSystemInput
|
class OperativeSystemInput
|
||||||
{
|
{
|
||||||
#[Assert\NotBlank]
|
#[Assert\NotBlank(message: 'validators.operative_system.name.not_blank')]
|
||||||
#[Groups(['operative-system:write'])]
|
#[Groups(['operative-system:write'])]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ use Symfony\Component\Validator\Constraints as Assert;
|
||||||
#[OrganizationalUnitParent]
|
#[OrganizationalUnitParent]
|
||||||
class OrganizationalUnitInput
|
class OrganizationalUnitInput
|
||||||
{
|
{
|
||||||
#[Assert\NotBlank]
|
#[Assert\NotBlank(message: 'validators.organizational_unit.name.not_blank')]
|
||||||
#[Groups(['organizational-unit:write'])]
|
#[Groups(['organizational-unit:write'])]
|
||||||
public ?string $name = null;
|
public ?string $name = null;
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto\Input;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\ApiProperty;
|
||||||
|
use App\Entity\View;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
use Symfony\Component\Validator\Constraints as Assert;
|
||||||
|
|
||||||
|
final class ViewInput
|
||||||
|
{
|
||||||
|
#[Assert\NotBlank(message: 'validators.view.name.not_blank')]
|
||||||
|
#[Groups(['view:write'])]
|
||||||
|
#[ApiProperty(description: 'The name of the view', example: "View 1")]
|
||||||
|
public ?string $name = null;
|
||||||
|
|
||||||
|
#[Groups(['view:write'])]
|
||||||
|
#[ApiProperty(description: 'The favourite status of the view', example: true)]
|
||||||
|
public ?bool $favourite = null;
|
||||||
|
|
||||||
|
#[Groups(['view:write'])]
|
||||||
|
#[ApiProperty(description: 'The filters of the view', example: ["filter1" => "value1"])]
|
||||||
|
public ?array $filters = null;
|
||||||
|
|
||||||
|
public function __construct(?View $view = null)
|
||||||
|
{
|
||||||
|
if (!$view) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->name = $view->getName();
|
||||||
|
$this->favourite = $view->isFavourite();
|
||||||
|
$this->filters= $view->getFilters();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createOrUpdateEntity(?View $view = null): View
|
||||||
|
{
|
||||||
|
if (!$view) {
|
||||||
|
$view = new View();
|
||||||
|
}
|
||||||
|
|
||||||
|
$view->setName($this->name);
|
||||||
|
$view->setFavourite($this->favourite);
|
||||||
|
$view->setFilters($this->filters);
|
||||||
|
|
||||||
|
return $view;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -48,6 +48,9 @@ final class ClientOutput extends AbstractOutput
|
||||||
#[ApiProperty(readableLink: true )]
|
#[ApiProperty(readableLink: true )]
|
||||||
public ?HardwareProfileOutput $hardwareProfile = null;
|
public ?HardwareProfileOutput $hardwareProfile = null;
|
||||||
|
|
||||||
|
#[Groups(['client:read'])]
|
||||||
|
public ?array $position = ['x' => 0, 'y' => 0];
|
||||||
|
|
||||||
#[Groups(['client:read'])]
|
#[Groups(['client:read'])]
|
||||||
public \DateTime $createdAt;
|
public \DateTime $createdAt;
|
||||||
|
|
||||||
|
@ -74,8 +77,8 @@ final class ClientOutput extends AbstractOutput
|
||||||
)->toArray();
|
)->toArray();
|
||||||
|
|
||||||
$this->menu = $client->getMenu() ? new MenuOutput($client->getMenu()) : null;
|
$this->menu = $client->getMenu() ? new MenuOutput($client->getMenu()) : null;
|
||||||
|
$this->position = $client->getPosition();
|
||||||
$this->hardwareProfile = $client->getHardwareProfile() ? new HardwareProfileOutput($client->getHardwareProfile()) : null;
|
$this->hardwareProfile = $client->getHardwareProfile() ? new HardwareProfileOutput($client->getHardwareProfile()) : null;
|
||||||
|
|
||||||
$this->createdAt = $client->getCreatedAt();
|
$this->createdAt = $client->getCreatedAt();
|
||||||
$this->createdBy = $client->getCreatedBy();
|
$this->createdBy = $client->getCreatedBy();
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Dto\Output;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\Get;
|
||||||
|
use App\Entity\View;
|
||||||
|
use Symfony\Component\Serializer\Annotation\Groups;
|
||||||
|
|
||||||
|
#[Get(shortName: 'View')]
|
||||||
|
final class ViewOutput extends AbstractOutput
|
||||||
|
{
|
||||||
|
#[Groups(['view:read'])]
|
||||||
|
public string $name;
|
||||||
|
|
||||||
|
#[Groups(['view:read'])]
|
||||||
|
public bool $favorite;
|
||||||
|
|
||||||
|
#[Groups(['view:read'])]
|
||||||
|
public ?array $filters = null;
|
||||||
|
|
||||||
|
public function __construct(View $view)
|
||||||
|
{
|
||||||
|
parent::__construct($view);
|
||||||
|
|
||||||
|
$this->name = $view->getName();
|
||||||
|
$this->favorite = $view->isFavourite();
|
||||||
|
$this->filters = $view->getFilters();
|
||||||
|
}
|
||||||
|
}
|
|
@ -54,6 +54,9 @@ class Client extends AbstractEntity
|
||||||
#[ORM\Column(nullable: true)]
|
#[ORM\Column(nullable: true)]
|
||||||
private ?bool $validation = null;
|
private ?bool $validation = null;
|
||||||
|
|
||||||
|
#[ORM\Column(nullable: true)]
|
||||||
|
private ?array $position = ['x' => 0, 'y' => 0];
|
||||||
|
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
parent::__construct();
|
parent::__construct();
|
||||||
|
@ -209,4 +212,16 @@ class Client extends AbstractEntity
|
||||||
|
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getPosition(): ?array
|
||||||
|
{
|
||||||
|
return $this->position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setPosition(?array $position): static
|
||||||
|
{
|
||||||
|
$this->position = $position;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Entity;
|
||||||
|
|
||||||
|
use App\Repository\ViewRepository;
|
||||||
|
use Doctrine\DBAL\Types\Types;
|
||||||
|
use Doctrine\ORM\Mapping as ORM;
|
||||||
|
|
||||||
|
#[ORM\Entity(repositoryClass: ViewRepository::class)]
|
||||||
|
class View extends \App\Entity\AbstractEntity
|
||||||
|
{
|
||||||
|
use NameableTrait;
|
||||||
|
|
||||||
|
#[ORM\Column]
|
||||||
|
private ?bool $favourite = null;
|
||||||
|
|
||||||
|
#[ORM\Column(type: Types::JSON, nullable: true)]
|
||||||
|
private ?array $filters = [];
|
||||||
|
|
||||||
|
#[ORM\ManyToOne]
|
||||||
|
private ?User $user = null;
|
||||||
|
|
||||||
|
public function setName(string $name): static
|
||||||
|
{
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function isFavourite(): ?bool
|
||||||
|
{
|
||||||
|
return $this->favourite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFavourite(bool $favourite): static
|
||||||
|
{
|
||||||
|
$this->favourite = $favourite;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getFilters(): ?array
|
||||||
|
{
|
||||||
|
return $this->filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setFilters(?array $filters): static
|
||||||
|
{
|
||||||
|
$this->filters = $filters;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUser(): ?User
|
||||||
|
{
|
||||||
|
return $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function setUser(?User $user): static
|
||||||
|
{
|
||||||
|
$this->user = $user;
|
||||||
|
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
// src/EventListener/LocaleSubscriber.php
|
||||||
|
namespace App\EventListener;
|
||||||
|
|
||||||
|
use Symfony\Component\HttpKernel\Event\RequestEvent;
|
||||||
|
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
|
||||||
|
use Symfony\Component\HttpKernel\KernelEvents;
|
||||||
|
use Symfony\Component\HttpFoundation\RequestStack;
|
||||||
|
|
||||||
|
class LocaleSubscriber implements EventSubscriberInterface
|
||||||
|
{
|
||||||
|
private string $defaultLocale;
|
||||||
|
private RequestStack $requestStack;
|
||||||
|
|
||||||
|
public function __construct(RequestStack $requestStack, string $defaultLocale = 'es')
|
||||||
|
{
|
||||||
|
$this->defaultLocale = $defaultLocale;
|
||||||
|
$this->requestStack = $requestStack;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onKernelRequest(RequestEvent $event): void
|
||||||
|
{
|
||||||
|
$request = $event->getRequest();
|
||||||
|
$locale = $request->getSession()->get('_locale', $this->defaultLocale);
|
||||||
|
|
||||||
|
if ($request->attributes->get('_locale')) {
|
||||||
|
$locale = $request->attributes->get('_locale');
|
||||||
|
}
|
||||||
|
|
||||||
|
$localeFromHeader = $request->getPreferredLanguage(['en', 'es']);
|
||||||
|
if ($localeFromHeader) {
|
||||||
|
$locale = $localeFromHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
$request->setLocale($locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getSubscribedEvents(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
KernelEvents::REQUEST => [['onKernelRequest', 20]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Factory;
|
||||||
|
|
||||||
|
use App\Entity\View;
|
||||||
|
use App\Repository\ViewRepository;
|
||||||
|
use Zenstruck\Foundry\ModelFactory;
|
||||||
|
use Zenstruck\Foundry\Persistence\PersistentProxyObjectFactory;
|
||||||
|
use Zenstruck\Foundry\Persistence\Proxy;
|
||||||
|
use Zenstruck\Foundry\Persistence\ProxyRepositoryDecorator;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends PersistentProxyObjectFactory<View>
|
||||||
|
*/
|
||||||
|
final class ViewFactory extends ModelFactory
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#factories-as-services
|
||||||
|
*
|
||||||
|
* @todo inject services if required
|
||||||
|
*/
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
parent::__construct();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function class(): string
|
||||||
|
{
|
||||||
|
return View::class;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#model-factories
|
||||||
|
*
|
||||||
|
* @todo add your default values here
|
||||||
|
*/
|
||||||
|
protected function getDefaults(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'createdAt' => self::faker()->dateTime(),
|
||||||
|
'favourite' => self::faker()->boolean(),
|
||||||
|
'name' => self::faker()->text(255),
|
||||||
|
'updatedAt' => self::faker()->dateTime()
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://symfony.com/bundles/ZenstruckFoundryBundle/current/index.html#initialization
|
||||||
|
*/
|
||||||
|
protected function initialize(): self
|
||||||
|
{
|
||||||
|
return $this
|
||||||
|
// ->afterInstantiate(function(View $view): void {})
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function getClass(): string
|
||||||
|
{
|
||||||
|
return View::class;
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,6 +19,8 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface
|
||||||
$openApi = $this->decorated->__invoke($context);
|
$openApi = $this->decorated->__invoke($context);
|
||||||
|
|
||||||
$this->addRefreshToken($openApi);
|
$this->addRefreshToken($openApi);
|
||||||
|
$this->addSearchEndpoint($openApi);
|
||||||
|
|
||||||
|
|
||||||
return $openApi;
|
return $openApi;
|
||||||
}
|
}
|
||||||
|
@ -75,4 +77,53 @@ final readonly class OpenApiFactory implements OpenApiFactoryInterface
|
||||||
)
|
)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
private function addSearchEndpoint(OpenApi $openApi): void
|
||||||
|
{
|
||||||
|
$openApi
|
||||||
|
->getPaths()
|
||||||
|
->addPath('/search', (new Model\PathItem())->withGet(
|
||||||
|
(new Model\Operation('getSearch'))
|
||||||
|
->withTags(['Search'])
|
||||||
|
->withResponses([
|
||||||
|
Response::HTTP_OK => [
|
||||||
|
'description' => 'Search results',
|
||||||
|
'content' => [
|
||||||
|
'application/json' => [
|
||||||
|
'schema' => [
|
||||||
|
'type' => 'object',
|
||||||
|
'properties' => [
|
||||||
|
'results' => [
|
||||||
|
'type' => 'array',
|
||||||
|
'items' => [
|
||||||
|
'type' => 'object',
|
||||||
|
'properties' => [
|
||||||
|
'id' => [
|
||||||
|
'type' => 'integer',
|
||||||
|
'example' => 1,
|
||||||
|
],
|
||||||
|
'name' => [
|
||||||
|
'type' => 'string',
|
||||||
|
'example' => 'Item name',
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
])
|
||||||
|
->withSummary('Search for items')
|
||||||
|
->withParameters([
|
||||||
|
new Model\Parameter(
|
||||||
|
'query',
|
||||||
|
'query',
|
||||||
|
'Search query parameter',
|
||||||
|
true,
|
||||||
|
false,
|
||||||
|
),
|
||||||
|
])
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Repository;
|
||||||
|
|
||||||
|
use App\Entity\View;
|
||||||
|
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||||
|
use Doctrine\Persistence\ManagerRegistry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @extends ServiceEntityRepository<View>
|
||||||
|
*/
|
||||||
|
class ViewRepository extends AbstractRepository
|
||||||
|
{
|
||||||
|
public function __construct(ManagerRegistry $registry)
|
||||||
|
{
|
||||||
|
parent::__construct($registry, View::class);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\State\Processor;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\Delete;
|
||||||
|
use ApiPlatform\Metadata\Operation;
|
||||||
|
use ApiPlatform\Metadata\Patch;
|
||||||
|
use ApiPlatform\Metadata\Post;
|
||||||
|
use ApiPlatform\Metadata\Put;
|
||||||
|
use ApiPlatform\State\ProcessorInterface;
|
||||||
|
use ApiPlatform\Validator\ValidatorInterface;
|
||||||
|
use App\Dto\Input\ViewInput;
|
||||||
|
use App\Dto\Output\ViewOutput;
|
||||||
|
use App\Repository\ViewRepository;
|
||||||
|
use Symfony\Component\Security\Core\Security;
|
||||||
|
|
||||||
|
readonly class ViewProcessor implements ProcessorInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ViewRepository $viewRepository,
|
||||||
|
private ValidatorInterface $validator,
|
||||||
|
private Security $security
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
public function process(mixed $data, Operation $operation, array $uriVariables = [], array $context = []): ViewOutput|null
|
||||||
|
{
|
||||||
|
switch ($operation){
|
||||||
|
case $operation instanceof Post:
|
||||||
|
case $operation instanceof Put:
|
||||||
|
case $operation instanceof Patch:
|
||||||
|
return $this->processCreateOrUpdate($data, $operation, $uriVariables, $context);
|
||||||
|
case $operation instanceof Delete:
|
||||||
|
return $this->processDelete($data, $operation, $uriVariables, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws \Exception
|
||||||
|
*/
|
||||||
|
private function processCreateOrUpdate($data, Operation $operation, array $uriVariables = [], array $context = []): ViewOutput
|
||||||
|
{
|
||||||
|
if (!($data instanceof ViewInput)) {
|
||||||
|
throw new \Exception(sprintf('data is not instance of %s', ViewInput::class));
|
||||||
|
}
|
||||||
|
|
||||||
|
$entity = null;
|
||||||
|
if (isset($uriVariables['uuid'])) {
|
||||||
|
$entity = $this->viewRepository->findOneByUuid($uriVariables['uuid']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$view = $data->createOrUpdateEntity($entity);
|
||||||
|
$view->setUser($this->security->getUser());
|
||||||
|
$this->validator->validate($view);
|
||||||
|
$this->viewRepository->save($view);
|
||||||
|
|
||||||
|
return new ViewOutput($view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function processDelete($data, Operation $operation, array $uriVariables = [], array $context = []): null
|
||||||
|
{
|
||||||
|
$user = $this->viewRepository->findOneByUuid($uriVariables['uuid']);
|
||||||
|
$this->viewRepository->delete($user);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,71 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\State\Provider;
|
||||||
|
|
||||||
|
use ApiPlatform\Metadata\Get;
|
||||||
|
use ApiPlatform\Metadata\GetCollection;
|
||||||
|
use ApiPlatform\Metadata\Operation;
|
||||||
|
use ApiPlatform\Metadata\Patch;
|
||||||
|
use ApiPlatform\Metadata\Put;
|
||||||
|
use ApiPlatform\State\Pagination\TraversablePaginator;
|
||||||
|
use ApiPlatform\State\ProviderInterface;
|
||||||
|
use App\Dto\Input\ViewInput;
|
||||||
|
use App\Dto\Output\ViewOutput;
|
||||||
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
||||||
|
|
||||||
|
readonly class ViewProvider implements ProviderInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
private ProviderInterface $collectionProvider,
|
||||||
|
private ProviderInterface $itemProvider
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provide(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||||
|
{
|
||||||
|
switch ($operation){
|
||||||
|
case $operation instanceof GetCollection:
|
||||||
|
return $this->provideCollection($operation, $uriVariables, $context);
|
||||||
|
case $operation instanceof Patch:
|
||||||
|
case $operation instanceof Put:
|
||||||
|
return $this->provideInput($operation, $uriVariables, $context);
|
||||||
|
case $operation instanceof Get:
|
||||||
|
return $this->provideItem($operation, $uriVariables, $context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function provideCollection(Operation $operation, array $uriVariables = [], array $context = []): object
|
||||||
|
{
|
||||||
|
$paginator = $this->collectionProvider->provide($operation, $uriVariables, $context);
|
||||||
|
|
||||||
|
$items = new \ArrayObject();
|
||||||
|
foreach ($paginator->getIterator() as $item){
|
||||||
|
$items[] = new ViewOutput($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new TraversablePaginator($items, $paginator->getCurrentPage(), $paginator->getItemsPerPage(), $paginator->getTotalItems());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideItem(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||||
|
{
|
||||||
|
$item = $this->itemProvider->provide($operation, $uriVariables, $context);
|
||||||
|
|
||||||
|
if (!$item) {
|
||||||
|
throw new NotFoundHttpException('View not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ViewOutput($item);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function provideInput(Operation $operation, array $uriVariables = [], array $context = []): object|array|null
|
||||||
|
{
|
||||||
|
if (isset($uriVariables['uuid'])) {
|
||||||
|
$item = $this->itemProvider->provide($operation, $uriVariables, $context);
|
||||||
|
|
||||||
|
return $item !== null ? new ViewInput($item) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ViewInput();
|
||||||
|
}
|
||||||
|
}
|
13
symfony.lock
13
symfony.lock
|
@ -219,6 +219,19 @@
|
||||||
"config/routes/security.yaml"
|
"config/routes/security.yaml"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
"symfony/translation": {
|
||||||
|
"version": "6.4",
|
||||||
|
"recipe": {
|
||||||
|
"repo": "github.com/symfony/recipes",
|
||||||
|
"branch": "main",
|
||||||
|
"version": "6.3",
|
||||||
|
"ref": "e28e27f53663cc34f0be2837aba18e3a1bef8e7b"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"config/packages/translation.yaml",
|
||||||
|
"translations/.gitignore"
|
||||||
|
]
|
||||||
|
},
|
||||||
"symfony/twig-bundle": {
|
"symfony/twig-bundle": {
|
||||||
"version": "6.4",
|
"version": "6.4",
|
||||||
"recipe": {
|
"recipe": {
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Functional;
|
||||||
|
|
||||||
|
|
||||||
|
use App\Entity\HardwareProfile;
|
||||||
|
use App\Entity\OrganizationalUnit;
|
||||||
|
use App\Entity\View;
|
||||||
|
use App\Factory\HardwareProfileFactory;
|
||||||
|
use App\Factory\OrganizationalUnitFactory;
|
||||||
|
use App\Factory\UserFactory;
|
||||||
|
use App\Factory\ViewFactory;
|
||||||
|
use App\Model\OrganizationalUnitTypes;
|
||||||
|
use App\Model\UserGroupPermissions;
|
||||||
|
use Symfony\Component\HttpFoundation\Response;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\DecodingExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface;
|
||||||
|
use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface;
|
||||||
|
|
||||||
|
class ViewTest extends AbstractTest
|
||||||
|
{
|
||||||
|
CONST string USER_ADMIN = 'ogadmin';
|
||||||
|
CONST string VIEW_CREATE = 'test-view-create';
|
||||||
|
CONST string VIEW_UPDATE = 'test-view-update';
|
||||||
|
CONST string VIEW_DELETE = 'test-view-delete';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RedirectionExceptionInterface
|
||||||
|
* @throws DecodingExceptionInterface
|
||||||
|
* @throws ClientExceptionInterface
|
||||||
|
* @throws TransportExceptionInterface
|
||||||
|
* @throws ServerExceptionInterface
|
||||||
|
*/
|
||||||
|
public function testGetCollectionViews(): void
|
||||||
|
{
|
||||||
|
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||||
|
|
||||||
|
ViewFactory::createMany(10, ['user' => $user]);
|
||||||
|
|
||||||
|
$this->createClientWithCredentials()->request('GET', '/views');
|
||||||
|
$this->assertResponseStatusCodeSame(Response::HTTP_OK);
|
||||||
|
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
||||||
|
$this->assertJsonContains([
|
||||||
|
'@context' => '/contexts/View',
|
||||||
|
'@id' => '/views',
|
||||||
|
'@type' => 'hydra:Collection',
|
||||||
|
'hydra:totalItems' => 10,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RedirectionExceptionInterface
|
||||||
|
* @throws DecodingExceptionInterface
|
||||||
|
* @throws ClientExceptionInterface
|
||||||
|
* @throws TransportExceptionInterface
|
||||||
|
* @throws ServerExceptionInterface
|
||||||
|
*/
|
||||||
|
public function testCreateView(): void
|
||||||
|
{
|
||||||
|
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||||
|
|
||||||
|
ViewFactory::createOne(['name' => self::VIEW_CREATE, 'favourite' => true, 'user' => $user]);
|
||||||
|
$viewIri = $this->findIriBy(View::class, ['name' => self::VIEW_CREATE]);
|
||||||
|
|
||||||
|
$this->createClientWithCredentials()->request('POST', '/views',['json' => [
|
||||||
|
'name' => self::VIEW_CREATE,
|
||||||
|
'favourite' => true
|
||||||
|
]]);
|
||||||
|
|
||||||
|
$this->assertResponseStatusCodeSame(201);
|
||||||
|
$this->assertResponseHeaderSame('content-type', 'application/ld+json; charset=utf-8');
|
||||||
|
$this->assertJsonContains([
|
||||||
|
'@context' => '/contexts/ViewOutput',
|
||||||
|
'@type' => 'View',
|
||||||
|
'name' => self::VIEW_CREATE
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws RedirectionExceptionInterface
|
||||||
|
* @throws DecodingExceptionInterface
|
||||||
|
* @throws ClientExceptionInterface
|
||||||
|
* @throws TransportExceptionInterface
|
||||||
|
* @throws ServerExceptionInterface
|
||||||
|
*/
|
||||||
|
public function testUpdateView(): void
|
||||||
|
{
|
||||||
|
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||||
|
|
||||||
|
ViewFactory::createOne(['name' => self::VIEW_CREATE, 'favourite' => true, 'user' => $user]);
|
||||||
|
$viewIri = $this->findIriBy(View::class, ['name' => self::VIEW_CREATE]);
|
||||||
|
|
||||||
|
$this->createClientWithCredentials()->request('PUT', $viewIri, ['json' => [
|
||||||
|
'name' => self::VIEW_UPDATE,
|
||||||
|
'favourite' => false
|
||||||
|
]]);
|
||||||
|
|
||||||
|
$this->assertResponseIsSuccessful();
|
||||||
|
$this->assertJsonContains([
|
||||||
|
'@id' => $viewIri,
|
||||||
|
'name' => self::VIEW_UPDATE,
|
||||||
|
'favorite' => false
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @throws TransportExceptionInterface
|
||||||
|
* @throws ServerExceptionInterface
|
||||||
|
* @throws RedirectionExceptionInterface
|
||||||
|
* @throws DecodingExceptionInterface
|
||||||
|
* @throws ClientExceptionInterface
|
||||||
|
*/
|
||||||
|
public function testDeleteView(): void
|
||||||
|
{
|
||||||
|
$user = UserFactory::createOne(['username' => self::USER_ADMIN, 'roles'=> [UserGroupPermissions::ROLE_SUPER_ADMIN]]);
|
||||||
|
|
||||||
|
ViewFactory::createOne(['name' => self::VIEW_DELETE, 'favourite' => true, 'user' => $user]);
|
||||||
|
$viewIri = $this->findIriBy(View::class, ['name' => self::VIEW_DELETE]);
|
||||||
|
|
||||||
|
$this->createClientWithCredentials()->request('DELETE', $viewIri);
|
||||||
|
$this->assertResponseStatusCodeSame(204);
|
||||||
|
$this->assertNull(
|
||||||
|
static::getContainer()->get('doctrine')->getRepository(View::class)->findOneBy(['name' => self::VIEW_DELETE])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,39 @@
|
||||||
|
# messages.en.yaml
|
||||||
|
validators:
|
||||||
|
client:
|
||||||
|
ip_address:
|
||||||
|
invalid: 'The IP address "{{ value }}" is not valid.'
|
||||||
|
name:
|
||||||
|
not_blank: 'The name should not be blank.'
|
||||||
|
organizational_unit:
|
||||||
|
not_null: 'The organizational unit should not be null.'
|
||||||
|
|
||||||
|
view:
|
||||||
|
name:
|
||||||
|
not_blank: 'The name should not be blank.'
|
||||||
|
|
||||||
|
hardware:
|
||||||
|
name:
|
||||||
|
not_blank: 'The name should not be blank.'
|
||||||
|
type:
|
||||||
|
not_null: 'The type should not be null.'
|
||||||
|
|
||||||
|
hardware_type:
|
||||||
|
name:
|
||||||
|
not_blank: 'The name should not be blank.'
|
||||||
|
|
||||||
|
image:
|
||||||
|
name:
|
||||||
|
not_blank: 'The name should not be blank.'
|
||||||
|
|
||||||
|
network_settings:
|
||||||
|
ip_address:
|
||||||
|
invalid: 'The IP address "{{ value }}" is not valid.'
|
||||||
|
p2p_time:
|
||||||
|
invalid: 'The P2P time "{{ value }}" is not valid.'
|
||||||
|
mcast_speed:
|
||||||
|
invalid: 'The MCAST speed "{{ value }}" is not valid.'
|
||||||
|
|
||||||
|
operative_system:
|
||||||
|
name:
|
||||||
|
not_blank: 'The name should not be blank.'
|
|
@ -0,0 +1,39 @@
|
||||||
|
# messages.es.yaml
|
||||||
|
validators:
|
||||||
|
client:
|
||||||
|
ip_address:
|
||||||
|
invalid: 'La dirección IP "{{ value }}" no es válida.'
|
||||||
|
name:
|
||||||
|
not_blank: 'El nombre no debería estar vacío.'
|
||||||
|
organizational_unit:
|
||||||
|
not_null: 'La unidad organizativa no debería estar vacía.'
|
||||||
|
|
||||||
|
view:
|
||||||
|
name:
|
||||||
|
not_blank: 'El nombre no debería estar vacío.'
|
||||||
|
|
||||||
|
hardware:
|
||||||
|
name:
|
||||||
|
not_blank: 'El nombre no debería estar vacío.'
|
||||||
|
type:
|
||||||
|
not_null: 'El tipo no debería estar vacío.'
|
||||||
|
|
||||||
|
hardware_type:
|
||||||
|
name:
|
||||||
|
not_blank: 'El nombre no debería estar vacío.'
|
||||||
|
|
||||||
|
image:
|
||||||
|
name:
|
||||||
|
not_blank: 'El nombre no debería estar vacío.'
|
||||||
|
|
||||||
|
network_settings:
|
||||||
|
ip_address:
|
||||||
|
invalid: 'La dirección IP "{{ value }}" no es válida.'
|
||||||
|
p2p_time:
|
||||||
|
invalid: 'El tiempo P2P "{{ value }}" no es válido.'
|
||||||
|
mcast_speed:
|
||||||
|
invalid: 'La velocidad MCAST "{{ value }}" no es válida.'
|
||||||
|
|
||||||
|
operative_system:
|
||||||
|
name:
|
||||||
|
not_blank: 'El nombre no debería estar vacío.'
|
Loading…
Reference in New Issue