- First commit, routes and database builder are usable
This commit is contained in:
commit
5f6ce82fd2
|
@ -0,0 +1,21 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2020 Dave Mc Nicoll
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"name": "mcnd/lean-console",
|
||||||
|
"description": "A powerful enough debug console for LEAN.",
|
||||||
|
"type": "library",
|
||||||
|
"license": "MIT",
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Dave Mc Nicoll",
|
||||||
|
"email": "mcndave@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"require": {
|
||||||
|
"mcnd/lean": "dev-master"
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Lean\\Console\\": "src/"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,5 @@
|
||||||
|
{
|
||||||
|
"title": "Console -- LEAN",
|
||||||
|
"page-title": "LEAN - Console"
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
{
|
||||||
|
"lean": {
|
||||||
|
"label": "Lean",
|
||||||
|
"dashboard": "Dashboard"
|
||||||
|
},
|
||||||
|
|
||||||
|
"storage": {
|
||||||
|
"label": "Storage",
|
||||||
|
"summary": "Summary",
|
||||||
|
"database": "Database",
|
||||||
|
"session": "Session"
|
||||||
|
},
|
||||||
|
|
||||||
|
"templating": {
|
||||||
|
"label": "Templating",
|
||||||
|
"picea": "Picea"
|
||||||
|
},
|
||||||
|
|
||||||
|
"caching": {
|
||||||
|
"label": "Caching"
|
||||||
|
},
|
||||||
|
|
||||||
|
"request": {
|
||||||
|
"label": "Request",
|
||||||
|
"routes": "Routes"
|
||||||
|
},
|
||||||
|
|
||||||
|
"email": {
|
||||||
|
"label": "Email",
|
||||||
|
"routes": "Activity"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"title": "Request -- LEAN",
|
||||||
|
"page-title": "LEAN - Request",
|
||||||
|
"route": {
|
||||||
|
"header": "List of active routes",
|
||||||
|
"name": "Name",
|
||||||
|
"uri": "URI",
|
||||||
|
"methods": "HTTP Methods",
|
||||||
|
"target": "class::method()"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"title": "Storage -- LEAN",
|
||||||
|
"page-title": "LEAN - Storage",
|
||||||
|
|
||||||
|
"database": {
|
||||||
|
"header": "List of databases",
|
||||||
|
"name": "Database",
|
||||||
|
"adapter": "Adapter",
|
||||||
|
"host": "Hostname:port",
|
||||||
|
"username": "Username",
|
||||||
|
"connection": "Connection",
|
||||||
|
|
||||||
|
"table": {
|
||||||
|
"header": "Tables details",
|
||||||
|
"fields": "{$count} fields",
|
||||||
|
"name": "Name",
|
||||||
|
"actions": "Actions",
|
||||||
|
"table-fields" : "Fields in table",
|
||||||
|
"create": "Create table",
|
||||||
|
"createAll": "Create all tables",
|
||||||
|
"query": "SQL Query"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"title" : "Console -- LEAN",
|
||||||
|
"page-title": "Console",
|
||||||
|
"breadcrumb" : {
|
||||||
|
"index" : "Negundo"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{
|
||||||
|
"title" : "Setup -- LEAN",
|
||||||
|
|
||||||
|
"breadcrumb" : {
|
||||||
|
"index" : "Negundo"
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
|
use Notes\Route\Annotation\Object\Route as RouteParam,
|
||||||
|
Notes\Route\Annotation\Method\Route,
|
||||||
|
Notes\Security\Annotation\Security,
|
||||||
|
Notes\Tell\Annotation\Language;
|
||||||
|
|
||||||
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Language("lean.console")
|
||||||
|
*/
|
||||||
|
class Console {
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/", "name" => "lean.console:home")
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @param array $arguments
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function home(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
return $this->renderView("page/dashboard/index", [
|
||||||
|
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use League\Route\Router;
|
||||||
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
|
use Notes\Route\Annotation\Object\Route as RouteParam,
|
||||||
|
Notes\Route\Annotation\Method\Route,
|
||||||
|
Notes\Security\Annotation\Security,
|
||||||
|
Notes\Tell\Annotation\Language;
|
||||||
|
|
||||||
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Picea\Extension\UrlExtension;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Language("lean.route")
|
||||||
|
*/
|
||||||
|
class Request extends Console {
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/request/routes", "name" => "lean.console:request.route")
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @param array $arguments
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function routes(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$routes = $this->container->has(UrlExtension::class) ? $this->container->get(UrlExtension::class)->getRouteList(true) : false;
|
||||||
|
|
||||||
|
uksort($routes, function($a, $b) {
|
||||||
|
return $a <=> $b;
|
||||||
|
});
|
||||||
|
|
||||||
|
return $this->renderView("page/request/route", [
|
||||||
|
'routes' => $routes
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use League\Route\Router;
|
||||||
|
|
||||||
|
use Picea\Ui\Method\FormHandler;
|
||||||
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
|
use Notes\Route\Annotation\Object\Route as RouteParam,
|
||||||
|
Notes\Route\Annotation\Method\Route,
|
||||||
|
Notes\Security\Annotation\Security,
|
||||||
|
Notes\Tell\Annotation\Language;
|
||||||
|
|
||||||
|
use \Lean\Console\Lib,
|
||||||
|
\Lean\Console\Form;
|
||||||
|
|
||||||
|
use Picea\Extension\UrlExtension;
|
||||||
|
|
||||||
|
use Ulmus\Annotation\Classes\Table,
|
||||||
|
Ulmus\Container\AdapterProxy;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Language("lean.storage")
|
||||||
|
*/
|
||||||
|
class Storage extends Console {
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Route("/storage/database", "name" => "lean.console:request.route")
|
||||||
|
* @param ServerRequestInterface $request
|
||||||
|
* @param array $arguments
|
||||||
|
* @return ResponseInterface
|
||||||
|
*/
|
||||||
|
public function database(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$connections = $this->container->has(AdapterProxy::class) ? $this->container->get(AdapterProxy::class)->connections : false;
|
||||||
|
$migrations = $this->container->has(Lib\DatabaseMigrations::class) ? $this->container->get(Lib\DatabaseMigrations::class) : false;
|
||||||
|
$migrations->getEntities();
|
||||||
|
|
||||||
|
$form = new FormHandler($request, new Form\Database($migrations), null);
|
||||||
|
$context = $form->context;
|
||||||
|
|
||||||
|
return $this->renderView("page/storage/database", get_defined_vars());
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createTable() : void
|
||||||
|
{
|
||||||
|
foreach($migrations->entities as $table) {
|
||||||
|
// $repository = $table
|
||||||
|
// $entity::repository()->createTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Entity;
|
||||||
|
|
||||||
|
use Ulmus\Common\EntityField;
|
||||||
|
use Ulmus\Entity\Field\Datetime,
|
||||||
|
Ulmus\Entity\InformationSchema;
|
||||||
|
use Ulmus\EntityCollection;
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Table('name' => "columns", 'database' => "information_schema")
|
||||||
|
*/
|
||||||
|
class Column extends InformationSchema\Column
|
||||||
|
{
|
||||||
|
|
||||||
|
public function differsFromFieldDefinition(FieldDefinition $definition) : bool
|
||||||
|
{
|
||||||
|
switch(true) {
|
||||||
|
//case $definition->
|
||||||
|
|
||||||
|
// return true;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* public static function entityCollection(...$arguments) : EntityCollection
|
||||||
|
{
|
||||||
|
return new class(...$arguments) extends EntityCollection
|
||||||
|
{
|
||||||
|
public function getEntityData() : array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,96 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Form;
|
||||||
|
|
||||||
|
use Picea\Ui\Method\{ FormInterface, FormContext, FormContextInterface };
|
||||||
|
|
||||||
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Picea\Compiler\Context;
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use \Ulmus\Entity\InformationSchema\Table;
|
||||||
|
|
||||||
|
class Database implements FormInterface
|
||||||
|
{
|
||||||
|
protected ? Lib\DatabaseMigrations $migration;
|
||||||
|
|
||||||
|
public function __construct(Lib\DatabaseMigrations $migration)
|
||||||
|
{
|
||||||
|
$this->migration = $migration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initialize(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
$context->tableExist = [];
|
||||||
|
|
||||||
|
foreach($this->migration->entities as $entity => $table) {
|
||||||
|
|
||||||
|
$table = Table::repository()->where(Table::field('name'), $table->tableName())
|
||||||
|
->where(Table::field('schema'), $table->databaseName())
|
||||||
|
->loadOne();
|
||||||
|
|
||||||
|
if ( $table ) {
|
||||||
|
#$fields = $entiy::resolveEntity()->fieldList();
|
||||||
|
|
||||||
|
foreach($table->columns as $col) {
|
||||||
|
dump( $entity::field($col->name) );
|
||||||
|
}
|
||||||
|
|
||||||
|
# if columns are different
|
||||||
|
$context->status[$entity] = [
|
||||||
|
'msg' => "up-to-date",
|
||||||
|
'query' => "",
|
||||||
|
];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$context->status[$entity] = [
|
||||||
|
'msg' => "unexisting",
|
||||||
|
'query' => $entity::repository()->createSqlQuery()->getSqlQuery(true),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( $context->formSent() ) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(FormContextInterface $context) : bool
|
||||||
|
{
|
||||||
|
return $context->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
if ( $context->create ?? false ) {
|
||||||
|
$context->create::repository()->createTable();
|
||||||
|
}
|
||||||
|
elseif ( $context->createAll ?? false ) {
|
||||||
|
foreach(explode(',', $context->createAll) as $entity) {
|
||||||
|
$entity::repository()->createTable();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->initialize($context);
|
||||||
|
}
|
||||||
|
catch (\Exception $ex) {
|
||||||
|
dump($ex);
|
||||||
|
|
||||||
|
$context->pushMessage(new Message(
|
||||||
|
"Une erreur inattendue semble avoir été provoquée lors de la sauvegarde des données. Le programmeur en charge du logiciel en a été avisé par courriel."
|
||||||
|
));
|
||||||
|
|
||||||
|
# @TODO ADD THEBUGS EMAIL SENDING HERE !!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public function getContext(ServerRequestInterface $request) : FormContextInterface
|
||||||
|
{
|
||||||
|
return new class($request) extends FormContext {
|
||||||
|
|
||||||
|
public array $status = [];
|
||||||
|
|
||||||
|
public array $actions = [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
use Storage\Session;
|
||||||
|
|
||||||
|
use Picea;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Language("lean.route")
|
||||||
|
* @RouteParam("methods" => [ 'GET', 'POST', 'DELETE' ], "base" => "/~")
|
||||||
|
* @Security('locked' => false)
|
||||||
|
*/
|
||||||
|
trait ConsoleControllerTrait
|
||||||
|
{
|
||||||
|
use \Lean\Console\ControllerTrait;
|
||||||
|
|
||||||
|
protected ContainerInterface $container;
|
||||||
|
|
||||||
|
public function __construct(? Picea\Picea $picea, Session $session, ContainerInterface $container) {
|
||||||
|
$this->picea = $picea;
|
||||||
|
$this->session = $session;
|
||||||
|
$this->container = $container;
|
||||||
|
// $this->mailer = $mailer;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,46 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Lib;
|
||||||
|
|
||||||
|
class DatabaseMigrations
|
||||||
|
{
|
||||||
|
public array $folderList;
|
||||||
|
|
||||||
|
public array $entities;
|
||||||
|
|
||||||
|
public function __construct(array $folders = [])
|
||||||
|
{
|
||||||
|
$this->folderList = $folders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getEntities() : void
|
||||||
|
{
|
||||||
|
$this->entities = [];
|
||||||
|
|
||||||
|
foreach($this->folderList as $folder => $namespace) {
|
||||||
|
foreach(static::files($folder) as $file) {
|
||||||
|
$name = $file->getBasename(".".$file->getExtension());
|
||||||
|
$entity = rtrim($namespace, "\\") . "\\{$name}";
|
||||||
|
$this->entities[$entity] = $entity::resolveEntity();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static function files(string $path, string $fileExtension = "") : \Generator
|
||||||
|
{
|
||||||
|
if ( \file_exists($path) ) {
|
||||||
|
$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST, \RecursiveIteratorIterator::CATCH_GET_CHILD);
|
||||||
|
|
||||||
|
foreach ($iterator as $file) {
|
||||||
|
if ( $file->isFile() || $file->isDir() ) {
|
||||||
|
if ($fileExtension && ( $file->getExtension() === $fileExtension )) {
|
||||||
|
yield $file;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
yield $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*! 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}
|
||||||
|
|
||||||
|
:root {
|
||||||
|
--color-red: #d47474
|
||||||
|
}
|
||||||
|
|
||||||
|
.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; font-size: 1rem; 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(255,0,0,0.5);color: rgba(255, 255, 255, 0.9);}
|
||||||
|
|
||||||
|
code {white-space:pre;font-family:monospace;color: #cacaca;background: #434446;display: block;padding: 1rem;line-height: 1.5em;border: 1px solid #2e2e30;}
|
||||||
|
h1 {font-size:2rem;color:#525960}
|
||||||
|
body {font-family:Helvetica Neue, Helvetica, Arial, sans-serif;}
|
||||||
|
summary {cursor:pointer;}
|
||||||
|
|
||||||
|
#body-main {background:#ccc;min-height:calc(100vh - 90px);display:flex}
|
||||||
|
|
||||||
|
/* Header */
|
||||||
|
#body-header {background: #385075; color:#fff; min-height:60px;line-height:60px;padding:0 1rem}
|
||||||
|
#body-header .page-title {font-size:1.5rem}
|
||||||
|
#body-header .page-title:before {content:"🔳"; margin-right:10px}
|
||||||
|
|
||||||
|
/* Footer */
|
||||||
|
#body-footer {background: #2e2e30;color: #fff;height: 30px;line-height: 30px;font-size: 0.8rem;padding: 0 0.5rem;text-align: right;border-top:2px solid #434446;}
|
||||||
|
|
||||||
|
/* Sidebar */
|
||||||
|
#main-nav {background:#393a3c;border-top:2px solid #172842;min-width:210px;color:#fff;font-family:consolas, courier new, monospace;font-size:0.9rem}
|
||||||
|
#main-nav label {background:rgba(0,0,0,0.2);text-transform:uppercase ; display:block;padding:0.8rem 1rem;font-size:1.15em;}
|
||||||
|
#main-nav label:before {content:"⊙"; margin-right:10px}
|
||||||
|
#main-nav a {color: #efecec;text-decoration:none;display:block;padding:0rem 1rem;background:rgba(255,255,255,0.05);transition:all 0.3s ease;line-height:3em;font-size:0.9em}
|
||||||
|
#main-nav a:before {content:"›"; margin-right:10px;line-height:3em}
|
||||||
|
#main-nav a:hover {background:rgba(255,255,255,0.1)}
|
||||||
|
#main-nav li + li {border-top:1px solid #555}
|
||||||
|
|
||||||
|
/* Main content */
|
||||||
|
#main-content {padding:4vh 2vw;border-top:2px solid #172842;width:100%;}
|
||||||
|
#main-content section {border-radius:4px;box-shadow: 1px 1px 3px rgba(0,0,0,0.5)}
|
||||||
|
#main-content section article {background:#fff;padding:2vh 1vw;}
|
||||||
|
#main-content section header {background:#e8e8e8;padding:2vh 1vw;}
|
|
@ -0,0 +1,44 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="LEAN console environment">
|
||||||
|
<meta name="author" content="Dave Mc Nicoll">
|
||||||
|
<meta name="msapplication-TileColor" content="#ccc">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%3E%3Ctext%20x='0'%20y='14'%3E🔳%3C/text%3E%3C/svg%3E" type="image/svg+xml" />
|
||||||
|
|
||||||
|
<title>{{ title() }}</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
{% include "lean/base/asset/lean.css" %}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{% section "head" %}{% endsection %}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header id="body-header">
|
||||||
|
{% section "header" %}{% endsection %}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main id="body-main">
|
||||||
|
{% section "nav" %}
|
||||||
|
{% view "lean/base/console/main-nav" %}
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
<section id="main-content">
|
||||||
|
{% section "content" %}{% endsection %}
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer id="body-footer">
|
||||||
|
{% section "footer" %}
|
||||||
|
© {{ date('Y') }} - LEAN
|
||||||
|
{% endsection %}
|
||||||
|
</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<nav id="main-nav">
|
||||||
|
<label>{% lang "lean.nav.lean.label" %}</label>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{ url('~') }}">{% lang "lean.nav.lean.dashboard" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<label>{% lang "lean.nav.request.label" %}</label>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{ url('~/request/routes') }}">{% lang "lean.nav.request.routes" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<label>{% lang "lean.nav.storage.label" %}</label>
|
||||||
|
<ul>
|
||||||
|
{#<li><a href="{{ url('~/storage') }}">{% lang "lean.nav.storage.summary" %}</a></li>#}
|
||||||
|
<li><a href="{{ url('~/storage/database') }}">{% lang "lean.nav.storage.database" %}</a></li>
|
||||||
|
<li><a href="{{ url('~/storage/session') }}">{% lang "lean.nav.storage.session" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<label>{% lang "lean.nav.templating.label" %}</label>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{ url('~/templating/picea') }}">{% lang "lean.nav.templating.picea" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<label>{% lang "lean.nav.caching.label" %}</label>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{{ url('~/storage') }}">{% lang "lean.nav.templating.picea" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="fr">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||||
|
<meta name="description" content="LEAN console environment">
|
||||||
|
<meta name="author" content="Dave Mc Nicoll">
|
||||||
|
<meta name="msapplication-TileColor" content="#ccc">
|
||||||
|
<meta name="theme-color" content="#ffffff">
|
||||||
|
|
||||||
|
<link rel="icon" href="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%2016%2016'%3E%3Ctext%20x='0'%20y='14'%3E🔳%3C/text%3E%3C/svg%3E" type="image/svg+xml" />
|
||||||
|
|
||||||
|
<title>{{ title() }}</title>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
{% include "lean/base/asset/lean.css" %}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
{% section "head" %}{% endsection %}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header>{% section "header" %}{% endsection %}</header>
|
||||||
|
<main>{% section "content" %}{% endsection %}</main>
|
||||||
|
<footer>{% section "footer" %}{% endsection %}</footer>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,13 @@
|
||||||
|
{% extends "lean/base/console/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.console" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "header" %}
|
||||||
|
<div class="page-title">{% _ "page-title" %}</div>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
|
||||||
|
{% endsection %}
|
|
@ -0,0 +1,49 @@
|
||||||
|
{% extends "lean/base/console/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.request" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "header" %}
|
||||||
|
<div class="page-title">{% _ "page-title" %}</div>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h1>{% _ 'route.header' %}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="routes">
|
||||||
|
{% if $routes %}
|
||||||
|
<strong class="grid">
|
||||||
|
<div class="col route-name">{% _ 'route.name' %}</div>
|
||||||
|
<div class="col route-uri">{% _ 'route.uri' %}</div>
|
||||||
|
<div class="col route-methods">{% _ 'route.methods' %}</div>
|
||||||
|
<div class="col controller-method">{% _ 'route.target' %}</div>
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
{% 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>
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
|
||||||
|
{% else %}
|
||||||
|
{% _ 'routeless' %}
|
||||||
|
{% endif %}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.routes strong.grid {background:#172842;color:#eeffee}
|
||||||
|
.routes .grid {padding:0.66rem 0.3rem}
|
||||||
|
.routes .grid strong {color:#444}
|
||||||
|
.routes .grid:nth-child(even) {background: #e3e3e3 }
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
|
@ -0,0 +1,7 @@
|
||||||
|
{% extends "lean/base/layout/console" %}
|
||||||
|
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
Welcome to Setup!
|
||||||
|
|
||||||
|
{% endsection %}
|
|
@ -0,0 +1,104 @@
|
||||||
|
{% extends "lean/base/console/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.storage" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "header" %}
|
||||||
|
<div class="page-title">{% _ "page-title" %}</div>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h1>{% _ 'database.header' %}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="databases">
|
||||||
|
{% if $connections %}
|
||||||
|
<strong class="grid db-grid">
|
||||||
|
<div class="col db-connection">{% _ 'database.connection' %}</div>
|
||||||
|
<div class="col db-adapter">{% _ 'database.adapter' %}</div>
|
||||||
|
<div class="col db-host">{% _ 'database.host' %}</div>
|
||||||
|
<div class="col db-name">{% _ 'database.name' %}</div>
|
||||||
|
<div class="col db-username">{% _ 'database.username' %}</div>
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
{% foreach $connections as $connection %}
|
||||||
|
{% php $conf = $connection->getConfiguration(); %}
|
||||||
|
|
||||||
|
<div class="grid db-grid">
|
||||||
|
<div class="col db-connection">{{ $connection->name }}</div>
|
||||||
|
<div class="col db-adapter">{{ $conf['adapter'] }}</div>
|
||||||
|
<div class="col db-host">{{ $conf['host'] }}:{{ $conf['port'] }}</div>
|
||||||
|
<div class="col db-name">{{ $conf['database'] }}</div>
|
||||||
|
<div class="col db-username">{{ $conf['username'] }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>
|
||||||
|
{% _ 'database.table.header' %}
|
||||||
|
</summary>
|
||||||
|
|
||||||
|
<div class="tables">
|
||||||
|
<strong class="grid table-item">
|
||||||
|
<div class="col">{% _ 'database.table.name' %}</div>
|
||||||
|
<div class="col">{% _ 'database.table.table-fields' %}</div>
|
||||||
|
<div class="col col-grow-2">{% _ 'database.table.query' %}</div>
|
||||||
|
<div class="col text-right">{% _ 'database.table.actions' %}</div>
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
{% ui.form.post "database" %}
|
||||||
|
{% foreach array_filter($migrations->entities, fn($e) => $e->databaseAdapter() === $connection) as $entity => $item %}
|
||||||
|
<div class="grid table-item align-items-center">
|
||||||
|
<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->status[$entity]['query'] %}
|
||||||
|
<code>{{ $context->status[$entity]['query'] }}</code>
|
||||||
|
{% else %}
|
||||||
|
<div>🗸 This table is up-to-date</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
{% switch $context->status[$entity]['msg'] %}
|
||||||
|
{% case 'unexisting' %}
|
||||||
|
{% php $createAll[] = $entity %}
|
||||||
|
|
||||||
|
<div class="text-right">
|
||||||
|
<button name="create" value="{{$entity}}" class="btn-blue">🗸 {% _ 'database.table.create' %}</button>
|
||||||
|
</div>
|
||||||
|
{% break %}
|
||||||
|
{% endswitch %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
|
||||||
|
{% if ($createAll ?? 0) > 1 %}
|
||||||
|
<div class="text-right" style="padding:0.5rem 0">
|
||||||
|
<button name="createAll" value="{{ implode(',', $createAll) }}" class="btn-red">🗸 {% _ 'database.table.createAll' %}</button>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
{% ui.endform %}
|
||||||
|
</div>
|
||||||
|
</details>
|
||||||
|
{% endforeach %}
|
||||||
|
{% endif %}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.databases strong.grid {background:#172842;color:#eeffee}
|
||||||
|
|
||||||
|
.databases .db-grid {padding:0.66rem 0.3rem}
|
||||||
|
.databases .db-grid strong {color:#444}
|
||||||
|
.databases .db-grid:nth-child(even) {background: #e3e3e3 }
|
||||||
|
|
||||||
|
.databases .tables .table-item {padding:0.33rem 0;background:rgba(255,255,255,0.1)}
|
||||||
|
.databases .tables .table-item:nth-child(even) {background:rgba(255,255,255,0.2)}
|
||||||
|
.databases summary {background: #172841;color:#fff;margin: 0 -8px 0 -8px;padding:7px 10px}
|
||||||
|
|
||||||
|
.tables {background: #172841;margin: 0 -8px 0 -8px;color: #fff;padding: 3px 10px;}
|
||||||
|
.tables label {padding:10px 5px;display:block}
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
Loading…
Reference in New Issue