2 Commits
Author SHA1 Message Date
Dave Mc Nicoll 0b1286c05f - WIP on CLI 2024-11-11 20:19:24 +00:00
Dave Mc Nicoll 73fca52013 - Fixed a bug where an empty definition would crash the migration: 2024-11-01 16:14:52 -04:00
25 changed files with 428 additions and 73 deletions

No files matched your search

+1 -4
View File
@@ -1,8 +1,6 @@
/*! minireset.css v0.0.6 | MIT License | github.com/jgthms/minireset.css */html,body,p,ol,ul,li,dl,dt,dd,blockquote,figure,fieldset,legend,textarea,pre,iframe,hr,h1,h2,h3,h4,h5,h6{margin:0;padding:0}h1,h2,h3,h4,h5,h6{font-size:100%;font-weight:normal}ul{list-style:none}button,input,select,textarea{margin:0}html{box-sizing:border-box}*,*::before,*::after{box-sizing:inherit}img,video{height:auto;max-width:100%}iframe{border:0}table{border-collapse:collapse;border-spacing:0}td,th{padding:0}td:not([align]),th:not([align]){text-align:left}
.grid{box-sizing:border-box;display:-webkit-flex;display:-ms-flexbox;display:-webkit-box;display:flex;-webkit-flex:0 1 auto;-ms-flex:0 1 auto;-webkit-box-flex:0;flex:0 1 auto;-webkit-flex-direction:row;-ms-flex-direction:row;-webkit-box-orient:horizontal;-webkit-box-direction:normal;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;margin:0 -8px 0 -8px}.grid.grid-nogutter{margin:0}.grid.grid-nogutter>.col{padding:0}.col{box-sizing:border-box;-webkit-flex:0 0 auto;-ms-flex:0 0 auto;flex:0 0 auto;-webkit-flex-grow:1;-ms-flex-positive:1;-webkit-box-flex:1;flex-grow:1;-ms-flex-preferred-size:0;-webkit-flex-basis:0;flex-basis:0;max-width:100%;min-width:0;padding:0 8px 0 8px}.col-align-top{-webkit-align-self:flex-start;-ms-flex-item-align:start;align-self:flex-start}.col-align-bottom{align-self:flex-end}.col-align-middle{-webkit-align-self:center;-ms-flex-item-align:center;align-self:center}.col-top{justify-content:flex-start !important;flex-direction:column;display:flex}.col-bottom{justify-content:flex-end !important;flex-direction:column;display:flex}.col-middle{justify-content:center;flex-direction:column;display:flex}.grid-start{-webkit-box-pack:start;-ms-flex-pack:start;justify-content:flex-start}.grid-center{-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center}.grid-end{-webkit-box-pack:end;-ms-flex-pack:end;justify-content:flex-end}.grid-around{justify-content:space-around}.grid-between{-webkit-box-pack:justify;-ms-flex-pack:justify;justify-content:space-between}.col-first{-webkit-box-ordinal-group:0;-ms-flex-order:-1;order:-1}.col-last{-webkit-box-ordinal-group:2;-ms-flex-order:1;order:1}.grid-reverse{-webkit-box-orient:horizontal;-webkit-box-direction:reverse;-ms-flex-direction:row-reverse;flex-direction:row-reverse}.col-fixed{flex:initial}.col-grow-2{flex-grow:2}.col-grow-3{flex-grow:3}.col-grow-4{flex-grow:4}.col-grow-5{flex-grow:5}.col-grow-6{flex-grow:6}.col-grow-7{flex-grow:7}.col-grow-8{flex-grow:8}.col-grow-9{flex-grow:9}.col-grow-10{flex-grow:10}.col-grow-11{flex-grow:11}.col-1{-ms-flex-preferred-size:8.33333%;-webkit-flex-basis:8.33333%;flex-basis:8.33333%;max-width:8.33333%}.col-2{-ms-flex-preferred-size:16.66667%;-webkit-flex-basis:16.66667%;flex-basis:16.66667%;max-width:16.66667%}.col-3{-ms-flex-preferred-size:25%;-webkit-flex-basis:25%;flex-basis:25%;max-width:25%}.col-4{-ms-flex-preferred-size:33.33333%;-webkit-flex-basis:33.33333%;flex-basis:33.33333%;max-width:33.33333%}.col-5{-ms-flex-preferred-size:41.66667%;-webkit-flex-basis:41.66667%;flex-basis:41.66667%;max-width:41.66667%}.col-6{-ms-flex-preferred-size:50%;-webkit-flex-basis:50%;flex-basis:50%;max-width:50%}.col-7{-ms-flex-preferred-size:58.33333%;-webkit-flex-basis:58.33333%;flex-basis:58.33333%;max-width:58.33333%}.col-8{-ms-flex-preferred-size:66.66667%;-webkit-flex-basis:66.66667%;flex-basis:66.66667%;max-width:66.66667%}.col-9{-ms-flex-preferred-size:75%;-webkit-flex-basis:75%;flex-basis:75%;max-width:75%}.col-10{-ms-flex-preferred-size:83.33333%;-webkit-flex-basis:83.33333%;flex-basis:83.33333%;max-width:83.33333%}.col-11{-ms-flex-preferred-size:91.66667%;-webkit-flex-basis:91.66667%;flex-basis:91.66667%;max-width:91.66667%}.col-12{-ms-flex-preferred-size:100%;-webkit-flex-basis:100%;flex-basis:100%;max-width:100%}@media only screen and (max-width: 480px){.col-sm{flex:100%;max-width:100%}}@media only screen and (max-width: 624px){.col-md{flex:100%;max-width:100%}}@media only screen and (max-width: 744px){.col-lg{flex:100%;max-width:100%}}
.align-items-center{align-items:center}.align-items-top{align-items:start}
.justify-content-around{justify-content: space-around;}.justify-content-end{justify-content: end}
.flex {display:flex}
:root {
--color-red: #d47474
@@ -10,7 +8,7 @@
.text-center{text-align:center;}.text-right{text-align:right}.text-left{text-align:left;}
[class^="btn-"], [class~=" btn-"] { display: inline-block; font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle; user-select: none; border: 1px solid transparent; padding: .375rem .75rem; line-height: 1.5; border-radius: .25rem; cursor:pointer; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; background:rgba(0,0,0,0.3); color:rgba(255,255,255,0.8); text-decoration:none; }
[class^="btn-"], [class~=" btn-"] { display: inline-block; font-weight: 400; text-align: center; white-space: nowrap; vertical-align: middle; user-select: none; border: 1px solid transparent; padding: .375rem .75rem; line-height: 1.5; border-radius: .25rem; cursor:pointer; transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out,box-shadow .15s ease-in-out; background:rgba(0,0,0,0.3); color:rgba(255,255,255,0.8); }
[class^="btn-"]:hover, [class~=" btn-"]:hover {border-color: rgba(0, 0, 0, 0.5);text-decoration: underline;}
.btn-red {background: rgba(155,0,0,0.5);color: rgba(255, 255, 255, 0.9);}
.btn-green {background: rgba(0,155,0,0.5);color: rgba(255, 255, 255, 0.9);}
@@ -25,7 +23,6 @@ summary {cursor:pointer;}
/* Header */
#body-header {background: #fff; color:#fff; min-height:60px;line-height:60px;padding:0 1rem;position:sticky;top:0;border-bottom:1px solid #ebedee;}
#body-header > div {min-height: 60px;}
#right-panel {max-width:calc(100% - 240px);width:100%;margin-left:auto}
#subheader {background:#fff; padding: 1rem 1.4rem;display:flex;justify-content: space-between;box-shadow:0 1px 2px rgba(55,65,75,0.15)}
#subheader h1 {font-size:1.1rem;font-size:inherit; font-weight:bold}
+4
View File
@@ -39,6 +39,10 @@ return [
]
],
'cli' => [
'Lean\\Console\\Cli' => implode(DIRECTORY_SEPARATOR, [ $path, "src", "Cli", "" ]),
],
'routes' => ! getenv('DEBUG') ? [] : [
'Lean\\Console\\Controller' => implode(DIRECTORY_SEPARATOR, [ $path, "src", "Controller", "" ]),
],
+2 -2
View File
@@ -10,7 +10,7 @@ use Storage\Session;
use function DI\autowire, DI\create, DI\get;
return [
/* 'lean:adapter.sqlite' => function($c) {
'lean:adapter.sqlite' => function($c) {
$adapter = new ConnectionAdapter('lean.console', $c->get('config')['ulmus'], false);
$adapter->resolveConfiguration();
@@ -23,5 +23,5 @@ return [
$adapter->resolveConfiguration();
return $adapter;
}*/
}
];
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace Lean\Console\Cli;
use Notes\CLI\Attribute\{Option, Command};
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
use Lean\Console\{Lib, };
# https://www.asciiart.eu/text-to-ascii-art
#[Command(description: PHP_EOL . <<<CLI
#[color:gray, bg: black]╔═════════════════════════╗[#]
#[color:gray, bg: black]║ _ ║[#]
#[color:gray, bg: black]║ | | ___ __ _ _ __ ║[#]
#[color:gray, bg: black]║ | | / _ \/ _` | '_ \ ║[#]
#[color:gray, bg: black]║ | |__| __/ (_| | | | | ║[#]
#[color:gray, bg: black]║ |_____\___|\__,_|_| |_| ║[#]
#[color:gray, bg: black]║ ║[#]
#[color:gray, bg: black]╚═════════════════════════╝[#]
Try #[color:gray, bg: black]'lean console --help'[#] for more information.
CLI
, command: 'console')]
#[Option(toggle: ['-h', '--help'], description: "Display help for the given command. When no command is given display help for the list command")]
#[Option(toggle: ['-q', '--quiet'], description: "Do not output any message")]
#[Option(toggle: ['-n', '--no-interaction'], description: "Run script without user interaction")]
#[Option(toggle: ['-v', '-vv', '-vvv', '--verbose'], description: "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", argument: Option::ARGUMENT_OPTIONAL)]
class Console
{
use Lib\ConsoleControllerTrait;
}
+41
View File
@@ -0,0 +1,41 @@
<?php
namespace Lean\Console\Cli;
use Notes\CLI\Attribute\{Option, Command};
use Psr\Http\Message\{ServerRequestInterface, ResponseInterface};
use Lean\Console\{Lib, };
# https://www.asciiart.eu/text-to-ascii-art
#[Command(description: PHP_EOL . <<<CLI
#[color:gray, bg: black]╔═════════════════════════╗[#]
#[color:gray, bg: black]║ _ ║[#]
#[color:gray, bg: black]║ | | ___ __ _ _ __ ║[#]
#[color:gray, bg: black]║ | | / _ \/ _` | '_ \ ║[#]
#[color:gray, bg: black]║ | |__| __/ (_| | | | | ║[#]
#[color:gray, bg: black]║ |_____\___|\__,_|_| |_| ║[#]
#[color:gray, bg: black]║ ║[#]
#[color:gray, bg: black]║ STORAGE ║[#]
#[color:gray, bg: black]╚═════════════════════════╝[#]
Try #[color:gray, bg: black]'lean console storage --help'[#] for more information.
CLI
, command: 'console storage')]
#[Option(toggle: ['-h', '--help'], description: "Display help for the given command. When no command is given display help for the list command")]
#[Option(toggle: ['-q', '--quiet'], description: "Do not output any message")]
#[Option(toggle: ['-n', '--no-interaction'], description: "Run script without user interaction")]
#[Option(toggle: ['-v', '-vv', '-vvv', '--verbose'], description: "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", argument: Option::ARGUMENT_OPTIONAL)]
class Storage
{
use Lib\ConsoleControllerTrait;
#[Command(description: "Generate entities based on an existing connection", command: "entity:generate")]
#[Option(toggle: ['-l', '--list'], description: "")]
public function generate_entity(ServerRequestInterface $request, array $arguments): ResponseInterface
{
dump($arguments);
return $this->renderCLI($request, ":)");
}
}
+6 -11
View File
@@ -3,7 +3,6 @@
namespace Lean\Console\Controller;
use League\Route\Router;
use Lean\Routing;
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
use Notes\Tell\Attribute\Language, Notes\Route\Attribute\Method\Route;
@@ -18,18 +17,14 @@ class Request extends Console {
#[Route(route: "/request/routes", name: "lean.console:request.route")]
public function routes(ServerRequestInterface $request, array $arguments) : ResponseInterface
{
$routing = $this->container->has(Routing::class) ? $this->container->get(Routing::class) : false;
$routes = $this->container->has(UrlExtension::class) ? $this->container->get(UrlExtension::class)->getRouteList(true) : false;
if ( $routing === false ) {
throw new \Exception("Lean's routing library do not seems to be integrated into your container definition...");
}
$routes = $routing->fetchRoutesAttributes();
uasort($routes, function($a, $b) {
return ( $a->class . $a->name ) <=> ( $b->class . $b->name );
uksort($routes, function($a, $b) {
return $a <=> $b;
});
return $this->renderView("lean-console/page/request/route", get_defined_vars());
return $this->renderView("lean-console/page/request/route", [
'routes' => $routes
]);
}
}
+2 -10
View File
@@ -27,7 +27,7 @@ class Storage extends Console {
$migrations = $this->container->has(Lib\DatabaseMigrations::class) ? $this->container->get(Lib\DatabaseMigrations::class) : false;
$migrations->getEntities();
$context = (new FormHandler($request, new Form\Storage\DatabaseMigration($migrations)))->context;
$context = (new FormHandler($request, new Form\Storage\Database\Migrate($migrations)))->context;
return $this->renderView("lean-console/page/storage/database", get_defined_vars());
}
@@ -39,7 +39,7 @@ class Storage extends Console {
$migrations = $this->container->has(Lib\DatabaseMigrations::class) ? $this->container->get(Lib\DatabaseMigrations::class) : false;
$migrations->getEntities();
$form = new Form\Storage\DatabaseImport($migrations, $connections);
$form = new Form\Storage\Database\Import($migrations, $connections);
$context = (new FormHandler($request, $form, $this->pushContext(new Lib\FormContext($request, "database.import"))))->context;
@@ -74,12 +74,4 @@ class Storage extends Console {
{
return rtrim(ini_get("session.save_path"), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
}
public function createTable() : void
{
foreach($migrations->entities as $table) {
// $repository = $table
// $entity::repository()->createTable();
}
}
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace Lean\Console\Entity\Firewall;
use Ulmus\Attribute\Obj\Table;
use Ulmus\Attribute\Property\Field;
use Ulmus\Entity\Field\Datetime;
#[Table(name:"firewall_banned_ips", adapter: "lean.console")]
class BannedIp implements \JsonSerializable
{
use \Ulmus\EntityTrait;
#[Field\Id]
public string $id;
#[Field\ForeignKey(name: "connection_id")]
public ? int $connectionId;
#[Field(length: 12)]
public ? string $ipv4;
#[Field(length: 40)]
public ? string $ipv6;
#[Field\Datetime(name: "banned_until")]
public Datetime $bannedUntil;
#[Field\Datetime(name: "created_at")]
public Datetime $createdAt;
}
+31
View File
@@ -0,0 +1,31 @@
<?php
namespace Lean\Console\Entity\Firewall;
use Ulmus\Attribute\Obj\Table;
use Ulmus\Attribute\Property\Field;
use Ulmus\Entity\Field\Datetime;
#[Table(name:"firewall_connections", adapter: "lean.console")]
class Connection implements \JsonSerializable
{
use \Ulmus\EntityTrait;
#[Field\Id]
public string $id;
#[Field(length: 12)]
public ? string $ipv4;
#[Field(length: 40)]
public ? string $ipv6;
#[Field]
public bool $success;
#[Field(length: 255, name: "error_message")]
public ? string $errorMessage;
#[Field\Datetime(name: "created_at")]
public Datetime $createdAt;
}
@@ -0,0 +1,34 @@
<?php
namespace Lean\Console\Form\Storage\Database;
use Picea\Ui\Method\{ FormInterface, FormContext, FormContextInterface };
use \Lean\Console\{ Lib, Entity };
use Picea\Compiler\Context;
use Psr\Http\Message\ServerRequestInterface;
use Ulmus\{ EntityCollection };
class GenerateEntity implements FormInterface
{
public function __construct()
{
}
public function initialize(FormContextInterface $context) : void
{
}
public function validate(FormContextInterface $context) : bool
{
return $context->valid();
}
public function execute(FormContextInterface $context) : void
{
}
}
@@ -1,6 +1,6 @@
<?php
namespace Lean\Console\Form\Storage;
namespace Lean\Console\Form\Storage\Database;
use Picea\Ui\Method\{ FormInterface, FormContext, FormContextInterface };
@@ -10,7 +10,7 @@ use Picea\Compiler\Context;
use Psr\Http\Message\ServerRequestInterface;
use Ulmus\{ EntityCollection };
class DatabaseImport implements FormInterface
class Import implements FormInterface
{
protected ? Lib\DatabaseMigrations $migration;
+163
View File
@@ -0,0 +1,163 @@
<?php
namespace Lean\Console\Form\Storage\Database;
use Picea\Ui\Method\{ FormInterface, FormContext, FormContextInterface };
use \Lean\Console\Lib;
use Picea\Compiler\Context;
use Psr\Http\Message\ServerRequestInterface;
use Ulmus\Common\EntityResolver;
use \Ulmus\Entity\InformationSchema\Table;
class Migrate implements FormInterface
{
public function __construct(
protected ? Lib\DatabaseMigrations $migration,
protected null|Lib\Database\DefinitionCollection $definition = null,
)
{
$this->definition ??= new Lib\Database\DefinitionCollection();
}
public function initialize(FormContextInterface $context) : void
{
foreach($this->migration->entities as $entity => $table) {
$previous = null;
$connection = $entity::resolveEntity()->sqlAdapter();
$adapter = $connection->adapter();
$tableName = $table->tableName();
$databaseName = $table->databaseName();
if ( ! $tableName || ! $databaseName ) {
continue;
}
# Query current table's columns
$tableEntity = $adapter->schemaTable($connection, $databaseName, $tableName);
$this->definition[$entity]['table'] = $tableDefinition = new Lib\Database\Definition(
entity: $entity,
modifier: new Lib\Database\Modifier( type: Lib\Database\ModifierTypeEnum::None, ),
);
if ( $tableEntity ) {
$this->definition[$entity]['columns'] = new Lib\Database\DefinitionCollection();
foreach($table->fieldList(EntityResolver::KEY_COLUMN_NAME, true) as $field => $definition) {
$this->definition[$entity]['columns'][$field] = $def = new Lib\Database\Definition(
entity: $entity,
field: $field,
definition: $definition,
modifier: new Lib\Database\Modifier( type: Lib\Database\ModifierTypeEnum::None, ),
previous: $def ?? null,
);
$column = $tableEntity->columns->filtersOne(fn($e) => strtolower($e->name) === $field);
# Column do not exists
if ( $column === null ) {
$def->action = "add";
$def->modifier = new Lib\Database\Modifier(
type: Lib\Database\ModifierTypeEnum::Alter,
query: $entity::repository()
->alterSqlQuery([ $def->toArray() ])
->getSqlQuery(true)
);
}
elseif ( ! $column->matchFieldDefinition($definition) ) {
$def->action = "change";
$def->modifier = new Lib\Database\Modifier(
type: Lib\Database\ModifierTypeEnum::Alter,
query: $entity::repository()
->alterSqlQuery([ $def->toArray() ])
->getSqlQuery(true)
);
}
}
# ALTER TABLE `ajustements` CHANGE `annee` `annee` INT(11) NULL;
$alter = $this->definition[$entity]['columns']->filterAlter();
if ( $alter->count() ) {
if ( $adapter->splitAlterQuery() ) {
$query = $alter->map(fn(Lib\Database\Definition $map) => $entity::repository()
->alterSqlQuery([ $map->toArray() ])
->getSqlQuery(true));
}
else {
$query = $entity::repository()
->alterSqlQuery($alter->map(fn(Lib\Database\Definition $map) => $map->toArray()))
->getSqlQuery(true);
}
$tableDefinition->modifier = new Lib\Database\Modifier(
type: Lib\Database\ModifierTypeEnum::Alter,
query: $query,
);
}
}
else {
$tableDefinition->modifier = new Lib\Database\Modifier(
type: Lib\Database\ModifierTypeEnum::Create,
query: $entity::repository()
->createSqlQuery()
->getSqlQuery(true)
);
}
}
$context->definition = $this->definition;
}
public function validate(FormContextInterface $context) : bool
{
return $context->valid();
}
public function execute(FormContextInterface $context) : void
{
$create = $context->createAll ? explode(',', $context->createAll) : [ $context->create ];
foreach(array_filter($create) as $entity) {
if ($this->definition[$entity]['table']->modifier->type === Lib\Database\ModifierTypeEnum::Create) {
$entity::repository()->createTable();
}
}
$alter = $context->alterAll ? explode(',', $context->alterAll) : [ $context->alter ];
foreach(array_filter($alter) as $entity) {
if ($this->definition[$entity]['table']->modifier->type === Lib\Database\ModifierTypeEnum::Alter) {
$adapter = $entity::resolveEntity()->sqlAdapter()->adapter();
$def = $this->definition[$entity]['columns']->filterAlter();
if ( $adapter->splitAlterQuery() ) {
$def->walk(fn(Lib\Database\Definition $definition) =>
$entity::repository()->alterTable([ $definition->toArray() ])
);
}
else {
$entity::repository()->alterTable($def->map( fn(Lib\Database\Definition $e) => $e->toArray() ));
}
}
}
$this->initialize($context);
}
public static function getContext(ServerRequestInterface $request, ? string $formName = null) : FormContextInterface
{
return new class($request, $formName) extends FormContext {
public array $status = [];
public array $actions = [];
};
}
}
+1 -14
View File
@@ -55,22 +55,10 @@ class DatabaseMigration implements FormInterface
previous: $def ?? null,
);
$column = $tableEntity->columns->filtersOne(fn($e) => strtolower($e->name) === $field);
# Column do not exists
if ( $column === null ) {
if ( $tableEntity->columns->filtersCollection(fn($e) => strtolower($e->name) === $field)->count() === 0 ) {
$def->action = "add";
$def->modifier = new Lib\Database\Modifier(
type: Lib\Database\ModifierTypeEnum::Alter,
query: $entity::repository()
->alterSqlQuery([ $def->toArray() ])
->getSqlQuery(true)
);
}
elseif ( ! $column->matchFieldDefinition($definition) ) {
$def->action = "change";
$def->modifier = new Lib\Database\Modifier(
type: Lib\Database\ModifierTypeEnum::Alter,
query: $entity::repository()
@@ -80,7 +68,6 @@ class DatabaseMigration implements FormInterface
}
}
# ALTER TABLE `ajustements` CHANGE `annee` `annee` INT(11) NULL;
$alter = $this->definition[$entity]['columns']->filterAlter();
if ( $alter->count() ) {
+1 -3
View File
@@ -2,14 +2,12 @@
namespace Lean\Console\Lib\Database;
use Notes\Common\ReflectedProperty;
class Definition
{
public function __construct(
public string $entity,
public string|null $field = null,
public array|null|ReflectedProperty $definition = null,
public array|null $definition = null,
public null|Modifier|array $modifier = null,
public null|Definition $previous = null,
public null|string $action = null,
+27
View File
@@ -0,0 +1,27 @@
<?php
namespace Ulmus\User\Middleware;
use Psr\Http\{
Message\ResponseInterface,
Message\ServerRequestInterface,
Server\MiddlewareInterface,
Server\RequestHandlerInterface
};
use Ulmus\User\Entity\UserInterface;
use Ulmus\User\Authorize\HeaderAuthentication;
class HeaderAuthenticationMiddleware implements MiddlewareInterface
{
protected HeaderAuthentication $authenticator;
public function __construct() {
}
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
return $handler->handle($request);
}
}
+1 -5
View File
@@ -25,11 +25,7 @@
<div id="right-panel">
<header id="body-header">
{% section "header" %}
<div class="flex align-items-center justify-content-end">
<a class="btn-blue" href="{% url %}">⇠ Return</a>
</div>
{% endsection %}
{% section "header" %}{% endsection %}
</header>
<div id="subheader">
@@ -4,6 +4,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "breadcrumb-items" %}
<li class="breadcrumb-item">{% _ 'breadcrumb' %}</li>
{% endsection %}
@@ -4,6 +4,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "content" %}
<section>
<article>Welcome into your Lean Console section. Select the appropriate menu item from the sidebar.</article>
@@ -4,6 +4,14 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "breadcrumb-items" %}
<li class="breadcrumb-item">{% _ 'logs.breadcrumb' %}</li>
{% endsection %}
{% section "content" %}
<section>
<header>
+12 -20
View File
@@ -4,21 +4,14 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "breadcrumb-items" %}
<li class="breadcrumb-item">{% _ 'route.breadcrumb' %}</li>
{% endsection %}
{% function routeHtml($route) %}
<div class="grid">
<strong class="col route-name">{{ $route->name }}</strong>
<div class="col route-uri">{{ $route->getRoute() }}</div>
<div class="col route-methods">{{ implode(', ', (array) ( $route->method ?? $route->methods )) }}</div>
<div class="col controller-method">
<span class="class">{{ $route->class }}</span>::<span>{{ $route->classMethod }}</span>
</div>
</div>
{% endfunction %}
{% section "content" %}
<section>
<header>
@@ -34,16 +27,15 @@
<div class="col controller-method">{% _ 'route.target' %}</div>
</strong>
{% foreach $routes as $route %}
{{ routeHtml($route) }}
{% if $overridden = $routing->findOverriddenRoute($route) %}
<div style="background:rgba(255,0,0,0.2); text-decoration:line-through">
{% foreach $routing->findOverriddenRoute($route) as $overridden %}
{{ routeHtml($overridden) }}
{% endforeach %}
{% foreach $routes as $name => $route %}
<div class="grid">
<strong class="col route-name">{{ $name }}</strong>
<div class="col route-uri">{{ $route['route'] }}</div>
<div class="col route-methods">{{ implode(', ', $route['routeMethods']) }}</div>
<div class="col controller-method">
<span class="class">{{ $route['class'] }}</span>::<span>{{ $route['classMethod'] }}</span>
</div>
{% endif %}
</div>
{% endforeach %}
{% else %}
{% _ 'routeless' %}
@@ -6,6 +6,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "breadcrumb-items" %}
<li class="breadcrumb-item">{% _ 'database.breadcrumb' %}</li>
{% endsection %}
@@ -47,7 +51,7 @@
<div class="col"><span>📄</span> <span>{{ $item->tableName() }}</span></div>
<div class="col">{% _ "database.table.fields", [ 'count' => count( $item->fieldList() ) ] %}</div>
<div class="col col-grow-2">
{% if $context->definition[$entity]['table']->modifier->query %}
{% if $context->definition[$entity]['table']->modifier->query ?? false %}
<code>{{= implode('<br><br>',(array) $context->definition[$entity]['table']->modifier->query) }}</code>
{% else %}
<div style="color:#abecab">&#x2713 {% _ 'database.table.uptodate' %}</div>
@@ -55,7 +59,7 @@
</div>
<div class="col">
{% switch $context->definition[$entity]['table']->modifier->type %}
{% switch $context->definition[$entity]['table']->modifier->type ?? false %}
{% case ModifierTypeEnum::Create %}
{% php $createAll[] = $entity %}
@@ -4,6 +4,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "content" %}
{% if $connections %}
{% ui:form.post "database.import" %}
@@ -4,6 +4,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "breadcrumb-items" %}
<li class="breadcrumb-item">{% _ 'session.breadcrumb' %}</li>
{% endsection %}
@@ -4,6 +4,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "breadcrumb-items" %}
<li class="breadcrumb-item">{% _ 'breadcrumb' %}</li>
{% endsection %}
@@ -4,6 +4,10 @@
{% title _("title") %}
{% section "header" %}
<div class="page-title">{% _ "page-title" %}</div>
{% endsection %}
{% section "content" %}
<section>
<header>