- First commit, routes and database builder are usable
This commit is contained in:
		
						commit
						5f6ce82fd2
					
				
							
								
								
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								LICENSE
									
									
									
									
									
										Normal file
									
								
							| @ -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. | ||||
							
								
								
									
										20
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								composer.json
									
									
									
									
									
										Normal file
									
								
							| @ -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/" | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										5
									
								
								meta/i18n/en/lean.console.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								meta/i18n/en/lean.console.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,5 @@ | ||||
| { | ||||
|   "title": "Console -- LEAN", | ||||
|   "page-title": "LEAN - Console" | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										32
									
								
								meta/i18n/en/lean.nav.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								meta/i18n/en/lean.nav.json
									
									
									
									
									
										Normal file
									
								
							| @ -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" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										12
									
								
								meta/i18n/en/lean.request.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								meta/i18n/en/lean.request.json
									
									
									
									
									
										Normal file
									
								
							| @ -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()" | ||||
|   } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										25
									
								
								meta/i18n/en/lean.storage.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								meta/i18n/en/lean.storage.json
									
									
									
									
									
										Normal file
									
								
							| @ -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" | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										7
									
								
								meta/i18n/fr/lean.console.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								meta/i18n/fr/lean.console.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| { | ||||
|     "title" : "Console -- LEAN", | ||||
|     "page-title": "Console", | ||||
|     "breadcrumb" : { | ||||
|         "index" : "Negundo" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										7
									
								
								meta/i18n/fr/lean.setup.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								meta/i18n/fr/lean.setup.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| { | ||||
|     "title" : "Setup -- LEAN", | ||||
| 
 | ||||
|     "breadcrumb" : { | ||||
|         "index" : "Negundo" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/Controller/Console.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/Controller/Console.php
									
									
									
									
									
										Normal file
									
								
							| @ -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", [ | ||||
| 
 | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/Controller/Request.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/Controller/Request.php
									
									
									
									
									
										Normal file
									
								
							| @ -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 | ||||
|         ]); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										55
									
								
								src/Controller/Storage.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/Controller/Storage.php
									
									
									
									
									
										Normal file
									
								
							| @ -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();
 | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										44
									
								
								src/Entity/Column.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/Entity/Column.php
									
									
									
									
									
										Normal file
									
								
							| @ -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 [ | ||||
| 
 | ||||
|                 ]; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| */ | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										96
									
								
								src/Form/Database.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										96
									
								
								src/Form/Database.php
									
									
									
									
									
										Normal file
									
								
							| @ -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 = []; | ||||
|         }; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/Lib/ConsoleControllerTrait.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/Lib/ConsoleControllerTrait.php
									
									
									
									
									
										Normal file
									
								
							| @ -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;
 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										46
									
								
								src/Lib/DatabaseMigrations.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/Lib/DatabaseMigrations.php
									
									
									
									
									
										Normal file
									
								
							| @ -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; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										43
									
								
								view/base/asset/lean.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								view/base/asset/lean.css
									
									
									
									
									
										Normal 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;} | ||||
							
								
								
									
										44
									
								
								view/base/console/layout.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								view/base/console/layout.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||
							
								
								
									
										28
									
								
								view/base/console/main-nav.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								view/base/console/main-nav.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||
							
								
								
									
										28
									
								
								view/base/layout/console.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								view/base/layout/console.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -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> | ||||
							
								
								
									
										13
									
								
								view/page/dashboard/index.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								view/page/dashboard/index.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -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 %} | ||||
							
								
								
									
										49
									
								
								view/page/request/route.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								view/page/request/route.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -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 %} | ||||
							
								
								
									
										7
									
								
								view/page/setup/index.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								view/page/setup/index.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| {% extends "lean/base/layout/console" %} | ||||
| 
 | ||||
| 
 | ||||
| {% section "content" %} | ||||
|     Welcome to Setup! | ||||
| 
 | ||||
| {% endsection %} | ||||
							
								
								
									
										104
									
								
								view/page/storage/database.phtml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								view/page/storage/database.phtml
									
									
									
									
									
										Normal file
									
								
							| @ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user