Compare commits
59
Commits
e78492d398
...
v1.3.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8323c6218e | ||
|
|
6d8763a22c | ||
|
|
0471c0ab83 | ||
|
|
0d3f807d9d | ||
|
|
e5fab028b3 | ||
|
|
7117021750 | ||
|
|
2fd9331c15 | ||
|
|
3de4b78a0b | ||
|
|
5b68bb191b | ||
|
|
d8b208426a | ||
|
|
3a8e56a617 | ||
|
|
39b02507a3 | ||
|
|
ce2b9399c2 | ||
|
|
cd38800131 | ||
|
|
8c71d0b4d8 | ||
|
|
0b1286c05f | ||
|
|
e260177943 | ||
|
|
73fca52013 | ||
|
|
474ec986a6 | ||
|
|
ac568b1750 | ||
|
|
d76148fed9 | ||
|
|
e032c89fdc | ||
|
|
6001ecdecd | ||
|
|
38638b5ad4 | ||
|
|
91ddd4d64c | ||
|
|
fd51903a8a | ||
|
|
55f5071475 | ||
|
|
e78ee3a458 | ||
|
|
a5f305fb7f | ||
|
|
a5d8e0a1aa | ||
|
|
10317a55f2 | ||
|
|
0de4a9d05a | ||
|
|
e898c6a23e | ||
|
|
64b9a779de | ||
|
|
ce5a97ce45 | ||
|
|
ea82d8dd08 | ||
|
|
b64f416fc0 | ||
|
|
e3de6146ec | ||
|
|
58a96c4b5c | ||
|
|
74d88dc8bf | ||
|
|
406694ce51 | ||
|
|
6be483dcf7 | ||
|
|
7ec6aa3f06 | ||
|
|
fbfbd48eb8 | ||
|
|
7b4d1e5cd7 | ||
|
|
d133ac662e | ||
|
|
5035a65672 | ||
|
|
f66ac02bcd | ||
|
|
963598764a | ||
|
|
f9229b890d | ||
|
|
eda0ee6f33 | ||
|
|
bf1bec644b | ||
|
|
689120dd44 | ||
|
|
6ff29a576c | ||
|
|
9c8f9903fc | ||
|
|
24e5490c71 | ||
|
|
94b5aff9e9 | ||
|
|
9c5cf3d1b1 | ||
|
|
da72314c62 |
No files matched your search
@@ -1,43 +1,60 @@
|
|||||||
/*! 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}
|
/*! 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%}}
|
.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}
|
.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 {
|
:root {--color-red: #d47474}
|
||||||
--color-red: #d47474
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-center{text-align:center;}.text-right{text-align:right}.text-left{text-align:left;}
|
.text-center{text-align:center;}.text-right{text-align:right}.text-left{text-align:left;}
|
||||||
|
.m-0 {margin:0!important}.mx-0 {margin-left:0!important;margin-right:0!important}.my-0 {margin-top:0!important;margin-bottom:0!important}
|
||||||
|
.p-0 {padding:0!important}.px-0 {padding-left:0!important;padding-right:0!important}.py-0 {padding-top:0!important;padding-bottom:0!important}
|
||||||
|
|
||||||
[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-"], [class~=" btn-"] { display: inline-block; font-weight: 400; font-size:16px; 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-"]:hover, [class~=" btn-"]:hover {border-color: rgba(0, 0, 0, 0.5);text-decoration: underline;}
|
[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);}
|
.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);}
|
||||||
|
.btn-blue {background: rgba(0,0,155,0.5);color: rgba(255, 255, 255, 0.9);}
|
||||||
|
.btn-yellow {background: rgba(249, 200, 11, 0.69);color: rgba(255, 255, 255, 0.9);}
|
||||||
|
.bg-yellow {background:#c09f1f!important}
|
||||||
|
|
||||||
code {white-space:pre;font-family:monospace;color: #cacaca;background: #434446;display: block;padding: 1rem;line-height: 1.5em;border: 1px solid #2e2e30;}
|
body{background:#f3f3f9}
|
||||||
h1 {font-size:2rem;color:#525960}
|
code {white-space:pre-line;font-family:monospace;color: #e6e6e6;background: #343537;display: block;padding: 1rem;line-height: 1.5em;border: 1px solid #2e2e30;}
|
||||||
body {font-family:Helvetica Neue, Helvetica, Arial, sans-serif;}
|
body {font-family:Helvetica Neue, Helvetica, Arial, sans-serif;}
|
||||||
summary {cursor:pointer;}
|
summary {cursor:pointer;}
|
||||||
|
|
||||||
#body-main {background:#ccc;min-height:calc(100vh - 90px);display:flex}
|
|
||||||
|
#body-main {min-height:calc(100vh - 30px);display:flex}
|
||||||
|
|
||||||
/* Header */
|
/* Header */
|
||||||
#body-header {background: #6b7fa8; color:#fff; min-height:60px;line-height:60px;padding:0 1rem}
|
#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 .page-title {font-size:1.5rem}
|
#body-header > div {min-height: 60px;}
|
||||||
#body-header .page-title:before {content:"🔳"; margin-right:10px}
|
#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}
|
||||||
|
#subheader .breadcrumb {font-size:0.9rem;display:flex;align-items:end}
|
||||||
|
#subheader .breadcrumb-item + .breadcrumb-item:before {content:"›";padding:0 6px;}
|
||||||
|
|
||||||
/* Footer */
|
/* Footer */
|
||||||
#body-footer {background: #475262;color: #fff;height: 30px;line-height: 30px;font-size: 0.8rem;padding: 0 0.5rem;text-align: right;border-top:2px solid #434446;}
|
#body-footer {background: #fff;color: #333;height: 30px;line-height: 30px;font-size: 0.8rem;padding: 0 0.5rem;text-align: right;border-top:1px solid #ebedee;}
|
||||||
|
|
||||||
/* Sidebar */
|
/* Sidebar */
|
||||||
#main-nav {background:#6b7fa8;border-top:2px solid #44526f;min-width:210px;color:#fff;font-family:consolas, courier new, monospace;font-size:0.9rem}
|
#main-nav {background:#373737;width:240px;color:#fff;font-family:consolas, courier new, monospace;font-size:0.9rem;position:fixed;top:0;bottom:0;overflow-y:auto;padding-bottom:2rem;border-right: 2px solid #333;}
|
||||||
#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 .app-title {font-size:1.3rem; text-align:center;padding:1.8rem 0}
|
||||||
|
#main-nav .app-title:before {content:"🔳"; margin-right:10px}
|
||||||
|
#main-nav label {color: #a4a4a4;text-transform:uppercase ; display:block;padding:0.8rem 1rem;font-size:1.15em;}
|
||||||
#main-nav label:before {content:"⊙"; margin-right:10px}
|
#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 {color: #efecec;text-decoration:none;display:block;padding:0 1rem 0 2rem;transition:all 0.3s ease;line-height:2.5em;font-size:0.9em}
|
||||||
#main-nav a:before {content:"›"; margin-right:10px;line-height:3em}
|
#main-nav a:before {content:"›"; margin-right:10px;}
|
||||||
#main-nav a:hover {background:rgba(255,255,255,0.1)}
|
#main-nav a:hover {background:rgba(255,255,255,0.1)}
|
||||||
#main-nav li + li {border-top:1px solid #555}
|
|
||||||
|
|
||||||
/* Main content */
|
/* Main content */
|
||||||
#main-content {padding:4vh 2vw;border-top:2px solid #7d7d7d;width:100%;}
|
#main-content {padding:4vh 2vw;width:100%;margin-left:auto;}
|
||||||
#main-content section {border-radius:4px;box-shadow: 1px 1px 3px rgba(0,0,0,0.5)}
|
#main-content section {border-radius:0.3rem;box-shadow: 0 1px 2px rgba(56,65,74,.15);display: flex;flex-direction: column;}
|
||||||
#main-content section article {background:#fff;padding:2vh 1vw;}
|
#main-content section article {border-radius:0.3rem;font-family: Courier New , Courier, monospace;font-size: 0.8em;background:#fff;padding:1.5rem;border: 1px solid #00000029;}
|
||||||
#main-content section header {background:#e8e8e8;padding:2vh 1vw;}
|
#main-content section header + article {border-top:0;border-top-left-radius: unset;border-top-right-radius: unset}
|
||||||
|
#main-content section header:has(+ article) {border: 1px solid #00000029;border-bottom:0}
|
||||||
|
#main-content section header {border-top-left-radius:0.3rem;border-top-right-radius:0.3rem;background:#373737;padding:1rem 1rem;font-size:1.2em;color: #fff;border-bottom:1px solid #7b7b7b;display:flex;align-items:center}
|
||||||
|
#main-content section article:has(+ footer) {border-bottom-left-radius:unset;border-bottom-right-radius:unset;border-bottom:0}
|
||||||
|
#main-content section footer {border-bottom-left-radius:0.3rem;border-bottom-right-radius:0.3rem;background:#f9f9f9;padding:1.5vh 1vw;line-height:1.5vh}
|
||||||
|
#main-content section article + footer {border: 1px solid #00000029;border-top:0}
|
||||||
|
#main-content section article [class*="col-"] {overflow-x:auto}
|
||||||
+15
-2
@@ -6,15 +6,28 @@
|
|||||||
"authors": [
|
"authors": [
|
||||||
{
|
{
|
||||||
"name": "Dave Mc Nicoll",
|
"name": "Dave Mc Nicoll",
|
||||||
"email": "mcndave@gmail.com"
|
"email": "info@mcnd.ca"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"require": {
|
"require": {
|
||||||
"mcnd/lean": "dev-master"
|
"mcnd/lean": "1.4.2"
|
||||||
},
|
},
|
||||||
"autoload": {
|
"autoload": {
|
||||||
"psr-4": {
|
"psr-4": {
|
||||||
"Lean\\Console\\": "src/"
|
"Lean\\Console\\": "src/"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"extra" : {
|
||||||
|
"lean" : {
|
||||||
|
"autoload": {
|
||||||
|
"definitions" : [
|
||||||
|
"meta/definitions/software.php",
|
||||||
|
"meta/definitions/storage.php"
|
||||||
|
],
|
||||||
|
"config": [
|
||||||
|
"meta/config.php"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
return [
|
||||||
|
'lean' => [
|
||||||
|
'autoload' => [
|
||||||
|
getenv('DEBUG') ? 'lean.console' : null,
|
||||||
|
]
|
||||||
|
],
|
||||||
|
|
||||||
|
'ulmus' => [
|
||||||
|
'connections' => [
|
||||||
|
'lean.console' => [
|
||||||
|
'adapter' => 'SQLite',
|
||||||
|
'path' => getenv('PROJECT_PATH') . DIRECTORY_SEPARATOR . "var/lean-console.sqlite3",
|
||||||
|
'pragma_begin' => array_filter([ "foreign_keys=ON", "synchronous=NORMAL", getenv('DEBUG') ? "journal_mode=WAL" : "" ]),
|
||||||
|
'pragma_close' => [ "analysis_limit=500", "optimize" ],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
],
|
||||||
|
];
|
||||||
@@ -2,30 +2,49 @@
|
|||||||
|
|
||||||
use Lean\Console\Lib\DatabaseMigrations;
|
use Lean\Console\Lib\DatabaseMigrations;
|
||||||
|
|
||||||
|
$path = dirname(__DIR__, 2);
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'lean.console' => [
|
'lean.console' => [
|
||||||
'picea' => [
|
'picea' => [
|
||||||
|
'context' => Lean\Console\View::class,
|
||||||
|
|
||||||
'view' => [
|
'view' => [
|
||||||
[
|
[
|
||||||
'path' => getenv("PROJECT_PATH") . "/vendor/mcnd/lean-console/view/",
|
'path' => implode(DIRECTORY_SEPARATOR, [ $path , "view", '' ]),
|
||||||
'order' => 99,
|
'order' => 99,
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
'asset' => [
|
||||||
|
[
|
||||||
|
'path' => implode(DIRECTORY_SEPARATOR, [ $path, "asset", '' ]),
|
||||||
|
'order' => 10
|
||||||
|
],
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
'ulmus' => [],
|
'ulmus' => [
|
||||||
|
'entities' => [
|
||||||
|
Lean\Console\Entity\Firewall::class => implode(DIRECTORY_SEPARATOR, [ $path , "src", "Entity", "Firewall" ]),
|
||||||
|
],
|
||||||
|
],
|
||||||
|
|
||||||
'tell' => [
|
'tell' => [
|
||||||
'json' => [
|
'json' => [
|
||||||
[
|
[
|
||||||
'path' => getenv("PROJECT_PATH") . "/vendor/mcnd/lean-console/meta/i18n",
|
'path' => implode(DIRECTORY_SEPARATOR, [ $path, "meta", "i18n", "" ]),
|
||||||
'order' => 99,
|
'order' => 99,
|
||||||
],
|
],
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
|
||||||
'routes' => [
|
'cli' => [
|
||||||
'Lean\\Console\\Controller' => getenv("PROJECT_PATH") . "/vendor/mcnd/lean-console/src/Controller/",
|
'Lean\\Console\\Cli' => implode(DIRECTORY_SEPARATOR, [ $path, "src", "Cli", "" ]),
|
||||||
|
],
|
||||||
|
|
||||||
|
'routes' => ! getenv('DEBUG') ? [] : [
|
||||||
|
Lean\Console\Controller::class => implode(DIRECTORY_SEPARATOR, [ $path, "src", "Controller", "" ]),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
use Ulmus\ConnectionAdapter,
|
||||||
|
Ulmus\Container\AdapterProxy;
|
||||||
|
|
||||||
|
use Storage\Session;
|
||||||
|
|
||||||
|
use function DI\autowire, DI\create, DI\get;
|
||||||
|
|
||||||
|
return [
|
||||||
|
/* 'lean:adapter.sqlite' => function($c) {
|
||||||
|
$adapter = new ConnectionAdapter('lean.console', $c->get('config')['ulmus'], false);
|
||||||
|
$adapter->resolveConfiguration();
|
||||||
|
|
||||||
|
return $adapter;
|
||||||
|
},
|
||||||
|
|
||||||
|
# @TODO BACKWARD COMPATIBILIY, TO BE REMOVED SOON !
|
||||||
|
'console.adapter' => function($c) {
|
||||||
|
$adapter = new ConnectionAdapter('lean.console', $c->get('config')['ulmus'], false);
|
||||||
|
$adapter->resolveConfiguration();
|
||||||
|
|
||||||
|
return $adapter;
|
||||||
|
}*/
|
||||||
|
];
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"title": "Caching -- LEAN",
|
||||||
|
"page-title": "LEAN - Caching",
|
||||||
|
"clear": "Clear",
|
||||||
|
"breadcrumb": "Caching"
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
{
|
{
|
||||||
"title": "Console -- LEAN",
|
"title": "Console -- LEAN",
|
||||||
"page-title": "LEAN - Console"
|
"page-title": "Console"
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"title" : "Debugging -- LEAN",
|
||||||
|
"page-title": "Debugging",
|
||||||
|
"logs": {
|
||||||
|
"breadcrumb": "Logs"
|
||||||
|
},
|
||||||
|
"phpinfo": {
|
||||||
|
"breadcrumb": "phpinfo()"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
{
|
{
|
||||||
"lean": {
|
"lean": {
|
||||||
"label": "Lean",
|
"label": "Lean",
|
||||||
"dashboard": "Dashboard"
|
"dashboard": "Dashboard",
|
||||||
|
"update": "Update(s)"
|
||||||
},
|
},
|
||||||
|
|
||||||
"storage": {
|
"storage": {
|
||||||
@@ -20,6 +21,13 @@
|
|||||||
"label": "Caching"
|
"label": "Caching"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"debugging": {
|
||||||
|
"label": "Debugging",
|
||||||
|
"logs": "Logs",
|
||||||
|
"phpinfo": "PhpInfo"
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
"request": {
|
"request": {
|
||||||
"label": "Request",
|
"label": "Request",
|
||||||
"routes": "Routes"
|
"routes": "Routes"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
"title": "Request -- LEAN",
|
"title": "Request -- LEAN",
|
||||||
"page-title": "LEAN - Request",
|
"page-title": "LEAN - Request",
|
||||||
"route": {
|
"route": {
|
||||||
|
"breadcrumb": "Routes",
|
||||||
"header": "List of active routes",
|
"header": "List of active routes",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"uri": "URI",
|
"uri": "URI",
|
||||||
|
|||||||
@@ -4,22 +4,40 @@
|
|||||||
|
|
||||||
"database": {
|
"database": {
|
||||||
"header": "List of databases",
|
"header": "List of databases",
|
||||||
|
"breadcrumb": "Database",
|
||||||
"name": "Database",
|
"name": "Database",
|
||||||
"adapter": "Adapter",
|
"adapter": "Adapter",
|
||||||
"host": "Hostname:port",
|
"host": "Hostname:port",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"connection": "Connection",
|
"connection": "Connection",
|
||||||
|
|
||||||
"table": {
|
"table": {
|
||||||
"header": "Tables details",
|
"header": "Tables details",
|
||||||
"fields": "{$count} fields",
|
"fields": "{$count} fields",
|
||||||
"name": "Name",
|
"name": "Table Name",
|
||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
|
"count": "Entries",
|
||||||
"table-fields" : "Fields in table",
|
"table-fields" : "Fields in table",
|
||||||
"create": "Create table",
|
"create": "Create table",
|
||||||
"createAll": "Create all tables",
|
"createAll": "Create all tables",
|
||||||
"query": "SQL Query"
|
"query": "SQL Query",
|
||||||
}
|
"add-column": "+ New row",
|
||||||
|
"alter": "Alter table",
|
||||||
|
"alterAll": "Alter all tables",
|
||||||
|
"uptodate": "This table is up-to-date"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
"database_insert": {
|
||||||
|
"add": "Create",
|
||||||
|
"breadcrumb": "Insert",
|
||||||
|
"readonly": "This field is read-only",
|
||||||
|
|
||||||
|
"table": {
|
||||||
|
"column": "Column",
|
||||||
|
"type": "Data type",
|
||||||
|
"function": "Function",
|
||||||
|
"attributes": "Attributs",
|
||||||
|
"value": "Value"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"title": "Templating -- LEAN",
|
||||||
|
"page-title": "LEAN - Templating",
|
||||||
|
"breadcrumb": "Templating",
|
||||||
|
"header": "Views"
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"title": "Update -- LEAN",
|
||||||
|
"page-title": "LEAN - Update",
|
||||||
|
"git": {
|
||||||
|
"breadcrumb": "Update",
|
||||||
|
"header": "Git Status"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,5 @@
|
|||||||
"title" : "Console -- LEAN",
|
"title" : "Console -- LEAN",
|
||||||
"page-title": "Console",
|
"page-title": "Console",
|
||||||
"breadcrumb" : {
|
"breadcrumb" : {
|
||||||
"index" : "Negundo"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"title" : "Debugging -- LEAN",
|
||||||
|
"page-title": "Déboguage",
|
||||||
|
"logs": {
|
||||||
|
"breadcrumb": "Journaux d'événements",
|
||||||
|
"line": "Lines number: "
|
||||||
|
},
|
||||||
|
"phpinfo": {
|
||||||
|
"breadcrumb": "phpinfo()"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -20,6 +20,12 @@
|
|||||||
"label": "Caching"
|
"label": "Caching"
|
||||||
},
|
},
|
||||||
|
|
||||||
|
"debugging": {
|
||||||
|
"label": "Déboguage",
|
||||||
|
"logs": "Journaux d'événements",
|
||||||
|
"phpinfo": "PhpInfo"
|
||||||
|
},
|
||||||
|
|
||||||
"request": {
|
"request": {
|
||||||
"label": "Request",
|
"label": "Request",
|
||||||
"routes": "Routes"
|
"routes": "Routes"
|
||||||
|
|||||||
@@ -13,13 +13,18 @@
|
|||||||
"table": {
|
"table": {
|
||||||
"header": "Tables details",
|
"header": "Tables details",
|
||||||
"fields": "{$count} fields",
|
"fields": "{$count} fields",
|
||||||
"name": "Name",
|
"name": "Table Name",
|
||||||
"actions": "Actions",
|
"actions": "Actions",
|
||||||
"table-fields" : "Fields in table",
|
"table-fields" : "Fields in table",
|
||||||
"create": "Create table",
|
"create": "Create table",
|
||||||
"createAll": "Create all tables",
|
"createAll": "Create all tables",
|
||||||
"query": "SQL Query"
|
"query": "SQL Query"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"session": {
|
||||||
|
"header": "Liste des sessions",
|
||||||
|
"breadcrumb": "Sessions",
|
||||||
|
"count": "{$count} session(s)"
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"title" : "Console -- LEAN",
|
||||||
|
"page-title": "Console",
|
||||||
|
"breadcrumb" : {
|
||||||
|
"index" : "Negundo"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Cli;
|
||||||
|
|
||||||
|
use Mcnd\CLI\OptionValueTypeEnum;
|
||||||
|
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]'cli lean-console --help'[#] for more information.
|
||||||
|
CLI
|
||||||
|
, command: 'lean-console')]
|
||||||
|
#[Option(switch: ['-h', '--help'], description: "Display help for the given command. When no command is given display help for the list command")]
|
||||||
|
#[Option(switch: ['-q', '--quiet'], description: "Do not output any message")]
|
||||||
|
#[Option(switch: ['-n', '--no-interaction'], description: "Run script without user interaction")]
|
||||||
|
#[Option(switch: ['-v', '-vv', '-vvv', '--verbose'], description: "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", value: OptionValueTypeEnum::OptionalValue)]
|
||||||
|
class Console
|
||||||
|
{
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Cli;
|
||||||
|
|
||||||
|
use Mcnd\CLI\OptionValueTypeEnum;
|
||||||
|
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]'cli lean-console storage --help'[#] for more information.
|
||||||
|
CLI
|
||||||
|
, command: 'lean-console storage')]
|
||||||
|
#[Option(switch: ['-h', '--help'], description: "Display help for the given command. When no command is given display help for the list command")]
|
||||||
|
#[Option(switch: ['-q', '--quiet'], description: "Do not output any message")]
|
||||||
|
#[Option(switch: ['-n', '--no-interaction'], description: "Run script without user interaction")]
|
||||||
|
#[Option(switch: ['-v', '-vv', '-vvv', '--verbose'], description: "Increase the verbosity of messages: 1 for normal output, 2 for more verbose output and 3 for debug", value: OptionValueTypeEnum::OptionalValue)]
|
||||||
|
class Storage
|
||||||
|
{
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
#[Command(description: "Generate entities based on an existing connection", command: "entity:generate")]
|
||||||
|
#[Option(switch: ['-l', '--list'], description: "")]
|
||||||
|
public function generate_entity(ServerRequestInterface $request, array $arguments): ResponseInterface
|
||||||
|
{
|
||||||
|
dump($arguments);
|
||||||
|
|
||||||
|
return $this->renderCLI($request, ":)");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use League\Route\Router;
|
||||||
|
use Picea\{FileFetcher, Picea, Caching\Opcache, Extension\UrlExtension, Ui\Method\FormHandler};
|
||||||
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
use Lean\Console\{ Form, Lib };
|
||||||
|
use Notes\Tell\Attribute\Language, Notes\Route\Attribute\Method\Route;
|
||||||
|
|
||||||
|
class Caching extends Console {
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
#[Route(route: "/caching/picea", name: "lean.console:caching")]
|
||||||
|
public function picea(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
|
||||||
|
if ( isset($this->picea) ) {
|
||||||
|
new FormHandler($request, new Form\Caching\Picea($this->picea, $list), $this->pushContext(new Lib\FormContext($request, "caching.picea")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/caching/picea", get_defined_vars());
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-11
@@ -2,28 +2,33 @@
|
|||||||
|
|
||||||
namespace Lean\Console\Controller;
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use Picea\Ui\Method\FormHandler;
|
||||||
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
use Notes\Route\Annotation\Object\Route as RouteParam,
|
use Notes\Tell\Attribute\Language, Notes\Route\Attribute\Method\Route;
|
||||||
Notes\Route\Annotation\Method\Route,
|
|
||||||
Notes\Security\Annotation\Security,
|
|
||||||
Notes\Tell\Annotation\Language;
|
|
||||||
|
|
||||||
use \Lean\Console\Lib;
|
use \Lean\Console\{ Lib, Form };
|
||||||
|
|
||||||
/**
|
|
||||||
* @Language("lean.console")
|
|
||||||
*/
|
|
||||||
class Console {
|
class Console {
|
||||||
use Lib\ConsoleControllerTrait;
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
/**
|
#[Route(route: "/", name: "lean.console:home")]
|
||||||
* @Route("/", "name" => "lean.console:home")
|
|
||||||
*/
|
|
||||||
public function home(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
public function home(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
{
|
{
|
||||||
return $this->renderView("lean-console/page/dashboard/index", [
|
return $this->renderView("lean-console/page/dashboard/index", [
|
||||||
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[Route(route: "/update", name: "lean.console:update")]
|
||||||
|
public function update(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
new FormHandler($request, $git = new Form\Update\Git(getenv('PROJECT_PATH')));
|
||||||
|
|
||||||
|
$status = iterator_to_array($git->run("/usr/bin/git status -s"));
|
||||||
|
$diff = iterator_to_array($git->run("/usr/bin/git diff"));
|
||||||
|
$lastUpdate = iterator_to_array($git->run("/usr/bin/git show --no-patch --format=%ci"))[0] ?? null;
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/update/index", get_defined_vars());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use Picea\{Ui\Method\FormHandler};
|
||||||
|
use Lean\File;
|
||||||
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
use Lean\Console\{ Form, Lib };
|
||||||
|
use Notes\Route\Attribute\Method\Route;
|
||||||
|
|
||||||
|
class Debugging extends Console {
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
#[Route(route: "/debugging/logs", name: "lean.console:debugging-logs")]
|
||||||
|
public function logs(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$list = [];
|
||||||
|
|
||||||
|
# new FormHandler($request, new Form\Debugging\Logs(), $this->pushContext(new Lib\FormContext($request, "debugging.logs")));
|
||||||
|
|
||||||
|
$path = getenv('LOGS_PATH');
|
||||||
|
|
||||||
|
$files = array_map(fn($e) => basename($e), glob("$path/*"));
|
||||||
|
|
||||||
|
$default = basename(ini_get('error_log'));
|
||||||
|
|
||||||
|
$open = File::sanitizeFilePath($request->getQueryParams()['logfile'] ?? end($files));
|
||||||
|
|
||||||
|
$content = File::tail($path . DIRECTORY_SEPARATOR . $open, $request->getQueryParams()['line'] ?? 100);
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/debugging/logs", get_defined_vars());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(route: "/debugging/phpinfo", name: "lean.console:debugging-phpinfo")]
|
||||||
|
public function phpinfo(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
ob_start() ;
|
||||||
|
phpinfo() ;
|
||||||
|
$phpinfo = ob_get_contents() ;
|
||||||
|
ob_end_clean() ;
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/debugging/phpinfo", get_defined_vars());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
<?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.dev")
|
|
||||||
*/
|
|
||||||
class Dev {
|
|
||||||
use Lib\ConsoleControllerTrait;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Route("/phpinfo", "name" => "lean.dev:phpinfo")
|
|
||||||
*/
|
|
||||||
public function home(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
|
||||||
{
|
|
||||||
phpinfo();
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
class Firewall
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
+13
-19
@@ -3,39 +3,33 @@
|
|||||||
namespace Lean\Console\Controller;
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
use League\Route\Router;
|
use League\Route\Router;
|
||||||
|
use Lean\Routing;
|
||||||
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
use Notes\Route\Annotation\Object\Route as RouteParam,
|
use Notes\Tell\Attribute\Language, Notes\Route\Attribute\Method\Route;
|
||||||
Notes\Route\Annotation\Method\Route,
|
|
||||||
Notes\Security\Annotation\Security,
|
|
||||||
Notes\Tell\Annotation\Language;
|
|
||||||
|
|
||||||
use \Lean\Console\Lib;
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
use Picea\Extension\UrlExtension;
|
use Picea\Extension\UrlExtension;
|
||||||
|
|
||||||
/**
|
|
||||||
* @Language("lean.request")
|
|
||||||
*/
|
|
||||||
class Request extends Console {
|
class Request extends Console {
|
||||||
use Lib\ConsoleControllerTrait;
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
/**
|
#[Route(route: "/request/routes", name: "lean.console:request.route")]
|
||||||
* @Route("/request/routes", "name" => "lean.console:request.route")
|
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
* @param array $arguments
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function routes(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
public function routes(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
{
|
{
|
||||||
$routes = $this->container->has(UrlExtension::class) ? $this->container->get(UrlExtension::class)->getRouteList(true) : false;
|
$routing = $this->container->has(Routing::class) ? $this->container->get(Routing::class) : false;
|
||||||
|
|
||||||
uksort($routes, function($a, $b) {
|
if ( $routing === false ) {
|
||||||
return $a <=> $b;
|
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 );
|
||||||
});
|
});
|
||||||
|
|
||||||
return $this->renderView("lean-console/page/request/route", [
|
return $this->renderView("lean-console/page/request/route", get_defined_vars());
|
||||||
'routes' => $routes
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+53
-21
@@ -7,10 +7,7 @@ use League\Route\Router;
|
|||||||
use Picea\Ui\Method\FormHandler;
|
use Picea\Ui\Method\FormHandler;
|
||||||
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
use Notes\Route\Annotation\Object\Route as RouteParam,
|
use Notes\Tell\Attribute\Language, Notes\Route\Attribute\Method\Route;
|
||||||
Notes\Route\Annotation\Method\Route,
|
|
||||||
Notes\Security\Annotation\Security,
|
|
||||||
Notes\Tell\Annotation\Language;
|
|
||||||
|
|
||||||
use \Lean\Console\Lib,
|
use \Lean\Console\Lib,
|
||||||
\Lean\Console\Form;
|
\Lean\Console\Form;
|
||||||
@@ -20,36 +17,71 @@ use Picea\Extension\UrlExtension;
|
|||||||
use Ulmus\Annotation\Classes\Table,
|
use Ulmus\Annotation\Classes\Table,
|
||||||
Ulmus\Container\AdapterProxy;
|
Ulmus\Container\AdapterProxy;
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @Language("lean.storage")
|
|
||||||
*/
|
|
||||||
class Storage extends Console {
|
class Storage extends Console {
|
||||||
use Lib\ConsoleControllerTrait;
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
/**
|
#[Route(route: "/storage/database", name: "lean.console:storage.database")]
|
||||||
* @Route("/storage/database", "name" => "lean.console:request.route")
|
|
||||||
* @param ServerRequestInterface $request
|
|
||||||
* @param array $arguments
|
|
||||||
* @return ResponseInterface
|
|
||||||
*/
|
|
||||||
public function database(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
public function database(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
{
|
{
|
||||||
$connections = $this->container->has(AdapterProxy::class) ? $this->container->get(AdapterProxy::class)->connections : false;
|
$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 = $this->container->has(Lib\DatabaseMigrations::class) ? $this->container->get(Lib\DatabaseMigrations::class) : false;
|
||||||
$migrations->getEntities();
|
$migrations->getEntities();
|
||||||
|
|
||||||
$form = new FormHandler($request, new Form\Database($migrations), null);
|
$context = (new FormHandler($request, new Form\Storage\Database\Migrate($migrations), $this->pushContext(new Lib\FormContext($request, "database.migrate"))))->context;
|
||||||
$context = $form->context;
|
|
||||||
|
|
||||||
return $this->renderView("lean-console/page/storage/database", get_defined_vars());
|
return $this->renderView("lean-console/page/storage/database", get_defined_vars());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createTable() : void
|
#[Route(route: "/storage/database/import", name: "lean.console:storage.database_import")]
|
||||||
|
public function database_import(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
{
|
{
|
||||||
foreach($migrations->entities as $table) {
|
$connections = $this->container->has(AdapterProxy::class) ? $this->container->get(AdapterProxy::class)->connections : false;
|
||||||
// $repository = $table
|
$migrations = $this->container->has(Lib\DatabaseMigrations::class) ? $this->container->get(Lib\DatabaseMigrations::class) : false;
|
||||||
// $entity::repository()->createTable();
|
$migrations->getEntities();
|
||||||
}
|
|
||||||
|
$form = new Form\Storage\Database\Import($migrations, $connections);
|
||||||
|
|
||||||
|
$context = (new FormHandler($request, $form, $this->pushContext(new Lib\FormContext($request, "database.import"))))->context;
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/storage/database_import", get_defined_vars());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(route: "/storage/database/insert", name: "lean.console:storage.database_insert")]
|
||||||
|
public function insert(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$class = $request->getQueryParams()['source'] ?? $request->getParsedBody()['source'];
|
||||||
|
|
||||||
|
$context = (new FormHandler($request, new Form\Storage\Database\Insert(new $class())))->context;
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/storage/database_insert", get_defined_vars());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(route: "/storage/session", name: "lean.console:storage.session")] # migrated from: "/storage/session", "name" => "lean.console:storage.session"
|
||||||
|
public function session(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$path = ini_get("session.save_path");
|
||||||
|
|
||||||
|
$sessions = preg_grep("/^sess_/", scandir($path));
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/storage/session", get_defined_vars());
|
||||||
|
}
|
||||||
|
|
||||||
|
#[Route(route: "/storage/session/content/{hash}", name: "lean.console:storage.session_content")] # migrated from: "/storage/session/content/{hash}", "name" => "lean.console:storage.session_content"
|
||||||
|
public function sessionContent(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$sess = session_encode();
|
||||||
|
|
||||||
|
session_decode(file_get_contents($this->sessionPath() . $arguments['hash']));
|
||||||
|
|
||||||
|
$data = array_combine(array_keys($_SESSION), array_values($_SESSION));
|
||||||
|
|
||||||
|
session_decode($sess);
|
||||||
|
|
||||||
|
return $this->renderJson($data);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function sessionPath() : string
|
||||||
|
{
|
||||||
|
return rtrim(ini_get("session.save_path"), DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Controller;
|
||||||
|
|
||||||
|
use League\Route\Router;
|
||||||
|
use Picea\FileFetcher;
|
||||||
|
use Picea\Picea;
|
||||||
|
use Psr\Http\Message\{ ResponseInterface, ServerRequestInterface };
|
||||||
|
|
||||||
|
use Notes\Tell\Attribute\Language, Notes\Route\Attribute\Method\Route;
|
||||||
|
|
||||||
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Picea\Extension\UrlExtension;
|
||||||
|
|
||||||
|
class Templating extends Console {
|
||||||
|
use Lib\ConsoleControllerTrait;
|
||||||
|
|
||||||
|
#[Route(route: "/templating/picea", name: "lean.console:templating.picea")]
|
||||||
|
public function picea(ServerRequestInterface $request, array $arguments) : ResponseInterface
|
||||||
|
{
|
||||||
|
$picea = $this->container->has(Picea::class) ? $this->container->get(Picea::class) : false;
|
||||||
|
|
||||||
|
$list = $picea->fileFetcher->getFileList();
|
||||||
|
|
||||||
|
return $this->renderView("lean-console/page/templating/picea", get_defined_vars());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Entity\Mysql;
|
||||||
|
|
||||||
|
use Ulmus\Common\EntityField;
|
||||||
|
use Ulmus\Entity\Field\Datetime,
|
||||||
|
Ulmus\Entity\InformationSchema;
|
||||||
|
use Ulmus\EntityCollection;
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
|
||||||
|
use Ulmus\Attribute\Obj\Table;
|
||||||
|
|
||||||
|
#[Table(name: "columns", database: "information_schema")] # migrated from: '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,42 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Entity\Mysql;
|
||||||
|
|
||||||
|
use Ulmus\Common\EntityField;
|
||||||
|
use Ulmus\Entity\Field\Datetime,
|
||||||
|
Ulmus\Entity\Sqlite;
|
||||||
|
use Ulmus\EntityCollection;
|
||||||
|
use Ulmus\Migration\FieldDefinition;
|
||||||
|
|
||||||
|
use Ulmus\Attribute\Obj\Table;
|
||||||
|
|
||||||
|
#[Table(name: "columns", database: "information_schema")]
|
||||||
|
class Column extends Sqlite
|
||||||
|
{
|
||||||
|
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,67 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Form\Caching;
|
||||||
|
|
||||||
|
use Picea\Ui\Method\{ FormInterface, FormContext, FormContextInterface };
|
||||||
|
|
||||||
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Picea\{Caching\Opcache, Compiler\Context };
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Ulmus\Common\EntityResolver;
|
||||||
|
use \Ulmus\Entity\InformationSchema\Table;
|
||||||
|
|
||||||
|
use RecursiveIteratorIterator, RecursiveDirectoryIterator;
|
||||||
|
|
||||||
|
class Picea implements FormInterface
|
||||||
|
{
|
||||||
|
|
||||||
|
public \Picea\Picea $picea;
|
||||||
|
|
||||||
|
public array $folders;
|
||||||
|
|
||||||
|
public function __construct(\Picea\Picea $picea, array &$folders)
|
||||||
|
{
|
||||||
|
$this->folders = &$folders;
|
||||||
|
$this->picea = $picea;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initialize(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
if ($this->picea->cache instanceof Opcache) {
|
||||||
|
$path = $this->picea->cache->cachePath() . "/";
|
||||||
|
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($path, RecursiveDirectoryIterator::SKIP_DOTS), RecursiveIteratorIterator::SELF_FIRST, RecursiveIteratorIterator::CATCH_GET_CHILD);
|
||||||
|
|
||||||
|
foreach ($iterator as $file) {
|
||||||
|
if ($file->isFile() && in_array($file->getExtension(), [ 'php' ])) {
|
||||||
|
$this->folders[$path][] = $file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(FormContextInterface $context) : bool
|
||||||
|
{
|
||||||
|
return $context->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
$deleted = $failed = 0;
|
||||||
|
|
||||||
|
foreach($this->folders as $path => $files) {
|
||||||
|
foreach($files as $file)
|
||||||
|
{
|
||||||
|
unlink($file->getPathname()) ? $deleted++ : $failed++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($deleted) {
|
||||||
|
# $context->pushMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($failed) {
|
||||||
|
# $context->pushMessage();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,122 +0,0 @@
|
|||||||
<?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\Common\EntityResolver;
|
|
||||||
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) {
|
|
||||||
$adapter = $entity::resolveEntity()->sqlAdapter()->adapter();
|
|
||||||
|
|
||||||
$tableName = $table->tableName();
|
|
||||||
$databaseName = $table->databaseName();
|
|
||||||
|
|
||||||
if ( ! $tableName || ! $databaseName ) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
#<<<<<<< HEAD
|
|
||||||
$tableEntity = $adapter->schemaTable($databaseName, $tableName);
|
|
||||||
|
|
||||||
if ( $tableEntity ) {
|
|
||||||
#$fields = $entiy::resolveEntity()->fieldList();
|
|
||||||
|
|
||||||
foreach($tableEntity->columns as $col) {
|
|
||||||
//dump( $entity::field($col->name) );
|
|
||||||
#=======
|
|
||||||
# $table = Table::repository()
|
|
||||||
# ->where(Table::field('name'), $table->tableName())
|
|
||||||
# ->where(Table::field('schema'), $table->databaseName())
|
|
||||||
# ->loadOne();
|
|
||||||
|
|
||||||
# if ( $table ) {
|
|
||||||
# $fields = $entity::resolveEntity()->fieldList(EntityResolver::KEY_COLUMN_NAME, true);
|
|
||||||
|
|
||||||
# $alter = [];
|
|
||||||
|
|
||||||
# foreach($fields as $field => $definition) {
|
|
||||||
# if ( $table->columns->filtersCollection(fn($e) => $e->name === $field)->count() === 0 ) {
|
|
||||||
# $alter[$field] = $definition;
|
|
||||||
# }
|
|
||||||
#>>>>>>> 7194a33bec884d745e838c8ac2693b353e95a3ce
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( $alter ) {
|
|
||||||
$context->status[$entity] = [
|
|
||||||
'msg' => "alter",
|
|
||||||
"query" => $entity::repository()->alterSqlQuery($alter)->getSqlQuery(true),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
# 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
|
|
||||||
{
|
|
||||||
if ( $context->create ?? false ) {
|
|
||||||
$context->create::repository()->createTable();
|
|
||||||
}
|
|
||||||
elseif ( $context->createAll ?? false ) {
|
|
||||||
foreach(explode(',', $context->createAll) as $entity) {
|
|
||||||
$entity::repository()->createTable();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
elseif ( $context->alter ?? false ) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->initialize($context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getContext(ServerRequestInterface $request) : FormContextInterface
|
|
||||||
{
|
|
||||||
return new class($request) extends FormContext {
|
|
||||||
|
|
||||||
public array $status = [];
|
|
||||||
|
|
||||||
public array $actions = [];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Form\Debugging;
|
||||||
|
|
||||||
|
use Picea\Ui\Method\{ FormInterface, FormContext, FormContextInterface };
|
||||||
|
|
||||||
|
use \Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Picea\{Caching\Opcache, Compiler\Context };
|
||||||
|
use Psr\Http\Message\ServerRequestInterface;
|
||||||
|
use Ulmus\Common\EntityResolver;
|
||||||
|
use \Ulmus\Entity\InformationSchema\Table;
|
||||||
|
|
||||||
|
use RecursiveIteratorIterator, RecursiveDirectoryIterator;
|
||||||
|
|
||||||
|
class Logs 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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?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 Import implements FormInterface
|
||||||
|
{
|
||||||
|
protected ? Lib\DatabaseMigrations $migration;
|
||||||
|
|
||||||
|
protected array $connections;
|
||||||
|
|
||||||
|
public function __construct(Lib\DatabaseMigrations $migration, array $connections)
|
||||||
|
{
|
||||||
|
$this->migration = $migration;
|
||||||
|
$this->connections = $connections;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initialize(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
$context->sourceTables ??= new EntityCollection();
|
||||||
|
$context->destinationTables ??= new EntityCollection();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(FormContextInterface $context) : bool
|
||||||
|
{
|
||||||
|
if ($context->source) {
|
||||||
|
$filtered = array_filter($this->migration->entities, fn($e, $key) => $key::repository()->adapter->name === $context->source, ARRAY_FILTER_USE_BOTH);
|
||||||
|
$context->sourceTables->replaceWith($filtered);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $context->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
if ($context->copy) {
|
||||||
|
foreach (array_filter($context->copy) as $dest => $source) {
|
||||||
|
foreach($source::repository()->yield() as $src) {
|
||||||
|
$dest::repository()->save( $src->toArray(), null, true );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function getContext(ServerRequestInterface $request, ? string $formName = null) : FormContextInterface
|
||||||
|
{
|
||||||
|
return new class($request, $formName) extends FormContext {
|
||||||
|
|
||||||
|
public EntityCollection $sourceTables;
|
||||||
|
|
||||||
|
public EntityCollection $destinationTables;
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
<?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\{Attribute\Property\Field, Entity\EntityInterface, Entity\Field\Datetime, EntityCollection};
|
||||||
|
|
||||||
|
class Insert implements FormInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
protected EntityInterface $entity
|
||||||
|
) { }
|
||||||
|
|
||||||
|
public function initialize(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(FormContextInterface $context) : bool
|
||||||
|
{
|
||||||
|
|
||||||
|
return $context->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
foreach ($this->entity::resolveEntity()->fieldList() as $field) {
|
||||||
|
$type = $field->getTypes()[0];
|
||||||
|
$value = $context->{$field->name};
|
||||||
|
|
||||||
|
if (! $field->getAttribute(Field::class)->object->readonly) {
|
||||||
|
if ($type->isEnum() && $value) {
|
||||||
|
$this->entity->{$field->name} = $type->type::from($value);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$this->entity->{$field->name} = $value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Temp patch while fixing default value in sqlite
|
||||||
|
if (property_exists($this->entity, 'createdAt')) {
|
||||||
|
$this->entity->createdAt = new Datetime();
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->entity::repository()->save($this->entity);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
use Ulmus\Ulmus;
|
||||||
|
|
||||||
|
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) {
|
||||||
|
|
||||||
|
if ( isset($definition->value) ) {
|
||||||
|
$definition->value = $entity::repository()->adapter->adapter()->writableValue($definition->value);
|
||||||
|
}
|
||||||
|
|
||||||
|
$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";
|
||||||
|
}
|
||||||
|
elseif ( ! $column->matchFieldDefinition($definition) ) {
|
||||||
|
$def->action = "change";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($def->action && $adapter->supportAlterColumnAction($def->action)) {
|
||||||
|
$def->modifier = new Lib\Database\Modifier(
|
||||||
|
type: Lib\Database\ModifierTypeEnum::Alter,
|
||||||
|
query: $entity::repository()
|
||||||
|
->alterSqlQuery([ $def->toArray() ])
|
||||||
|
->getSqlQuery(true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$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 = [];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Form\Update;
|
||||||
|
|
||||||
|
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 Git implements FormInterface
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public string $projectPath = "",
|
||||||
|
)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function initialize(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function validate(FormContextInterface $context) : bool
|
||||||
|
{
|
||||||
|
return $context->valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function execute(FormContextInterface $context) : void
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function run(string $command) : \Generator
|
||||||
|
{
|
||||||
|
$command = escapeshellcmd($command);
|
||||||
|
|
||||||
|
$handle = popen("$command", 'r');
|
||||||
|
|
||||||
|
while ( false !== $output = fgets($handle, 1024) ){
|
||||||
|
yield trim($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
pclose($handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,8 +4,10 @@ namespace Lean\Console;
|
|||||||
|
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
|
#[\Deprecated]
|
||||||
abstract class Lean
|
abstract class Lean
|
||||||
{
|
{
|
||||||
|
#[\Deprecated]
|
||||||
public static function definitions() : array
|
public static function definitions() : array
|
||||||
{
|
{
|
||||||
return require(dirname(__DIR__) . "/meta/definitions/software.php");
|
return require(dirname(__DIR__) . "/meta/definitions/software.php");
|
||||||
|
|||||||
@@ -2,27 +2,37 @@
|
|||||||
|
|
||||||
namespace Lean\Console\Lib;
|
namespace Lean\Console\Lib;
|
||||||
|
|
||||||
|
use DI\Attribute\Inject;
|
||||||
|
use Notes\Attribute\Ignore;
|
||||||
use Psr\Container\ContainerInterface;
|
use Psr\Container\ContainerInterface;
|
||||||
|
|
||||||
use Storage\Session;
|
use Storage\Session;
|
||||||
|
|
||||||
|
use Lean\Console\Form;
|
||||||
|
|
||||||
|
use Notes\Security\Attribute\{ Security, Taxus };
|
||||||
|
|
||||||
use Picea;
|
use Picea;
|
||||||
|
|
||||||
/**
|
#[Security(locked: false)]
|
||||||
* @Language("lean.route")
|
#[Taxus("dev")]
|
||||||
* @RouteParam("methods" => [ 'GET', 'POST', 'DELETE' ], "base" => "/~")
|
#[\Notes\Route\Attribute\Object\Route(method: [ 'GET', 'POST' ] , base: "/~")]
|
||||||
* @Security('locked' => true)
|
|
||||||
* @Taxus("admin")
|
|
||||||
*/
|
|
||||||
trait ConsoleControllerTrait
|
trait ConsoleControllerTrait
|
||||||
{
|
{
|
||||||
use \Lean\ControllerTrait;
|
use \Lean\ControllerTrait;
|
||||||
|
|
||||||
|
#[Inject]
|
||||||
protected ContainerInterface $container;
|
protected ContainerInterface $container;
|
||||||
|
|
||||||
public function __construct(? Picea\Picea $picea, Session $session, ContainerInterface $container) {
|
#[Ignore]
|
||||||
$this->picea = $picea;
|
public function version() : string
|
||||||
$this->session = $session;
|
{
|
||||||
$this->container = $container;
|
$version = iterator_to_array(
|
||||||
|
new Form\Update\Git(getenv('PROJECT_PATH'))->run("/usr/bin/git describe --tags")
|
||||||
|
);
|
||||||
|
|
||||||
|
# dump($version);
|
||||||
|
|
||||||
|
return "1.5.0";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
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 null|Modifier|array $modifier = null,
|
||||||
|
public null|Definition $previous = null,
|
||||||
|
public null|string $action = null,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
public function toArray() : array
|
||||||
|
{
|
||||||
|
return array_filter(get_object_vars($this));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Lib\Database;
|
||||||
|
|
||||||
|
class DefinitionCollection extends \Ulmus\EntityCollection
|
||||||
|
{
|
||||||
|
public function filterType(ModifierTypeEnum $type) : self
|
||||||
|
{
|
||||||
|
return $this->filtersCollection(fn(Definition $e) => $e->modifier->type === $type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filterCreate() : self
|
||||||
|
{
|
||||||
|
return $this->filterType(ModifierTypeEnum::Create);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filterAlter() : self
|
||||||
|
{
|
||||||
|
return $this->filterType(ModifierTypeEnum::Alter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function filterDelete() : self
|
||||||
|
{
|
||||||
|
return $this->filterType(ModifierTypeEnum::Delete);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Lib\Database;
|
||||||
|
|
||||||
|
class Modifier
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ModifierTypeEnum $type,
|
||||||
|
public null|array|string $query = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Lib\Database;
|
||||||
|
|
||||||
|
enum ModifierTypeEnum: string
|
||||||
|
{
|
||||||
|
case Alter = 'alter';
|
||||||
|
case Create = 'create';
|
||||||
|
case Delete = 'delete';
|
||||||
|
case None = 'none';
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@
|
|||||||
|
|
||||||
namespace Lean\Console\Lib;
|
namespace Lean\Console\Lib;
|
||||||
|
|
||||||
|
use Ulmus\Adapter\SqlAdapterInterface;
|
||||||
|
|
||||||
class DatabaseMigrations
|
class DatabaseMigrations
|
||||||
{
|
{
|
||||||
public array $folderList;
|
public array $folderList;
|
||||||
@@ -20,14 +22,20 @@ class DatabaseMigrations
|
|||||||
foreach($this->folderList as $namespace => $folder) {
|
foreach($this->folderList as $namespace => $folder) {
|
||||||
foreach(static::files($folder) as $file) {
|
foreach(static::files($folder) as $file) {
|
||||||
$name = $file->getBasename("." . $file->getExtension());
|
$name = $file->getBasename("." . $file->getExtension());
|
||||||
$subNs = substr($file->getPath(), strlen($folder));
|
$subNs = ltrim(str_replace('/', '\\', substr($file->getPath(), strlen($folder))), '\\');
|
||||||
$entity = rtrim($namespace, "\\") . ( $subNs ? "\\$subNs" : "" ) . "\\{$name}";
|
$entity = rtrim($namespace, "\\") . ( $subNs ? "\\$subNs" : "" ) . "\\{$name}";
|
||||||
|
|
||||||
if ( ! method_exists($entity, 'resolveEntity') ) {
|
if ( ! method_exists($entity, 'resolveEntity') ) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->entities[$entity] = $entity::resolveEntity();
|
$resolve = $entity::resolveEntity();
|
||||||
|
|
||||||
|
if ( $resolve->sqlAdapter()->adapter() instanceof SqlAdapterInterface) {
|
||||||
|
$this->entities[$entity] = $resolve;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Lean\Console\Lib;
|
||||||
|
|
||||||
|
class FormContext extends \Picea\Ui\Method\FormContext { }
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
class Triggers
|
||||||
|
{
|
||||||
|
public function onUpdateCurrentTimestamp(string $table) : string
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +1,40 @@
|
|||||||
<nav id="main-nav">
|
<nav id="main-nav">
|
||||||
|
<div class="app-title">LEAN {{ $this->version() }}</div>
|
||||||
|
|
||||||
<label>{% lang "lean.nav.lean.label" %}</label>
|
<label>{% lang "lean.nav.lean.label" %}</label>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url('~') }}">{% lang "lean.nav.lean.dashboard" %}</a></li>
|
<li><a href="{% route 'lean.console:home' %}">{% lang "lean.nav.lean.dashboard" %}</a></li>
|
||||||
|
<li><a href="{% route 'lean.console:update' %}">{% lang "lean.nav.lean.update" %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<label>{% lang "lean.nav.request.label" %}</label>
|
<label>{% lang "lean.nav.request.label" %}</label>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url('~/request/routes') }}">{% lang "lean.nav.request.routes" %}</a></li>
|
<li><a href="{% route 'lean.console:request.route' %}">{% lang "lean.nav.request.routes" %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<label>{% lang "lean.nav.storage.label" %}</label>
|
<label>{% lang "lean.nav.storage.label" %}</label>
|
||||||
<ul>
|
<ul>
|
||||||
{#<li><a href="{{ url('~/storage') }}">{% lang "lean.nav.storage.summary" %}</a></li>#}
|
{#<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="{% route 'lean.console:storage.database' %}">{% lang "lean.nav.storage.database" %}</a></li>
|
||||||
<li><a href="{{ url('~/storage/session') }}">{% lang "lean.nav.storage.session" %}</a></li>
|
<li><a href="{% route 'lean.console:storage.session' %}">{% lang "lean.nav.storage.session" %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<label>{% lang "lean.nav.templating.label" %}</label>
|
<label>{% lang "lean.nav.templating.label" %}</label>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url('~/templating/picea') }}">{% lang "lean.nav.templating.picea" %}</a></li>
|
<li><a href="{% route 'lean.console:templating.picea' %}">{% lang "lean.nav.templating.picea" %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<label>{% lang "lean.nav.caching.label" %}</label>
|
<label>{% lang "lean.nav.caching.label" %}</label>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="{{ url('~/storage') }}">{% lang "lean.nav.templating.picea" %}</a></li>
|
<li><a href="{% route 'lean.console:caching' %}">{% lang "lean.nav.templating.picea" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<label>{% lang "lean.nav.debugging.label" %}</label>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{% route 'lean.console:debugging-logs' %}">{% lang "lean.nav.debugging.logs" %}</a></li>
|
||||||
|
</ul>
|
||||||
|
<ul>
|
||||||
|
<li><a href="{% route 'lean.console:debugging-phpinfo' %}">{% lang "lean.nav.debugging.phpinfo" %}</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
|
<hr>
|
||||||
@@ -10,29 +10,42 @@
|
|||||||
<meta name="theme-color" content="#ffffff">
|
<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" />
|
<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" />
|
||||||
|
<link rel="stylesheet" href='{% asset:path "lean-console/lean-console-bw.css" %}'>
|
||||||
|
|
||||||
<title>{{ title() }}</title>
|
<title>{{ title() }}</title>
|
||||||
|
|
||||||
<style>
|
|
||||||
{% include "lean-console/base/asset/lean.css" %}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{% section "head" %}{% endsection %}
|
{% section "head" %}{% endsection %}
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<header id="body-header">
|
|
||||||
{% section "header" %}{% endsection %}
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main id="body-main">
|
<main id="body-main">
|
||||||
{% section "nav" %}
|
{% section "nav" %}
|
||||||
{% view "lean-console/base/console/main-nav" %}
|
{% view "lean-console/base/console/main-nav" %}
|
||||||
{% endsection %}
|
{% endsection %}
|
||||||
|
|
||||||
|
<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 %}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<div id="subheader">
|
||||||
|
<h1>{% section "subheader" %}{% _ "page-title" %}{% endsection %}</h1>
|
||||||
|
{% section "breadcrumb" %}
|
||||||
|
<ul class="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">Console</li>
|
||||||
|
{% section "breadcrumb-items" %}{% endsection %}
|
||||||
|
</ul>
|
||||||
|
{% endsection %}
|
||||||
|
</div>
|
||||||
|
|
||||||
<section id="main-content">
|
<section id="main-content">
|
||||||
{% section "content" %}{% endsection %}
|
{% section "content" %}{% endsection %}
|
||||||
</section>
|
</section>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer id="body-footer">
|
<footer id="body-footer">
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.caching" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "breadcrumb-items" %}
|
||||||
|
<li class="breadcrumb-item">{% _ 'breadcrumb' %}</li>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
{% foreach $list as $path => $folder %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h2>{{ $path }}</h2>
|
||||||
|
|
||||||
|
{% ui:form.post "caching.picea" %}
|
||||||
|
<button class="btn-red" type="submit">{% _ 'clear' %}</button>
|
||||||
|
{% ui:endform %}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="picea">
|
||||||
|
{% foreach $folder as $file %}
|
||||||
|
{% php $import = include($file) %}
|
||||||
|
|
||||||
|
<div class="grid">
|
||||||
|
<strong class="col route-name">{{ substr($file, strlen($path)) }}</strong>
|
||||||
|
|
||||||
|
<div class="col">
|
||||||
|
{{ $import['namespace'] }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col">
|
||||||
|
{{ $import['view'] }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
{% endforeach %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
section > header {display:flex;justify-content: space-between}
|
||||||
|
.picea h5 {font-size:1.5em; line-height:2em; font-weight:bold;text-decoration:underline}
|
||||||
|
.picea strong.grid {background: #242528;color: #fff;}
|
||||||
|
.picea .grid {padding:0.66rem 0.3rem;align-items:center}
|
||||||
|
.picea .grid strong {color:#444}
|
||||||
|
.picea .grid:nth-child(even) {background: #e3e3e3 }
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
||||||
@@ -4,10 +4,19 @@
|
|||||||
|
|
||||||
{% title _("title") %}
|
{% title _("title") %}
|
||||||
|
|
||||||
{% section "header" %}
|
|
||||||
<div class="page-title">{% _ "page-title" %}</div>
|
|
||||||
{% endsection %}
|
|
||||||
|
|
||||||
{% section "content" %}
|
{% section "content" %}
|
||||||
|
<section>
|
||||||
|
<article>Welcome into your Lean Console section. Select the appropriate menu item from the sidebar.</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section style="margin-top:1rem;">
|
||||||
|
<article>
|
||||||
|
<div>Firewall</div>
|
||||||
|
<br>
|
||||||
|
<b>@todo</b>
|
||||||
|
<u>latest 50 connections</u>
|
||||||
|
<u>banned users / IP !</u>
|
||||||
|
<u>fail2ban integration</u>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
{% endsection %}
|
{% endsection %}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.debugging" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h2>{{ $path }}</h2>
|
||||||
|
|
||||||
|
{% ui:form.get current_url() %}
|
||||||
|
<small>{% _ 'logs.line' %} {% ui:text 'line', get('line') ?? 100, [ 'onchange' => "this.closest('form').submit()" ] %}</small>
|
||||||
|
{% ui:select 'logfile', array_combine($files, $files), get('file') ?? $open, [ 'onchange' => "this.closest('form').submit()" ] %}
|
||||||
|
{% ui:endform %}
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="logs">
|
||||||
|
<div class="log-item">
|
||||||
|
{% foreach array_reverse($content) as $line %}
|
||||||
|
<div class="line">{{ $line }}</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
<style>
|
||||||
|
section > header {display:flex;justify-content: space-between}
|
||||||
|
.log-item {max-height: 60vh; overflow-y:auto}
|
||||||
|
.log-item .line {padding:0.5rem}
|
||||||
|
.log-item .line {background: #efefef}
|
||||||
|
.log-item .line:nth-child(even) {background: #ccc}
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.debugging" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "header" %}
|
||||||
|
<div class="page-title">{% _ "page-title" %}</div>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "breadcrumb-items" %}
|
||||||
|
<li class="breadcrumb-item">{% _ 'phpinfo.breadcrumb' %}</li>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<iframe src="data:text/html;base64,{{ base64_encode($phpinfo) }}" style="width:100%; height: calc(100vh - 112px - 8vh)">
|
||||||
|
|
||||||
|
</iframe>
|
||||||
|
</section>
|
||||||
|
{% endsection %}
|
||||||
@@ -4,34 +4,46 @@
|
|||||||
|
|
||||||
{% title _("title") %}
|
{% title _("title") %}
|
||||||
|
|
||||||
{% section "header" %}
|
{% section "breadcrumb-items" %}
|
||||||
<div class="page-title">{% _ "page-title" %}</div>
|
<li class="breadcrumb-item">{% _ 'route.breadcrumb' %}</li>
|
||||||
{% endsection %}
|
{% endsection %}
|
||||||
|
|
||||||
|
{% function routeHtml($route) %}
|
||||||
|
<div class="grid">
|
||||||
|
<strong class="col-2 route-name">{{ $route->name }}</strong>
|
||||||
|
<div class="col-3 route-uri">{{ $route->getRoute() }}</div>
|
||||||
|
<div class="col-2 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 "content" %}
|
||||||
<section>
|
<section>
|
||||||
<header>
|
<header>
|
||||||
<h1>{% _ 'route.header' %}</h1>
|
<h2>{% _ 'route.header' %}</h2>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<article class="routes">
|
<article class="routes">
|
||||||
{% if $routes %}
|
{% if $routes %}
|
||||||
<strong class="grid">
|
<strong class="grid">
|
||||||
<div class="col route-name">{% _ 'route.name' %}</div>
|
<div class="col-2 route-name">{% _ 'route.name' %}</div>
|
||||||
<div class="col route-uri">{% _ 'route.uri' %}</div>
|
<div class="col-3 route-uri">{% _ 'route.uri' %}</div>
|
||||||
<div class="col route-methods">{% _ 'route.methods' %}</div>
|
<div class="col-2 route-methods">{% _ 'route.methods' %}</div>
|
||||||
<div class="col controller-method">{% _ 'route.target' %}</div>
|
<div class="col controller-method">{% _ 'route.target' %}</div>
|
||||||
</strong>
|
</strong>
|
||||||
|
|
||||||
{% foreach $routes as $name => $route %}
|
{% foreach $routes as $route %}
|
||||||
<div class="grid">
|
{{ routeHtml($route) }}
|
||||||
<strong class="col route-name">{{ $name }}</strong>
|
|
||||||
<div class="col route-uri">{{ $route['route'] }}</div>
|
{% if $overridden = $routing->findOverriddenRoute($route) %}
|
||||||
<div class="col route-methods">{{ implode(', ', $route['routeMethods']) }}</div>
|
<div style="background:rgba(255,0,0,0.2); text-decoration:line-through">
|
||||||
<div class="col controller-method">
|
{% foreach $routing->findOverriddenRoute($route) as $overridden %}
|
||||||
<span class="class">{{ $route['class'] }}</span>::<span>{{ $route['classMethod'] }}</span>
|
{{ routeHtml($overridden) }}
|
||||||
</div>
|
{% endforeach %}
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
{% endforeach %}
|
{% endforeach %}
|
||||||
{% else %}
|
{% else %}
|
||||||
{% _ 'routeless' %}
|
{% _ 'routeless' %}
|
||||||
@@ -40,7 +52,7 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.routes strong.grid {background:#172842;color:#eeffee}
|
.routes strong.grid {background: #242528;color: #fff;}
|
||||||
.routes .grid {padding:0.66rem 0.3rem}
|
.routes .grid {padding:0.66rem 0.3rem}
|
||||||
.routes .grid strong {color:#444}
|
.routes .grid strong {color:#444}
|
||||||
.routes .grid:nth-child(even) {background: #e3e3e3 }
|
.routes .grid:nth-child(even) {background: #e3e3e3 }
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
|
{% use Lean\Console\Lib\Database\ModifierTypeEnum %}
|
||||||
|
|
||||||
{% extends "lean-console/base/layout" %}
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
{% language.set "lean.storage" %}
|
{% language.set "lean.storage" %}
|
||||||
|
|
||||||
{% title _("title") %}
|
{% title _("title") %}
|
||||||
|
|
||||||
{% section "header" %}
|
{% section "breadcrumb-items" %}
|
||||||
<div class="page-title">{% _ "page-title" %}</div>
|
<li class="breadcrumb-item">{% _ 'database.breadcrumb' %}</li>
|
||||||
{% endsection %}
|
{% endsection %}
|
||||||
|
|
||||||
{% section "content" %}
|
{% section "content" %}
|
||||||
<section>
|
|
||||||
<header>
|
|
||||||
<h1>{% _ 'database.header' %}</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<article class="databases">
|
|
||||||
{% if $connections %}
|
{% if $connections %}
|
||||||
|
{% foreach $connections as $connection %}
|
||||||
|
<section>
|
||||||
|
{% php $conf = $connection->getConfiguration(); %}
|
||||||
|
<article class="databases">
|
||||||
<strong class="grid db-grid">
|
<strong class="grid db-grid">
|
||||||
<div class="col db-connection">{% _ 'database.connection' %}</div>
|
<div class="col db-connection">{% _ 'database.connection' %}</div>
|
||||||
<div class="col db-adapter">{% _ 'database.adapter' %}</div>
|
<div class="col db-adapter">{% _ 'database.adapter' %}</div>
|
||||||
@@ -24,85 +24,99 @@
|
|||||||
<div class="col db-username">{% _ 'database.username' %}</div>
|
<div class="col db-username">{% _ 'database.username' %}</div>
|
||||||
</strong>
|
</strong>
|
||||||
|
|
||||||
{% foreach $connections as $connection %}
|
|
||||||
{% php $conf = $connection->getConfiguration(); %}
|
|
||||||
|
|
||||||
<div class="grid db-grid">
|
<div class="grid db-grid">
|
||||||
<div class="col db-connection">{{ $connection->name }}</div>
|
<div class="col db-connection">{{ $connection->name }}</div>
|
||||||
<div class="col db-adapter">{{ $conf['adapter'] }}</div>
|
<div class="col db-adapter">{{ $connection->adapter()::class }}</div>
|
||||||
<div class="col db-host">{{ $conf['host'] }}:{{ $conf['port'] }}</div>
|
<div class="col db-host">{{ $connection->adapter()->hostname ?? '-' }}:{{ $connection->adapter()->port ?? '-' }}</div>
|
||||||
<div class="col db-name">{{ $conf['database'] }}</div>
|
<div class="col db-name">{{ $connection->adapter()->database ?? $connection->adapter()->path ?? '-' }}</div>
|
||||||
<div class="col db-username">{{ $conf['username'] }}</div>
|
<div class="col db-username">{{ $connection->adapter()->username ?? '-' }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tables">
|
<div class="tables">
|
||||||
<strong class="grid table-item">
|
<strong class="grid table-item">
|
||||||
<div class="col">{% _ 'database.table.name' %}</div>
|
<div class="col col-4">{% _ 'database.table.name' %}</div>
|
||||||
<div class="col">{% _ 'database.table.table-fields' %}</div>
|
<div class="col col-2 text-center">{% _ 'database.table.table-fields' %}</div>
|
||||||
<div class="col col-grow-2">{% _ 'database.table.query' %}</div>
|
<div class="col col-3 text-center">{% _ 'database.table.query' %}</div>
|
||||||
<div class="col text-right">{% _ 'database.table.actions' %}</div>
|
<div class="col col-2 text-center">{% _ 'database.table.count' %}</div>
|
||||||
|
<div class="col col-1 text-center">{% _ 'database.table.actions' %}</div>
|
||||||
</strong>
|
</strong>
|
||||||
|
|
||||||
{% ui.form.post "database" %}
|
{% ui:form.post "database.migrate", current_url() %}
|
||||||
{% foreach array_filter($migrations->entities, fn($e) => $e->databaseAdapter() === $connection) as $entity => $item %}
|
{% foreach array_filter($migrations->entities, fn($e) => $e->databaseAdapter() === $connection) as $entity => $item %}
|
||||||
<div class="grid table-item align-items-center">
|
<div class="grid table-item align-items-center">
|
||||||
<div class="col"><span>📄</span> <span>{{ $item->tableName() }}</span></div>
|
<div class="col col-4"><span>📄</span> <span>{{ $item->tableName() }}</span></div>
|
||||||
<div class="col">{% _ "database.table.fields", [ 'count' => count( $item->fieldList() ) ] %}</div>
|
<div class="col col-2 text-center">{% _ "database.table.fields", [ 'count' => count( $item->fieldList() ) ] %}</div>
|
||||||
<div class="col col-grow-2">
|
<div class="col col-3 text-center">
|
||||||
{% if $context->status[$entity]['query'] %}
|
{% if $context->definition[$entity]['table']->modifier->query ?? false %}
|
||||||
<code>{{ $context->status[$entity]['query'] }}</code>
|
<code>{{= implode('<br><br>',(array) $context->definition[$entity]['table']->modifier->query) }}</code>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div>🗸 This table is up-to-date</div>
|
<div style="color:#abecab">✓ {% _ 'database.table.uptodate' %}</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col">
|
<div class="col col-2 text-center">
|
||||||
{% switch $context->status[$entity]['msg'] %}
|
{% if $context->definition[$entity]['table']->modifier->type !== ModifierTypeEnum::Create %}
|
||||||
{% case 'unexisting' %}
|
{{ $entity::repository()->count() }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col col-1 text-center">
|
||||||
|
{% switch $context->definition[$entity]['table']->modifier->type ?? false %}
|
||||||
|
{% case ModifierTypeEnum::Create %}
|
||||||
{% php $createAll[] = $entity %}
|
{% php $createAll[] = $entity %}
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<button name="create" value="{{$entity}}" class="btn-blue">🗸 {% _ 'database.table.create' %}</button>
|
<button name="create" value="{{$entity}}" class="btn-blue">✓ {% _ 'database.table.create' %}</button>
|
||||||
</div>
|
</div>
|
||||||
{% break %}
|
{% break %}
|
||||||
|
|
||||||
{% case 'altering' %}
|
{% case ModifierTypeEnum::Alter %}
|
||||||
{% php $alter[] = $entity %}
|
{% php $alterAll[] = $entity %}
|
||||||
|
|
||||||
<div class="text-right">
|
<div class="text-right">
|
||||||
<button name="create" value="{{$entity}}" class="btn-blue">🗸 {% _ 'database.table.alter' %}</button>
|
<button name="alter" value="{{$entity}}" class="btn-blue">✓ {% _ 'database.table.alter' %}</button>
|
||||||
</div>
|
</div>
|
||||||
{% break %}
|
{% break %}
|
||||||
{% endswitch %}
|
{% endswitch %}
|
||||||
|
|
||||||
|
<div class="text-right">
|
||||||
|
<a href="{% route 'lean.console:storage.database_insert', [ 'source' => $entity ] %}" class="btn-gray">{% _ 'database.table.add-column' %}</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endforeach %}
|
{% endforeach %}
|
||||||
|
|
||||||
{% if ($createAll ?? 0) > 1 %}
|
{% if ($createAll ?? 0) > 1 %}
|
||||||
<div class="text-right" style="padding:0.5rem 0">
|
<div class="text-right" style="padding:0.5rem 0">
|
||||||
<button name="createAll" value="{{ implode(',', $createAll) }}" class="btn-red">🗸 {% _ 'database.table.createAll' %}</button>
|
<button name="createAll" value="{{ implode(',', $createAll) }}" class="btn-red">✓ {% _ 'database.table.createAll' %}</button>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% ui.endform %}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endforeach %}
|
{% if ($alterAll ?? 0) > 1 %}
|
||||||
|
<div class="text-right" style="padding:0.5rem 0">
|
||||||
|
<button name="alterAll" value="{{ implode(',', $alterAll) }}" class="btn-red">✓ {% _ 'database.table.alterAll' %}</button>
|
||||||
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
{% ui:endform %}
|
||||||
|
</div>
|
||||||
</article>
|
</article>
|
||||||
</section>
|
</section>
|
||||||
|
{% endforeach %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.databases strong.grid {background:#172842;color:#fff}
|
.databases strong.grid {background: #888a91;color:#fff}
|
||||||
|
|
||||||
.databases .db-grid {padding:0.66rem 0.3rem}
|
.databases .db-grid {padding:0.66rem 0.3rem}
|
||||||
.databases .db-grid strong {color:#444}
|
.databases .db-grid strong {color:#444}
|
||||||
.databases .db-grid:nth-child(even) {background: #e3e3e3 }
|
.databases .db-grid:nth-child(even) {background: #e3e3e3;line-height: 1.5em;font-size: 1.3em;}
|
||||||
|
|
||||||
.databases .tables .table-item {padding:0.33rem 0;background:rgba(255,255,255,0.1)}
|
.databases .tables .table-item {padding:0.33rem 0;background:rgba(255,255,255,0.1);line-height: 1.8em;}
|
||||||
.databases .tables .table-item:nth-child(even) {background:rgba(255,255,255,0.2)}
|
.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}
|
.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: 4px 12px;}
|
.tables {background: #2d3137;margin: 0 -8px 0 -8px;color: #fff;padding: 2px 10px;}
|
||||||
.tables label {padding:10px 5px;display:block}
|
.tables label {padding:10px 5px;display:block}
|
||||||
|
section + section { margin-top:15px; }
|
||||||
</style>
|
</style>
|
||||||
{% endsection %}
|
{% endsection %}
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.storage" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
{% if $connections %}
|
||||||
|
{% ui:form.post "database.import" %}
|
||||||
|
<section>
|
||||||
|
<header>Import data from a connection into another</header>
|
||||||
|
|
||||||
|
<article class="databases">
|
||||||
|
{% if ! $context->source %}
|
||||||
|
{% php $select = array_combine(array_column($connections, 'name'), array_column($connections, 'name')) %}
|
||||||
|
|
||||||
|
<div class="db-grid">
|
||||||
|
Source connection: {% ui:select "source", $select %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="db-grid">
|
||||||
|
Destination connection: {% ui:select "destination", $select %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
{% ui:hidden 'source', $context->source %}
|
||||||
|
{% ui:hidden 'destination', $context->destination %}
|
||||||
|
|
||||||
|
<div class="db-grid">
|
||||||
|
COPY DATA FROM → TO:
|
||||||
|
{% php $dest = array_filter($migrations->entities, fn($e, $key) => $key::repository()->adapter->name === $context->destination, ARRAY_FILTER_USE_BOTH); %}
|
||||||
|
|
||||||
|
{% foreach $dest as $key => $value %}
|
||||||
|
<div class="db-grid">
|
||||||
|
<span>{% ui:select "copy[$key]", [ null => '' ] + $context->sourceTables->buildArray('entityClass', 'entityClass') %}</span>
|
||||||
|
<span>→</span>
|
||||||
|
<span>{{ sprintf('%s (%s)', $key, $value->tableName()) }}</span>
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</article>
|
||||||
|
|
||||||
|
<footer class="text-center">
|
||||||
|
<button type="submit" class="btn-blue">Copy</button>
|
||||||
|
<a href="{% route 'lean.console:storage.database' %}" class="btn-red">Cancel</a>
|
||||||
|
</footer>
|
||||||
|
</section>
|
||||||
|
{% ui:endform %}
|
||||||
|
{% else %}
|
||||||
|
No connection found
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.databases strong.grid {background:#181818;color:#fff}
|
||||||
|
|
||||||
|
.databases .db-grid {padding:0.66rem 0.3rem}
|
||||||
|
.databases .db-grid strong {color:#444}
|
||||||
|
.databases .db-grid:nth-child(even) {background: #eaeaea }
|
||||||
|
.databases .tables .table-item {padding:0.33rem 0;background:rgba(255,255,255,0.1);line-height: 1.8em;}
|
||||||
|
.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: #2d3137;margin: 0 -8px 0 -8px;color: #fff;padding: 2px 10px;}
|
||||||
|
.tables label {padding:10px 5px;display:block}
|
||||||
|
section + section { margin-top:15px; }
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
||||||
@@ -0,0 +1,117 @@
|
|||||||
|
{% use Ulmus\Attribute\Property\Field %}
|
||||||
|
{% use Lean\Console\Lib\Database\ModifierTypeEnum %}
|
||||||
|
|
||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.storage" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "breadcrumb-items" %}
|
||||||
|
<li class="breadcrumb-item"><a href="{% route 'lean.console:storage.database' %}">{% _ 'database.breadcrumb' %}</a></li>
|
||||||
|
<li class="breadcrumb-item">{% _ 'database_insert.breadcrumb' %}</li>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
<section class="insert">
|
||||||
|
<header class="bg-yellow">
|
||||||
|
<h2>{{ $class }}</h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article>
|
||||||
|
<div class="database_insert">
|
||||||
|
<div class="tables">
|
||||||
|
<strong class="grid table-item">
|
||||||
|
<div class="col">{% _ 'database_insert.table.column' %}</div>
|
||||||
|
<div class="col">{% _ 'database_insert.table.type' %}</div>
|
||||||
|
<div class="col text-center">{% _ 'database_insert.table.attributes' %}</div>
|
||||||
|
<div class="col col-grow-4 text-center">{% _ 'database_insert.table.value' %}</div>
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
{% ui:form.post "database.insert", current_url(get()) %}
|
||||||
|
{% foreach $class::resolveEntity()->fieldList() as $field %}
|
||||||
|
<div class="grid table-item align-items-center column-item">
|
||||||
|
<div class="col">
|
||||||
|
<span>{{ $field->name }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col ">
|
||||||
|
{% foreach $field->getTypes() as $type %}
|
||||||
|
<span title="{{ $type->type }}">{{ $type->isObject() ? substr($type->type, strrpos($type->type, '\\') + 1) : $type->type }}</span>
|
||||||
|
{% endforeach %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col attributes text-center">
|
||||||
|
{% foreach $field->attributes as $attribute %}
|
||||||
|
<span class="attribute" title="{% json.pretty.html $attribute->object %}">{{ $attribute->tag }}</span>
|
||||||
|
{% endforeach %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col col-grow-4">
|
||||||
|
{% foreach $field->getTypes() as $type %}
|
||||||
|
{% php $attr = $field->getAttribute(Field::class)->object->readonly ? [ 'disabled' => 'disabled', 'placeholder' => _('database_insert.readonly') ] : [] %}
|
||||||
|
|
||||||
|
{% if enum_exists($type->type) %}
|
||||||
|
{% php $enum = array_map(fn($e) => $e->value, $type->type::cases()) %}
|
||||||
|
|
||||||
|
{% if $type->nullable %}
|
||||||
|
{% php $enum = [ null => null ] + $enum %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% ui:select $field->name, array_combine($enum, $enum), $context->{$field->name}, $attr %}
|
||||||
|
{% else %}
|
||||||
|
{% ui:text $field->name, $context->{$field->name}, $attr %}
|
||||||
|
{% endif %}
|
||||||
|
{% endforeach %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{# <div class="col">{% _ "database.table.fields", [ 'count' => count( $item->fieldList() ) ] %}</div>
|
||||||
|
<div class="col">
|
||||||
|
{% 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">✓ {% _ 'database.table.uptodate' %}</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col">
|
||||||
|
</div> #}
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
|
||||||
|
<div class="grid table-item">
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col"></div>
|
||||||
|
<div class="col text-center"></div>
|
||||||
|
<div class="col col-grow-4 text-right py-2">
|
||||||
|
<button type="submit" class="btn-yellow">{% _ 'database_insert.add' %}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% ui:endform %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
#main-content .insert article {background: #6a6a6a;padding:10px;}
|
||||||
|
|
||||||
|
select, input:not([type="file"]):not([type="button"]) {display: block;width: 100%;height: calc(2rem + 2px);padding: .375rem .75rem;font-size: 1rem;line-height: 1.5;color: #495057;background-color: #fff;background-clip: padding-box;border: 1px solid #ced4da; border-radius: 0; transition: border-color .15s ease-in-out,box-shadow .15s ease-in-out;}
|
||||||
|
select:disabled, input[disabled] {filter: contrast(60%);}
|
||||||
|
.database_insert strong.grid {background: #888a91;color:#fff}
|
||||||
|
|
||||||
|
.database_insert .db-grid {padding:0.66rem 0.3rem}
|
||||||
|
.database_insert .db-grid strong {color:#444}
|
||||||
|
.database_insert .db-grid:nth-child(even) {background: #e3e3e3;line-height: 1.5em;font-size: 1.3em;}
|
||||||
|
|
||||||
|
.database_insert .tables {color:#fff}
|
||||||
|
.database_insert .tables .table-item {padding:0.33rem 0;background:rgba(255,255,255,0.1);line-height: 1.8em;}
|
||||||
|
.database_insert .tables .table-item:nth-child(even) {background:rgba(255,255,255,0.2)}
|
||||||
|
.database_insert .attribute {display: inline-block;padding: .25em .4em 0 .4em;font-size: 70%;font-weight: 700;line-height: 1.2rem;text-align: center;white-space: nowrap;vertical-align: baseline;border-radius: .25rem;color:#ffe300; border:1px solid #ffe300}
|
||||||
|
.database_insert summary {background: #172841;color:#fff;margin: 0 -8px 0 -8px;padding:7px 10px}
|
||||||
|
|
||||||
|
.tables {background: #2d3137; #fff;padding: 2px 10px;}
|
||||||
|
.tables label {padding:10px 5px;display:block}
|
||||||
|
section + section { margin-top:15px; }
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.storage" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "breadcrumb-items" %}
|
||||||
|
<li class="breadcrumb-item">{% _ 'session.breadcrumb' %}</li>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h2>{% _ 'session.header' %}</h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="sessions">
|
||||||
|
<strong class="grid">
|
||||||
|
<div class="col route-name">{% _ 'session.count', [ 'count' => count($sessions) ] %}</div>
|
||||||
|
</strong>
|
||||||
|
|
||||||
|
{% foreach $sessions as $session %}
|
||||||
|
<div class="grid">
|
||||||
|
<strong class="col route-name">{{ $session }}</strong>
|
||||||
|
<div class="col">{{ date('Y-m-d H:i:s', filemtime(realpath($path . DIRECTORY_SEPARATOR . $session))) }}</div>
|
||||||
|
<div class="col text-right">
|
||||||
|
<a target="_blank" class="btn-red" href="{% route 'lean.console:storage.session_content', [ 'hash' => $session ] %}">
|
||||||
|
Voir
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.sessions strong.grid {background: #242528;color: #fff;}
|
||||||
|
.sessions .grid {padding:0.66rem 0.3rem;align-items:center;justify-content:space-between;}
|
||||||
|
.sessions .grid strong {color:#444}
|
||||||
|
.sessions .grid:nth-child(even) {background: #e3e3e3 }
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.templating" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
{% section "breadcrumb-items" %}
|
||||||
|
<li class="breadcrumb-item">{% _ 'breadcrumb' %}</li>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
{% foreach $list as $path => $folder %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h2>{{ $path }}</h2>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="picea">
|
||||||
|
{% foreach $folder as $file %}
|
||||||
|
<div class="grid">
|
||||||
|
<strong class="col route-name">{{ substr($file, strlen($path)) }}</strong>
|
||||||
|
<div>
|
||||||
|
{#<a target="_blank" class="btn-red" href="">
|
||||||
|
Voir
|
||||||
|
</a>#}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</article>
|
||||||
|
</section>
|
||||||
|
{% endforeach %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.picea h5 {font-size:1.5em; line-height:2em; font-weight:bold;text-decoration:underline}
|
||||||
|
.picea strong.grid {background: #242528;color: #fff;}
|
||||||
|
.picea .grid {padding:0.66rem 0.3rem;align-items:center}
|
||||||
|
.picea .grid strong {color:#444}
|
||||||
|
.picea .grid:nth-child(even) {background: #e3e3e3 }
|
||||||
|
section + section {margin-top:1.2rem}
|
||||||
|
</style>
|
||||||
|
{% endsection %}
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
{% extends "lean-console/base/layout" %}
|
||||||
|
|
||||||
|
{% language.set "lean.update" %}
|
||||||
|
|
||||||
|
{% title _("title") %}
|
||||||
|
|
||||||
|
|
||||||
|
{% function setStatusModifierClass($line) : string %}
|
||||||
|
{% return match(substr($line, 0, 2)) {
|
||||||
|
'??' => "action-add",
|
||||||
|
default => false,
|
||||||
|
} ?: match(substr($line, 0, 1)) {
|
||||||
|
'M' => "action-delete",
|
||||||
|
default => "",
|
||||||
|
}%}
|
||||||
|
{% endfunction %}
|
||||||
|
|
||||||
|
{% function setDiffModifierClass($line) : string %}
|
||||||
|
{% return match(substr($line, 0, 2)) {
|
||||||
|
'--' => "action-delete",
|
||||||
|
'++' => "action-add",
|
||||||
|
'@@' => "action-group",
|
||||||
|
default => false,
|
||||||
|
} ?: match(substr($line, 0, 1)) {
|
||||||
|
'-' => "action-delete",
|
||||||
|
'+' => "action-add",
|
||||||
|
default => "",
|
||||||
|
}%}
|
||||||
|
{% endfunction %}
|
||||||
|
|
||||||
|
{% section "content" %}
|
||||||
|
<section>
|
||||||
|
<header>
|
||||||
|
<h1>{% _ 'git.header' %}</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<article class="updates">
|
||||||
|
<div class="git-status">
|
||||||
|
<strong style="display:block;margin-bottom:7px">'git status' output</strong>
|
||||||
|
|
||||||
|
<code style="white-space:normal;font-size:120%">
|
||||||
|
{% foreach $status as $line %}
|
||||||
|
<div class="{{ setStatusModifierClass($line) }}">
|
||||||
|
{% if $line %}
|
||||||
|
{{ $line }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="git-diff" style="margin-top:2rem">
|
||||||
|
<strong style="display:block;margin-bottom:7px">'git diff' output</strong>
|
||||||
|
|
||||||
|
<code style="white-space:normal;font-size:120%">
|
||||||
|
{% foreach $diff as $line %}
|
||||||
|
<div class="{{ setDiffModifierClass($line) }}">
|
||||||
|
{% if $line %}
|
||||||
|
{{ $line }}
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% endforeach %}
|
||||||
|
</code>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
<footer>
|
||||||
|
{{ $lastUpdate }}
|
||||||
|
</footer>
|
||||||
|
</section>
|
||||||
|
{% endsection %}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.action-delete {color:#f88}
|
||||||
|
.action-add {color: #88ff8a}
|
||||||
|
.action-group {color:#88bcff}
|
||||||
|
</style>
|
||||||
Reference in new issue
Block a user