Compare commits
10 Commits
2790105a7d
...
fe2ed9d789
Author | SHA1 | Date | |
---|---|---|---|
fe2ed9d789 | |||
64dad0aaf9 | |||
32d1e93e73 | |||
dd231b0c07 | |||
88114ae9f2 | |||
6a07e5cdde | |||
7489e999ef | |||
1a54003030 | |||
28c8e24847 | |||
b5b7befd34 |
20
app/themes/gestalt/assets/GestaltThemeAssets.php
Normal file
@ -0,0 +1,20 @@
|
||||
<?php
|
||||
|
||||
namespace app\themes\gestalt\assets;
|
||||
|
||||
use kernel\Assets;
|
||||
|
||||
class GestaltThemeAssets extends Assets
|
||||
{
|
||||
|
||||
protected function createCSS(): void
|
||||
{
|
||||
$this->registerCSS(slug: "main", resource: "/_next/static/css/0d3195690bab7456.css");
|
||||
}
|
||||
|
||||
protected function createJS()
|
||||
{
|
||||
$this->registerJS(slug: "webpack", resource: "/_next/static/chunks/webpack-079ef2e4659c5b2a.js");
|
||||
}
|
||||
|
||||
}
|
23
app/themes/gestalt/controllers/MainController.php
Normal file
@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace app\themes\gestalt\controllers;
|
||||
|
||||
use kernel\Controller;
|
||||
|
||||
class MainController extends Controller
|
||||
{
|
||||
protected function init(): void
|
||||
{
|
||||
parent::init();
|
||||
$this->cgView->viewPath = APP_DIR . "/themes/gestalt/views/main/";
|
||||
$this->cgView->layout = "main.php";
|
||||
$this->cgView->layoutPath = APP_DIR . "/themes/gestalt/views/layout/";
|
||||
$this->cgView->addVarToLayout("resources", "/resources/out");
|
||||
}
|
||||
|
||||
public function actionIndex(): void
|
||||
{
|
||||
$this->cgView->render("index.php");
|
||||
}
|
||||
|
||||
}
|
10
app/themes/gestalt/manifest.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "Gestalt",
|
||||
"slug": "gestalt",
|
||||
"version": "0.1",
|
||||
"author": "ItGuild",
|
||||
"preview": "preview.png",
|
||||
"description": "Gestalt theme",
|
||||
"resource_path": "{RESOURCES}/out",
|
||||
"routs": "routs/gestalt.php"
|
||||
}
|
13
app/themes/gestalt/routs/gestalt.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
use kernel\App;
|
||||
use kernel\CgRouteCollector;
|
||||
use Phroute\Phroute\RouteCollector;
|
||||
|
||||
|
||||
App::$collector->get('/', [\app\themes\gestalt\controllers\MainController::class, 'actionIndex']);
|
||||
//App::$collector->get('/page/{page_number}', [\app\modules\tag\controllers\TagController::class, 'actionIndex']);
|
||||
//App::$collector->get('/create', [\app\modules\tag\controllers\TagController::class, 'actionCreate']);
|
||||
|
||||
|
||||
|
136
app/themes/gestalt/views/layout/main.php
Normal file
224
app/themes/gestalt/views/main/index.php
Normal file
@ -0,0 +1,224 @@
|
||||
<?php
|
||||
/**
|
||||
* @var string $resources;
|
||||
* @var \kernel\CgView $view
|
||||
*/
|
||||
|
||||
$view->setTitle("Донецкое гештальт сообщество");
|
||||
$view->setMeta([
|
||||
'description' => 'Донецкое гештальт сообщество'
|
||||
]);
|
||||
?>
|
||||
<div class="flex flex-col container m-auto text-center text-dark gap-[31px]"><h1 class="text-[40px] uppercase">
|
||||
Донецкое гештальт сообщество</h1>
|
||||
<p class="text-dark text-[19px] max-w-[832px] mx-auto">это добровольное самоорганизующееся сообщество
|
||||
специалистов г. Донецка и Донецкого края в области психологического консультирования и гештальт-терапии.</p>
|
||||
</div>
|
||||
<div class="flex justify-center mt-[100px] gap-[14px] container mx-auto">
|
||||
<div class="relative bg-blue border-[1px] border-white rounded-[25px] pr-[48px] max-w-[650px] min-h-[480px] w-full font-[400]">
|
||||
<img alt="intro" loading="lazy" width="1" height="1" decoding="async" data-nimg="1"
|
||||
class="w-auto h-auto absolute" style="color:transparent" src="<?= $resources ?>/images/intro.svg"/>
|
||||
<h3 class="text-white text-[38px] mt-[214px] text-end leading-[41px]"><span
|
||||
class="bg-darkBlue px-[12px] py-[3px] rounded-[18px]">Цель</span> нашего<br/>объединения:</h3>
|
||||
<p class="ml-auto mt-[50px] text-start text-white text-[19px] leading-[20px] max-w-[400px] font-[700]">
|
||||
взаимное обогащение профессиональными знаниями, идеями и опытом на конференциях и семинарах, в учебных
|
||||
программах и на интенсивах, на специализациях и в супервизорских группах.</p></div>
|
||||
<div class="flex flex-col gap-[12px] max-w-[368px]">
|
||||
<div class="flex items-center bg-blue rounded-[25px] min-h-[234px] px-[68px] py-[60px] relative"><p
|
||||
class="text-white font-[500] leading-[23px] text-[20px]">Через собственное развитие мы развиваем и
|
||||
популяризируем гештальт-подход</p><img alt="palm" loading="lazy" width="1" height="1" decoding="async"
|
||||
data-nimg="1" class="w-auto h-auto absolute right-3 bottom-0"
|
||||
style="color:transparent" src="<?= $resources ?>/images/palm.svg"/></div>
|
||||
<div class="flex flex-col items-center rounded-[25px] min-h-[234px] px-[68px] pt-[40px] border-[4px] border-white">
|
||||
<div class="flex relative left-[-20px] bottom-[-10px]"><img alt="avatar" loading="lazy" width="101"
|
||||
height="100" decoding="async" data-nimg="1"
|
||||
class="undefined relative"
|
||||
style="color:transparent"
|
||||
srcSet="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=128&q=75 1x, <?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75 2x"
|
||||
src="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75"/><img
|
||||
alt="avatar" loading="lazy" width="101" height="100" decoding="async" data-nimg="1"
|
||||
class="right-[55px] z-2 relative" style="color:transparent"
|
||||
srcSet="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=128&q=75 1x, <?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75 2x"
|
||||
src="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75"/><img alt="avatar"
|
||||
loading="lazy"
|
||||
width="101" height="100"
|
||||
decoding="async"
|
||||
data-nimg="1"
|
||||
class="right-[105px] z-3 relative"
|
||||
style="color:transparent"
|
||||
srcSet="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=128&q=75 1x, <?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75 2x"
|
||||
src="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75"/><img
|
||||
alt="avatar" loading="lazy" width="101" height="100" decoding="async" data-nimg="1"
|
||||
class="right-[155px] z-4 relative" style="color:transparent"
|
||||
srcSet="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=128&q=75 1x, <?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75 2x"
|
||||
src="<?= $resources ?>/_next/image?url=%2Fimages%2Favatar.png&w=256&q=75"/></div>
|
||||
<p class="text-blue font-[900] text-[26px]">+ 145 учасников</p></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-[50px] flex gap-[64px] justify-center container mx-auto">
|
||||
<div class="flex-col flex gap-[35px] items-center"><img alt="oppgp" loading="lazy" width="140" height="37"
|
||||
decoding="async" data-nimg="1" style="color:transparent"
|
||||
src="<?= $resources ?>/images/oppgp.svg"/>
|
||||
<p class="text-grey max-w-[300px] text-[16px] leading-[17px] text-center font-[700]">Донецкое
|
||||
гештальт-сообщество является частью Всероссийского общества психологов практикующих гештальт-подход (ОПП
|
||||
ГП). </p></div>
|
||||
<div class="flex-col flex gap-[19px] items-center"><img alt="oppgp" loading="lazy" width="177" height="53"
|
||||
decoding="async" data-nimg="1" style="color:transparent"
|
||||
src="<?= $resources ?>/images/pmg.svg"/>
|
||||
<p class="text-grey max-w-[507px] text-[16px] leading-[17px] text-center font-[700]">В своей работе мы
|
||||
придерживаемся стандартов программы «Московский Гештальт Институт», а также стандартов Европейской
|
||||
Ассоциации Гештальт Терапии, Этического Кодекса Гештальт Терапевта и принципов гуманизма.</p></div>
|
||||
</div>
|
||||
<div class="flex flex-col mt-[100px]">
|
||||
<div class="flex items-center max-w-[1033px] mx-auto justify-between w-full mb-[50px]">
|
||||
<div class="undefined px-[25px] py-[10px] max-w-[225px] min-w-[180px] justify-center w-fit cursor-pointer border-blue border-[1px] flex gap-[10px] rounded-[10px]">
|
||||
<p class="text-blue font-[700] text-[16px]">Конференции</p><img alt="chevronDown" loading="lazy"
|
||||
width="11" height="8" decoding="async"
|
||||
data-nimg="1" style="color:transparent"
|
||||
src="<?= $resources ?>/images/chevronDown.svg"/></div>
|
||||
<h3 class="text-black text-[26px] uppercase">Мероприятия сообщества</h3>
|
||||
<button class="flex items-center justify-center whitespace-nowrap rounded-[6px] font-[400] bg-blue text-[16px] text-white max-h-[39px] px-[25px] py-[10px] undefined">
|
||||
Все мероприятия
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex justify-around"><a
|
||||
class="border-[1px] border-white rounded-[6px] bg-darkGrey px-[13.5px] pt-[12px] pb-[35px] text-black"
|
||||
href="events/event-1"><span class="flex w-[288px] h-[177px] bg-white"></span><h5
|
||||
class="max-w-[267px] font-[500] text-[16px] leading-[18px] mt-[30px] mb-[8px] line-clamp-3 text-ellipsis">
|
||||
добровольное самоорганизующееся сообщество специалистов ... добровольное самоорганизующееся сообщество
|
||||
специалистов ...</h5>
|
||||
<p class="max-w-[267px] text-[15px] leading-[17px] line-clamp-3 text-ellipsis">добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области...</p></a><a
|
||||
class="border-[1px] border-white rounded-[6px] bg-darkGrey px-[13.5px] pt-[12px] pb-[35px] text-black"
|
||||
href="events/event-1"><span class="flex w-[288px] h-[177px] bg-white"></span><h5
|
||||
class="max-w-[267px] font-[500] text-[16px] leading-[18px] mt-[30px] mb-[8px] line-clamp-3 text-ellipsis">
|
||||
добровольное самоорганизующееся сообщество специалистов ... добровольное самоорганизующееся сообщество
|
||||
специалистов ...</h5>
|
||||
<p class="max-w-[267px] text-[15px] leading-[17px] line-clamp-3 text-ellipsis">добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области...</p></a><a
|
||||
class="border-[1px] border-white rounded-[6px] bg-darkGrey px-[13.5px] pt-[12px] pb-[35px] text-black"
|
||||
href="events/event-1"><span class="flex w-[288px] h-[177px] bg-white"></span><h5
|
||||
class="max-w-[267px] font-[500] text-[16px] leading-[18px] mt-[30px] mb-[8px] line-clamp-3 text-ellipsis">
|
||||
добровольное самоорганизующееся сообщество специалистов ... добровольное самоорганизующееся сообщество
|
||||
специалистов ...</h5>
|
||||
<p class="max-w-[267px] text-[15px] leading-[17px] line-clamp-3 text-ellipsis">добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области...</p></a><a
|
||||
class="border-[1px] border-white rounded-[6px] bg-darkGrey px-[13.5px] pt-[12px] pb-[35px] text-black"
|
||||
href="events/event-1"><span class="flex w-[288px] h-[177px] bg-white"></span><h5
|
||||
class="max-w-[267px] font-[500] text-[16px] leading-[18px] mt-[30px] mb-[8px] line-clamp-3 text-ellipsis">
|
||||
добровольное самоорганизующееся сообщество специалистов ... добровольное самоорганизующееся сообщество
|
||||
специалистов ...</h5>
|
||||
<p class="max-w-[267px] text-[15px] leading-[17px] line-clamp-3 text-ellipsis">добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области...</p></a><a
|
||||
class="border-[1px] border-white rounded-[6px] bg-darkGrey px-[13.5px] pt-[12px] pb-[35px] text-black"
|
||||
href="events/event-1"><span class="flex w-[288px] h-[177px] bg-white"></span><h5
|
||||
class="max-w-[267px] font-[500] text-[16px] leading-[18px] mt-[30px] mb-[8px] line-clamp-3 text-ellipsis">
|
||||
добровольное самоорганизующееся сообщество специалистов ... добровольное самоорганизующееся сообщество
|
||||
специалистов ...</h5>
|
||||
<p class="max-w-[267px] text-[15px] leading-[17px] line-clamp-3 text-ellipsis">добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области добровольное
|
||||
самоорганизующееся сообщество специалистов г. Донецка и Донецкого края в области...</p></a></div>
|
||||
</div>
|
||||
<div class="flex flex-col mt-[90px] mb-[80px] gap-[56px]">
|
||||
<div class="flex items-center max-w-[1033px] mx-auto justify-between w-full">
|
||||
<div class="undefined px-[25px] py-[10px] max-w-[225px] min-w-[180px] justify-center w-fit cursor-pointer border-blue border-[1px] flex gap-[10px] rounded-[10px]">
|
||||
<p class="text-blue font-[700] text-[16px]">Тренер</p><img alt="chevronDown" loading="lazy" width="11"
|
||||
height="8" decoding="async" data-nimg="1"
|
||||
style="color:transparent"
|
||||
src="<?= $resources ?>/images/chevronDown.svg"/></div>
|
||||
<h3 class="text-black text-[26px] uppercase">наше сообщество</h3>
|
||||
<button class="flex items-center justify-center whitespace-nowrap rounded-[6px] font-[400] bg-blue text-[16px] text-white max-h-[39px] px-[25px] py-[10px] undefined">
|
||||
Все участники
|
||||
</button>
|
||||
</div>
|
||||
<div class="flex max-w-[1033px] m-auto justify-between w-full"><a
|
||||
class=" backdrop-blur-custom border-[1px] border-white rounded-[6px] bg-darkWhite p-[10px] text-black w-fit shadow-custom"
|
||||
href="/participants/1"><img alt="image" loading="lazy" width="221" height="221" decoding="async"
|
||||
data-nimg="1" class="rotate-[180deg]" style="color:transparent"
|
||||
src="<?= $resources ?>/images/mok_human.svg"/><h5
|
||||
class="text-[18px] font-[400] leading-[20px] max-w-[190px] mt-[16px] mb-[20px]">Лукашенко Марина
|
||||
Анатольевна</h5><span class="text-lightGrey">Работает с темами<p
|
||||
class="text-black text-[13px] leading-[15px] line-clamp-3 text-ellipsis max-w-[220px] mb-[16px] ">Финансовые изменения, болезнь, своя или близких, разрыв отношений, развод...</p></span>
|
||||
<div class="flex gap-[5px] max-w-[220px] flex-wrap ">
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Терапевт</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Супервизор</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер-стажер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ассоциированный тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ведущий тренер</span></div>
|
||||
</div>
|
||||
</a><a class=" backdrop-blur-custom border-[1px] border-white rounded-[6px] bg-darkWhite p-[10px] text-black w-fit shadow-custom"
|
||||
href="/participants/1"><img alt="image" loading="lazy" width="221" height="221" decoding="async"
|
||||
data-nimg="1" class="rotate-[180deg]" style="color:transparent"
|
||||
src="<?= $resources ?>/images/mok_human.svg"/><h5
|
||||
class="text-[18px] font-[400] leading-[20px] max-w-[190px] mt-[16px] mb-[20px]">Лукашенко Марина
|
||||
Анатольевна</h5><span class="text-lightGrey">Работает с темами<p
|
||||
class="text-black text-[13px] leading-[15px] line-clamp-3 text-ellipsis max-w-[220px] mb-[16px] ">Финансовые изменения, болезнь, своя или близких, разрыв отношений, развод...</p></span>
|
||||
<div class="flex gap-[5px] max-w-[220px] flex-wrap ">
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Терапевт</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Супервизор</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер-стажер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ассоциированный тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ведущий тренер</span></div>
|
||||
</div>
|
||||
</a><a class=" backdrop-blur-custom border-[1px] border-white rounded-[6px] bg-darkWhite p-[10px] text-black w-fit shadow-custom"
|
||||
href="/participants/1"><img alt="image" loading="lazy" width="221" height="221" decoding="async"
|
||||
data-nimg="1" class="rotate-[180deg]" style="color:transparent"
|
||||
src="<?= $resources ?>/images/mok_human.svg"/><h5
|
||||
class="text-[18px] font-[400] leading-[20px] max-w-[190px] mt-[16px] mb-[20px]">Лукашенко Марина
|
||||
Анатольевна</h5><span class="text-lightGrey">Работает с темами<p
|
||||
class="text-black text-[13px] leading-[15px] line-clamp-3 text-ellipsis max-w-[220px] mb-[16px] ">Финансовые изменения, болезнь, своя или близких, разрыв отношений, развод...</p></span>
|
||||
<div class="flex gap-[5px] max-w-[220px] flex-wrap ">
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Терапевт</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Супервизор</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер-стажер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ассоциированный тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ведущий тренер</span></div>
|
||||
</div>
|
||||
</a><a class=" backdrop-blur-custom border-[1px] border-white rounded-[6px] bg-darkWhite p-[10px] text-black w-fit shadow-custom"
|
||||
href="/participants/1"><img alt="image" loading="lazy" width="221" height="221" decoding="async"
|
||||
data-nimg="1" class="rotate-[180deg]" style="color:transparent"
|
||||
src="<?= $resources ?>/images/mok_human.svg"/><h5
|
||||
class="text-[18px] font-[400] leading-[20px] max-w-[190px] mt-[16px] mb-[20px]">Лукашенко Марина
|
||||
Анатольевна</h5><span class="text-lightGrey">Работает с темами<p
|
||||
class="text-black text-[13px] leading-[15px] line-clamp-3 text-ellipsis max-w-[220px] mb-[16px] ">Финансовые изменения, болезнь, своя или близких, разрыв отношений, развод...</p></span>
|
||||
<div class="flex gap-[5px] max-w-[220px] flex-wrap ">
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Терапевт</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Супервизор</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер-стажер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ассоциированный тренер</span></div>
|
||||
<div class="flex items-center justify-center font-[400] border-blue w-fit text-[12px] py-[4px] px-[8px] rounded-[3px] border-[0.5px] text-blue font-[700]">
|
||||
<span class="relative top-[2px]">Ведущий тренер</span></div>
|
||||
</div>
|
||||
</a></div>
|
||||
</div>
|
@ -7,6 +7,7 @@ namespace kernel;
|
||||
use kernel\helpers\Debug;
|
||||
use kernel\modules\user\models\User;
|
||||
use kernel\services\ModuleService;
|
||||
use kernel\services\ThemeService;
|
||||
use Phroute\Phroute\Dispatcher;
|
||||
|
||||
class App
|
||||
@ -24,6 +25,8 @@ class App
|
||||
|
||||
public ModuleService $moduleService;
|
||||
|
||||
public ThemeService $themeService;
|
||||
|
||||
public static Database $db;
|
||||
|
||||
public function run(): void
|
||||
@ -39,6 +42,7 @@ class App
|
||||
public function load(): static
|
||||
{
|
||||
$this->moduleService = new ModuleService();
|
||||
$this->themeService = new ThemeService();
|
||||
App::$collector = new CgRouteCollector();
|
||||
$this->setRouting();
|
||||
|
||||
@ -53,6 +57,10 @@ class App
|
||||
foreach ($modules_routs as $rout){
|
||||
include "$rout";
|
||||
}
|
||||
$activeTheme = getConst($this->themeService->getActiveTheme());
|
||||
if (!empty($activeTheme)){
|
||||
include $activeTheme . "/" . $this->themeService->getThemeRout($activeTheme);
|
||||
}
|
||||
}
|
||||
|
||||
public static function create(): App
|
||||
|
66
kernel/Assets.php
Normal file
@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace kernel;
|
||||
|
||||
class Assets
|
||||
{
|
||||
protected array $jsHeader = [];
|
||||
protected array $jsBody = [];
|
||||
|
||||
protected array $css = [];
|
||||
|
||||
protected string $resourceURI = "/resource";
|
||||
|
||||
public function __construct(string $resourceURI)
|
||||
{
|
||||
$this->setResourceURI($resourceURI);
|
||||
$this->createCSS();
|
||||
$this->createJS();
|
||||
}
|
||||
|
||||
protected function createCSS(){}
|
||||
protected function createJS(){}
|
||||
|
||||
public function setResourceURI(string $resourceURI): void
|
||||
{
|
||||
$this->resourceURI = $resourceURI;
|
||||
}
|
||||
|
||||
public function registerJS(string $slug, string $resource, bool $body = true, bool $addResourceURI = true): void
|
||||
{
|
||||
$resource = $addResourceURI ? $this->resourceURI . $resource : $resource;
|
||||
if ($body) {
|
||||
$this->jsBody[$slug] = $resource;
|
||||
} else {
|
||||
$this->jsHeader[$slug] = $resource;
|
||||
}
|
||||
}
|
||||
|
||||
public function registerCSS(string $slug, string $resource, bool $addResourceURI = true): void
|
||||
{
|
||||
$resource = $addResourceURI ? $this->resourceURI . $resource : $resource;
|
||||
$this->css[$slug] = $resource;
|
||||
}
|
||||
|
||||
public function getJSAsStr(bool $body = true): void
|
||||
{
|
||||
if ($body) {
|
||||
foreach ($this->jsBody as $key => $item){
|
||||
echo "<script src='$item'></script>";
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach ($this->jsHeader as $key => $item){
|
||||
echo "<script src='$item'></script>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getCSSAsSTR(): void
|
||||
{
|
||||
foreach ($this->css as $key => $item){
|
||||
echo "<link rel='stylesheet' href='$item'>";
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -2,6 +2,8 @@
|
||||
|
||||
namespace kernel;
|
||||
|
||||
use kernel\helpers\Debug;
|
||||
|
||||
class CgView
|
||||
{
|
||||
public string $viewPath = '';
|
||||
@ -61,6 +63,13 @@ class CgView
|
||||
private function createContent(string $viewFile, array $data = []): false|string
|
||||
{
|
||||
ob_start();
|
||||
|
||||
if ($this->varToLayout){
|
||||
foreach ($this->varToLayout as $key => $datum) {
|
||||
${"$key"} = $datum;
|
||||
}
|
||||
}
|
||||
|
||||
$view = $this;
|
||||
foreach ($data as $key => $datum) {
|
||||
${"$key"} = $datum;
|
||||
|
@ -36,7 +36,9 @@ class FileUpload
|
||||
$newFileName = md5(time() . $this->fileName) . '.' . $this->fileExtension;
|
||||
if (in_array($this->fileExtension, $this->allowedFileExtensions)) {
|
||||
$this->uploadDir = $uploadDir . mb_substr($newFileName, 0, 2) . '/' . mb_substr($newFileName, 2, 2) . '/';
|
||||
mkdir(ROOT_DIR . $this->uploadDir, 0777, true);
|
||||
$oldMask = umask(0);
|
||||
mkdir(ROOT_DIR . $this->uploadDir, 0775, true);
|
||||
umask($oldMask);
|
||||
$uploadFileDir = ROOT_DIR . $this->uploadDir;
|
||||
$this->destPath = $uploadFileDir . $newFileName;
|
||||
$this->uploadFile = $this->uploadDir . $newFileName;
|
||||
@ -49,7 +51,9 @@ class FileUpload
|
||||
} else {
|
||||
if (in_array($this->fileExtension, $this->allowedFileExtensions)) {
|
||||
$this->uploadDir = $uploadDir;
|
||||
mkdir(ROOT_DIR . $this->uploadDir, 0777, true);
|
||||
$oldMask = umask(0);
|
||||
mkdir(ROOT_DIR . $this->uploadDir, 0775, true);
|
||||
umask($oldMask);
|
||||
$uploadFileDir = ROOT_DIR . $this->uploadDir;
|
||||
$this->destPath = $uploadFileDir . $this->fileName;
|
||||
$this->uploadFile = $this->uploadDir . $this->fileName;
|
||||
|
@ -17,13 +17,32 @@ class RestController
|
||||
return [];
|
||||
}
|
||||
|
||||
protected function filters(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
#[NoReturn] public function actionIndex(): void
|
||||
{
|
||||
$request = new Request();
|
||||
$get = $request->get();
|
||||
$page = $request->get('page') ?? 1;
|
||||
$perPage = $request->get('per_page') ?? 10;
|
||||
$query = $this->model->query();
|
||||
|
||||
if ($this->filters()) {
|
||||
foreach ($this->filters() as $filter){
|
||||
if (key_exists($filter, $get)){
|
||||
if (is_numeric($get[$filter])){
|
||||
$query->where($filter, $get[$filter]);
|
||||
}
|
||||
elseif (is_string($get[$filter])){
|
||||
$query->where($filter,'like', '%' . $get[$filter] . '%');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($page > 1) {
|
||||
$query->skip(($page - 1) * $perPage)->take($perPage);
|
||||
} else {
|
||||
@ -117,5 +136,4 @@ class RestController
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
25
kernel/admin_themes/default/DefaultAdminThemeAssets.php
Normal file
@ -0,0 +1,25 @@
|
||||
<?php
|
||||
|
||||
namespace kernel\admin_themes\default;
|
||||
|
||||
use kernel\Assets;
|
||||
|
||||
class DefaultAdminThemeAssets extends Assets
|
||||
{
|
||||
|
||||
protected function createJS(): void
|
||||
{
|
||||
$this->registerJS(slug: "jquery", resource: "/js/jquery.min.js");
|
||||
$this->registerJS(slug: "popper", resource: "/js/popper.js");
|
||||
$this->registerJS(slug: "bootstrap", resource: "/js/bootstrap.min.js");
|
||||
$this->registerJS(slug: "main", resource: "/js/main.js");
|
||||
}
|
||||
|
||||
protected function createCSS()
|
||||
{
|
||||
$this->registerCSS(slug: "font-awesome", resource: "https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css", addResourceURI: false);
|
||||
$this->registerCSS(slug: "bootstrap", resource: "/css/bootstrap.min.css");
|
||||
$this->registerCSS(slug: "style", resource: "/css/style.css");
|
||||
}
|
||||
|
||||
}
|
@ -6,6 +6,7 @@
|
||||
* @var \kernel\CgView $view
|
||||
*/
|
||||
\Josantonius\Session\Facades\Session::start();
|
||||
$assets = new \kernel\admin_themes\default\DefaultAdminThemeAssets($resources)
|
||||
?>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
@ -17,19 +18,21 @@
|
||||
|
||||
<link href="https://fonts.googleapis.com/css?family=Poppins:300,400,500,600,700,800,900" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.6.0/css/all.min.css">
|
||||
<link rel="stylesheet" href="<?= $resources ?>/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="<?= $resources ?>/css/style.css">
|
||||
<?php $assets->getCSSAsSTR(); ?>
|
||||
<?php $assets->getJSAsStr(body: false); ?>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="wrapper d-flex align-items-stretch">
|
||||
<nav id="sidebar">
|
||||
<div class="p-4 pt-5">
|
||||
<a href="#" class="img logo rounded-circle mb-5"
|
||||
style="background-image: url(/resources/admin_theme/images/logo.jpg);"></a>
|
||||
<a href="<?= '/admin/user/profile' ?>" class="img logo rounded-circle mb-5"
|
||||
style="background-image: url(<?= \kernel\modules\user\service\UserService::getAuthUserPhoto() ?? '/resources/default_user_photo/noPhoto.png' ?>);">
|
||||
</a>
|
||||
<p>
|
||||
<a href="<?= '/admin/user/profile' ?>">
|
||||
<?= \kernel\modules\user\service\UserService::getAuthUsername() ?>
|
||||
</a>
|
||||
</p>
|
||||
<?php \kernel\widgets\MenuWidget::create()->run(); ?>
|
||||
<div class="footer">
|
||||
@ -89,9 +92,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="<?= $resources ?>/js/jquery.min.js"></script>
|
||||
<script src="<?= $resources ?>/js/popper.js"></script>
|
||||
<script src="<?= $resources ?>/js/bootstrap.min.js"></script>
|
||||
<script src="<?= $resources ?>/js/main.js"></script>
|
||||
<?php $assets->getJSAsStr(); ?>
|
||||
</body>
|
||||
</html>
|
@ -6,15 +6,16 @@ use itguild\forms\builders\SelectBuilder;
|
||||
use Itguild\Tables\Filter\Filter;
|
||||
use kernel\helpers\Debug;
|
||||
|
||||
class CustomSelectFilterForAssociativeArr extends Filter
|
||||
class BootstrapSelectFilter extends Filter
|
||||
{
|
||||
|
||||
public function fetch(): string
|
||||
{
|
||||
$select = SelectBuilder::build($this->name, [
|
||||
'class' => 'form-control',
|
||||
'options' => $this->param,
|
||||
'options' => $this->params['options'],
|
||||
'value' => $this->value,
|
||||
'prompt' => $this->params['prompt'] ?? null,
|
||||
]);
|
||||
|
||||
return "<td>" . $select->create()->fetch() . "</td>";
|
21
kernel/filters/BootstrapTextFilter.php
Normal file
@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace kernel\filters;
|
||||
|
||||
use itguild\forms\builders\TextInputBuilder;
|
||||
use Itguild\Tables\Filter\Filter;
|
||||
|
||||
class BootstrapTextFilter extends Filter
|
||||
{
|
||||
|
||||
public function fetch()
|
||||
{
|
||||
$textInput = TextInputBuilder::build($this->name, [
|
||||
'value' => $this->value,
|
||||
'class' => "form-control"
|
||||
]);
|
||||
|
||||
return "<td>" . $textInput->create()->fetch() . "</td>";
|
||||
|
||||
}
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace kernel\filters;
|
||||
|
||||
use Itguild\Tables\Filter\Filter;
|
||||
|
||||
class CustomSelectFilter extends Filter
|
||||
{
|
||||
|
||||
public function fetch()
|
||||
{
|
||||
$this->html = "<td><select class='form-control' name='$this->name'>";
|
||||
foreach ($this->param as $value) {
|
||||
if ($value === $this->value) {
|
||||
$this->html .= "<option value='$value' selected>$value</option>";
|
||||
} else {
|
||||
$this->html .= "<option value='$value'>$value</option>";
|
||||
}
|
||||
}
|
||||
$this->html .= "value='$this->value'</select></td>";
|
||||
return $this->html;
|
||||
}
|
||||
}
|
48
kernel/helpers/ImageGD.php
Normal file
@ -0,0 +1,48 @@
|
||||
<?php
|
||||
|
||||
namespace kernel\helpers;
|
||||
|
||||
class ImageGD
|
||||
{
|
||||
public \GdImage $img;
|
||||
|
||||
public function __construct(string $resource = '', int $width = 200, int $height = 200)
|
||||
{
|
||||
if ($resource){
|
||||
$this->img = imagecreatefrompng($resource);
|
||||
}
|
||||
else {
|
||||
$this->img = imagecreatetruecolor($width, $height);
|
||||
}
|
||||
imagesavealpha($this->img, true);
|
||||
}
|
||||
|
||||
public function addText(string $font_size, int $degree, int $x, int $y, string $color, string $font, string $text): void
|
||||
{
|
||||
$rgbArr = $this->hexToRgb($color);
|
||||
$color = imagecolorallocate($this->img, $rgbArr[0], $rgbArr[1], $rgbArr[2]);
|
||||
imagettftext($this->img, $font_size, $degree, $x, $y, $color, $font, $text);
|
||||
}
|
||||
|
||||
public function addImg(\GdImage $gdImage, int $location_x, int $location_y, int $offset_src_x, int $offset_src_y, int $src_width, int $src_height, int $no_transparent): void
|
||||
{
|
||||
imagecopymerge($this->img, $gdImage, $location_x, $location_y, $offset_src_x, $offset_src_y, $src_width, $src_height, $no_transparent);
|
||||
}
|
||||
|
||||
public function getImg()
|
||||
{
|
||||
return $this->img;
|
||||
}
|
||||
|
||||
public function save(string $path): void
|
||||
{
|
||||
imagepng($this->img, $path);
|
||||
imagedestroy($this->img);
|
||||
}
|
||||
|
||||
protected function hexToRgb(string $hex)
|
||||
{
|
||||
return sscanf($hex, "#%02x%02x%02x");
|
||||
}
|
||||
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Kernel",
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.4",
|
||||
"author": "ITGuild",
|
||||
"slug": "kernel",
|
||||
"type": "kernel",
|
||||
|
@ -19,12 +19,15 @@ $table = new ListEloquentTable(new EloquentDataProvider(Menu::class, [
|
||||
'baseUrl' => "/admin/settings/menu",
|
||||
]));
|
||||
$table->columns([
|
||||
'parent_id' => (function ($data) {
|
||||
'parent_id' => function ($data) {
|
||||
if ($data == 0) return null;
|
||||
return Menu::find($data)->label;
|
||||
}),
|
||||
},
|
||||
'icon_file' => function ($data) {
|
||||
return $data ? "<img src='$data' width='150px'>" : "";
|
||||
},
|
||||
'status' => function ($data) {
|
||||
return Menu::getStatus()[$data];
|
||||
}
|
||||
]);
|
||||
$table->beforePrint(function () {
|
||||
|
@ -5,6 +5,7 @@ namespace kernel\modules\module_shop_client\controllers;
|
||||
use GuzzleHttp\Client;
|
||||
use GuzzleHttp\Exception\GuzzleException;
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
use Josantonius\Session\Facades\Session;
|
||||
use kernel\AdminController;
|
||||
use kernel\Flash;
|
||||
use kernel\helpers\Debug;
|
||||
@ -162,18 +163,22 @@ class ModuleShopClientController extends AdminController
|
||||
$filters = $request->get();
|
||||
if ($this->moduleService->issetModuleShopToken()) {
|
||||
if ($this->moduleService->isServerAvailable()) {
|
||||
$modules_info = [];
|
||||
// $modules_info = [];
|
||||
$per_page = 8;
|
||||
$modules = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug');
|
||||
$modules = json_decode($modules->getBody()->getContents(), true);
|
||||
foreach ($modules as $module) {
|
||||
foreach ($filters as $key => $value) {
|
||||
$modules_info = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug');
|
||||
$modules_info = json_decode($modules_info->getBody()->getContents(), true);
|
||||
foreach ($modules_info as $key => $module) {
|
||||
foreach ($filters as $column => $value) {
|
||||
if ($value === '') continue;
|
||||
if ($module[$key] !== $value) {
|
||||
break;
|
||||
if (is_numeric($value)) {
|
||||
if ($module[$column] !== $value) {
|
||||
unset($modules_info[$key]);
|
||||
}
|
||||
} elseif (is_string($value)) {
|
||||
if (!str_contains($module[$column], $value)) {
|
||||
unset($modules_info[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$modules_info[] = $module;
|
||||
}
|
||||
}
|
||||
$module_count = count($modules_info);
|
||||
@ -187,6 +192,7 @@ class ModuleShopClientController extends AdminController
|
||||
'per_page' => $per_page,
|
||||
'kernelService' => new KernelService(),
|
||||
'adminThemeService' => new AdminThemeService(),
|
||||
'filterValues' => $filters
|
||||
]);
|
||||
} else {
|
||||
$this->cgView->render("module_shop_error_connection.php");
|
||||
@ -237,4 +243,56 @@ class ModuleShopClientController extends AdminController
|
||||
$this->cgView->render('module_shop_error_connection.php');
|
||||
}
|
||||
|
||||
#[NoReturn] public function actionAdminThemeInstall(): void
|
||||
{
|
||||
$request = new Request();
|
||||
$id = $request->get("id");
|
||||
$adminThemeInfo = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/install/' . $id);
|
||||
|
||||
$adminThemeInfo = json_decode($adminThemeInfo->getBody()->getContents(), true);
|
||||
Files::uploadByUrl($_ENV['MODULE_SHOP_URL'] . $adminThemeInfo['path_to_archive'], RESOURCES_DIR . "/tmp/admin_themes");
|
||||
if ($this->adminThemeService->install('/resources/tmp/admin_themes/' . basename($adminThemeInfo['path_to_archive']))) {
|
||||
Flash::setMessage("success", "Тема админ-панели успешно установлена.");
|
||||
} else {
|
||||
Session::start();
|
||||
Session::set("error", implode(";", $this->adminThemeService->getErrors()));
|
||||
}
|
||||
|
||||
$this->redirect('/admin/module_shop_client', 302);
|
||||
}
|
||||
|
||||
#[NoReturn] public function actionAdminThemeUpdate(): void
|
||||
{
|
||||
$request = new Request();
|
||||
$slug = $request->get("slug");
|
||||
$modules_info = RESTClient::request($_ENV['MODULE_SHOP_URL'] . '/api/module_shop/gb_slug');
|
||||
|
||||
$modules_info = json_decode($modules_info->getBody()->getContents(), true);
|
||||
foreach ($modules_info as $module) {
|
||||
if ($module['slug'] === $slug) {
|
||||
$path = $module['path_to_archive'];
|
||||
}
|
||||
}
|
||||
if (isset($path)) {
|
||||
Files::uploadByUrl($_ENV['MODULE_SHOP_URL'] . $path, RESOURCES_DIR . "/tmp/admin_themes");
|
||||
$this->adminThemeService->update('/resources/tmp/admin_themes/' . basename($path));
|
||||
Flash::setMessage("success", "Тема админ-панели успешно обновлена.");
|
||||
} else {
|
||||
Flash::setMessage("error", "Ошибка обновления темы админ-панели.");
|
||||
}
|
||||
|
||||
$this->redirect('/admin/module_shop_client', 302);
|
||||
}
|
||||
|
||||
#[NoReturn] public function actionAdminThemeDelete(): void
|
||||
{
|
||||
$request = new Request();
|
||||
$slug = $request->get("slug");
|
||||
$adminThemeInfo = $this->adminThemeService->getAdminThemeInfoBySlug($slug);
|
||||
$this->adminThemeService->uninstall($adminThemeInfo['path']);
|
||||
|
||||
Flash::setMessage("success", "Тема админ-панели успешно удалена.");
|
||||
$this->redirect('/admin/module_shop_client', 302);
|
||||
}
|
||||
|
||||
}
|
@ -24,7 +24,9 @@ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){
|
||||
});
|
||||
App::$collector->group(["prefix" => "admin_theme"], function (RouteCollector $router) {
|
||||
App::$collector->get('/install', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAdminThemeInstall']);
|
||||
App::$collector->post('/update', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAdminThemeUpdate']);
|
||||
App::$collector->get('/update', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAdminThemeUpdate']);
|
||||
App::$collector->get('/delete', [\kernel\modules\module_shop_client\controllers\ModuleShopClientController::class, 'actionAdminThemeDelete']);
|
||||
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -7,6 +7,7 @@
|
||||
* @var \kernel\services\ModuleService $moduleService
|
||||
* @var \kernel\services\KernelService $kernelService
|
||||
* @var \kernel\services\AdminThemeService $adminThemeService
|
||||
* @var array $filterValues
|
||||
*/
|
||||
|
||||
use Itguild\Tables\ListJsonTable;
|
||||
@ -42,9 +43,15 @@ $table->addAction(function ($row, $url) use ($moduleService) {
|
||||
$table->columns([
|
||||
'type' => [
|
||||
'filter' => [
|
||||
'class' => \kernel\filters\CustomSelectFilter::class,
|
||||
'param' => ['kernel', 'entity'],
|
||||
'value' => "kernel"
|
||||
'class' => \kernel\filters\BootstrapSelectFilter::class,
|
||||
'params' => [
|
||||
'options' => [
|
||||
'kernel' => 'kernel',
|
||||
'entity' => 'entity',
|
||||
],
|
||||
'prompt' => 'Не выбрано'
|
||||
],
|
||||
'value' => $filterValues['type'] ?? ''
|
||||
],
|
||||
]
|
||||
]);
|
||||
@ -97,7 +104,7 @@ $table->addAction(function ($row, $url) use ($adminThemeService) {
|
||||
$slug = $row['slug'];
|
||||
if ($adminThemeService->isInstall($slug)) {
|
||||
if (!$adminThemeService->isLastVersion($slug)) {
|
||||
$url = "$url/admin_theme/update/";
|
||||
$url = "$url/admin_theme/update/?slug=" . $row['slug'];
|
||||
|
||||
return \kernel\widgets\IconBtn\IconBtnUpdateWidget::create(['url' => $url])->run();
|
||||
}
|
||||
@ -107,6 +114,22 @@ $table->addAction(function ($row, $url) use ($adminThemeService) {
|
||||
return false;
|
||||
});
|
||||
|
||||
$table->addAction(function ($row, $url) use ($adminThemeService) {
|
||||
if ($row['type'] === 'admin_theme') {
|
||||
if ($adminThemeService->isInstall($row['slug'])) {
|
||||
$url = "$url/admin_theme/delete/?slug=" . $row['slug'];
|
||||
|
||||
return \kernel\widgets\IconBtn\IconBtnDeleteWidget::create(['url' => $url])->run();
|
||||
} else {
|
||||
$url = "$url/admin_theme/install/?id=" . $row['id'];
|
||||
|
||||
return \kernel\widgets\IconBtn\IconBtnInstallWidget::create(['url' => $url])->run();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
|
||||
$table->afterPrint(function () {
|
||||
return \kernel\IGTabel\btn\PrimaryBtn::create('Сбросить все фильтры', '/admin/module_shop_client')->fetch();
|
||||
});
|
||||
|
@ -23,11 +23,9 @@ $table = new ListEloquentTable(new EloquentDataProvider(Post::class, [
|
||||
'params' => ["class" => "table table-bordered", "border" => "2"],
|
||||
'baseUrl' => "/admin/post",
|
||||
'searchPrefix' => "",
|
||||
'searchParams' => $get
|
||||
'searchParams' => $get,
|
||||
]));
|
||||
|
||||
//\kernel\helpers\Debug::dd((new \kernel\Request())->get());
|
||||
|
||||
$view->setTitle("Список постов");
|
||||
$view->setMeta([
|
||||
'description' => 'Список постов системы'
|
||||
@ -47,13 +45,13 @@ foreach ($additionals as $additional) {
|
||||
$table->columns([
|
||||
'title' => [
|
||||
'filter' => [
|
||||
'class' => \Itguild\Tables\Filter\InputTextFilter::class,
|
||||
'class' => \kernel\filters\BootstrapTextFilter::class,
|
||||
'value' => $get['title'] ?? ''
|
||||
]
|
||||
],
|
||||
'content' => [
|
||||
'filter' => [
|
||||
'class' => \Itguild\Tables\Filter\InputTextFilter::class,
|
||||
'class' => \kernel\filters\BootstrapTextFilter::class,
|
||||
'value' => $get['content'] ?? ''
|
||||
]
|
||||
],
|
||||
@ -72,10 +70,13 @@ $table->columns([
|
||||
return User::find($data)->username;
|
||||
},
|
||||
'filter' => [
|
||||
'class' => \kernel\filters\CustomSelectFilterForAssociativeArr::class,
|
||||
'param' => \kernel\modules\user\service\UserService::createUsernameArr(),
|
||||
'value' => $get['user_id'] ?? ''
|
||||
]
|
||||
'class' => \kernel\filters\BootstrapSelectFilter::class,
|
||||
'params' => [
|
||||
'options' => \kernel\modules\user\service\UserService::createUsernameArr(),
|
||||
'prompt' => 'Не выбрано'
|
||||
],
|
||||
'value' => $get['user_id'] ?? '',
|
||||
],
|
||||
]
|
||||
]);
|
||||
|
||||
|
@ -13,21 +13,28 @@ use kernel\services\TokenService;
|
||||
class SecureService
|
||||
{
|
||||
|
||||
public static function createSecretCode(User $user): void
|
||||
public static function createSecretCode(User $user): SecretCode
|
||||
{
|
||||
$secretCode = new SecretCode();
|
||||
$secretCode->user_id = $user->id;
|
||||
$secretCode->code = mt_rand(100000, 999999);
|
||||
$secretCode->code_expires_at = date("Y-m-d H:i:s", strtotime("+5 minutes"));;
|
||||
$secretCode->save();
|
||||
|
||||
return $secretCode;
|
||||
}
|
||||
|
||||
public static function updateSecretCode(User $user): void
|
||||
public static function updateSecretCode(User $user): SecretCode
|
||||
{
|
||||
$secretCode = SecretCode::where('user_id', $user->id)->first();
|
||||
if(!$secretCode){
|
||||
return self::createSecretCode($user);
|
||||
}
|
||||
$secretCode->code = mt_rand(100000, 999999);
|
||||
$secretCode->code_expires_at = date("Y-m-d H:i:s", strtotime("+5 minutes"));;
|
||||
$secretCode->save();
|
||||
|
||||
return $secretCode;
|
||||
}
|
||||
|
||||
public static function getCodeByUserId(int $user_id)
|
||||
|
@ -6,6 +6,8 @@ use Exception;
|
||||
use JetBrains\PhpStorm\NoReturn;
|
||||
use kernel\AdminController;
|
||||
use kernel\EntityRelation;
|
||||
use kernel\FileUpload;
|
||||
use kernel\helpers\Debug;
|
||||
use kernel\modules\user\models\forms\CreateUserForm;
|
||||
use kernel\modules\user\models\User;
|
||||
use kernel\modules\user\service\UserService;
|
||||
@ -35,10 +37,17 @@ class UserController extends AdminController
|
||||
{
|
||||
$userForm = new CreateUserForm();
|
||||
$userForm->load($_REQUEST);
|
||||
|
||||
|
||||
if (isset($_FILES['user_photo']) && $_FILES['user_photo']['error'] === UPLOAD_ERR_OK) {
|
||||
$file = new FileUpload($_FILES['user_photo'], ['jpg', 'jpeg', 'png']);
|
||||
$file->upload();
|
||||
$userForm->setItem('user_photo', $file->getUploadFile());
|
||||
}
|
||||
|
||||
if ($userForm->validate()){
|
||||
$user = $this->userService->create($userForm);
|
||||
|
||||
|
||||
$entityRelation = new EntityRelation();
|
||||
$entityRelation->saveEntityRelation(entity: "user", model: $user, request: new Request());
|
||||
|
||||
@ -98,6 +107,13 @@ class UserController extends AdminController
|
||||
$userForm = new CreateUserForm();
|
||||
$userService = new UserService();
|
||||
$userForm->load($_REQUEST);
|
||||
|
||||
if (isset($_FILES['user_photo']) && $_FILES['user_photo']['error'] === UPLOAD_ERR_OK) {
|
||||
$file = new FileUpload($_FILES['user_photo'], ['jpg', 'jpeg', 'png']);
|
||||
$file->upload();
|
||||
$userForm->setItem('user_photo', $file->getUploadFile());
|
||||
}
|
||||
|
||||
if ($userForm->validateForUpdate()){
|
||||
$user = $userService->update($userForm, $user);
|
||||
|
||||
@ -128,4 +144,53 @@ class UserController extends AdminController
|
||||
$this->redirect("/admin/user/");
|
||||
}
|
||||
|
||||
public function actionProfile(): void
|
||||
{
|
||||
$user = UserService::getAuthUser();
|
||||
if (!$user){
|
||||
throw new Exception(message: "The user not found");
|
||||
}
|
||||
$this->cgView->render("view_profile.php", ['user' => $user]);
|
||||
}
|
||||
|
||||
public function actionProfileUpdate(): void
|
||||
{
|
||||
$model = UserService::getAuthUser();
|
||||
if (!$model){
|
||||
throw new Exception(message: "The user not found");
|
||||
}
|
||||
|
||||
$this->cgView->render("form_profile.php", ['model' => $model]);
|
||||
}
|
||||
|
||||
public function actionProfileEdit(): void
|
||||
{
|
||||
$user = UserService::getAuthUser();
|
||||
if (!$user){
|
||||
throw new Exception(message: "The user not found");
|
||||
}
|
||||
|
||||
$userForm = new CreateUserForm();
|
||||
$userService = new UserService();
|
||||
$userForm->load($_REQUEST);
|
||||
|
||||
if (isset($_FILES['user_photo']) && $_FILES['user_photo']['error'] === UPLOAD_ERR_OK) {
|
||||
$file = new FileUpload($_FILES['user_photo'], ['jpg', 'jpeg', 'png']);
|
||||
$file->upload();
|
||||
$userForm->setItem('user_photo', $file->getUploadFile());
|
||||
}
|
||||
|
||||
if ($userForm->validateForUpdate()){
|
||||
$user = $userService->update($userForm, $user);
|
||||
|
||||
$entityRelation = new EntityRelation();
|
||||
$entityRelation->saveEntityRelation(entity: "user", model: $user, request: new Request());
|
||||
|
||||
if ($user){
|
||||
$this->redirect("/admin/user/profile");
|
||||
}
|
||||
}
|
||||
$this->redirect("/admin/user/profile/update");
|
||||
}
|
||||
|
||||
}
|
@ -20,6 +20,7 @@ return new class extends Migration
|
||||
$table->string('username', 255)->nullable(false);
|
||||
$table->string('email', 255);
|
||||
$table->string('password_hash', 255);
|
||||
$table->string('user_photo', 255)->nullable();
|
||||
$table->integer('role')->default(1);
|
||||
$table->string('access_token', 255)->nullable(true);
|
||||
$table->dateTime('access_token_expires_at')->nullable(true);
|
||||
|
@ -7,6 +7,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property string $username
|
||||
* @property string $email
|
||||
* @property string $password_hash
|
||||
* @property string $user_photo
|
||||
* @property string $access_token
|
||||
* @property string $access_token_expires_at
|
||||
* @method static find($id)
|
||||
@ -17,7 +18,7 @@ class User extends Model {
|
||||
const ADMIN_USER_ROLE = 9;
|
||||
|
||||
protected $table = 'user';
|
||||
protected $fillable = ['username', 'email', 'password_hash', 'role', 'access_token', 'access_token_expires_at'];
|
||||
protected $fillable = ['username', 'email', 'password_hash', 'user_photo', 'role', 'access_token', 'access_token_expires_at'];
|
||||
protected array $dates = ['deleted at'];
|
||||
|
||||
public static function labels(): array
|
||||
@ -25,6 +26,7 @@ class User extends Model {
|
||||
return [
|
||||
'username' => 'Логин',
|
||||
'email' => 'Email',
|
||||
'user_photo' => 'Фото профиля',
|
||||
'created_at' => 'Создан',
|
||||
'updated_at' => 'Обновлен',
|
||||
];
|
||||
|
@ -12,7 +12,8 @@ class CreateUserForm extends FormModel
|
||||
return [
|
||||
'username' => 'required|min-str-len:5|max-str-len:30',
|
||||
'password' => 'required|min-str-len:5|max-str-len:30',
|
||||
'email' => 'required|email'
|
||||
'email' => 'required|email',
|
||||
'user_photo' => ''
|
||||
];
|
||||
}
|
||||
|
||||
@ -21,7 +22,9 @@ class CreateUserForm extends FormModel
|
||||
return [
|
||||
'username' => 'required|min-str-len:5|max-str-len:30',
|
||||
'password' => '',
|
||||
'email' => 'required|email'
|
||||
'email' => 'required|email',
|
||||
'user_photo' => ''
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -17,6 +17,11 @@ App::$collector->group(["prefix" => "admin"], function (RouteCollector $router){
|
||||
App::$collector->any('/update/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionUpdate']);
|
||||
App::$collector->any("/edit/{id}", [\kernel\modules\user\controllers\UserController::class, 'actionEdit']);
|
||||
App::$collector->get('/delete/{id}', [\kernel\modules\user\controllers\UserController::class, 'actionDelete']);
|
||||
App::$collector->group(["prefix" => "profile"], callback: function (RouteCollector $router) {
|
||||
App::$collector->get('/', [\kernel\modules\user\controllers\UserController::class, 'actionProfile']);
|
||||
App::$collector->get('/update', [\kernel\modules\user\controllers\UserController::class, 'actionProfileUpdate']);
|
||||
App::$collector->any('/edit', [\kernel\modules\user\controllers\UserController::class, 'actionProfileEdit']);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@ -11,10 +11,15 @@ class UserService
|
||||
|
||||
public function create(FormModel $form_model): false|User
|
||||
{
|
||||
$model = User::where("username", $form_model->getItem('username'))->first();
|
||||
if ($model){
|
||||
return $model;
|
||||
}
|
||||
$model = new User();
|
||||
$model->username = $form_model->getItem('username');
|
||||
$model->email = $form_model->getItem('email');
|
||||
$model->password_hash = password_hash($form_model->getItem('password'), PASSWORD_DEFAULT);
|
||||
$model->user_photo = $form_model->getItem('user_photo');
|
||||
if ($model->save()){
|
||||
return $model;
|
||||
}
|
||||
@ -29,6 +34,7 @@ class UserService
|
||||
if ($form_model->getItem('password')) {
|
||||
$user->password_hash = password_hash($form_model->getItem('password'), PASSWORD_DEFAULT);
|
||||
}
|
||||
$user->user_photo = $form_model->getItem('user_photo');
|
||||
if ($user->save()){
|
||||
return $user;
|
||||
}
|
||||
@ -80,6 +86,28 @@ class UserService
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function getAuthUserId(): string
|
||||
{
|
||||
$user = self::getAuthUser();
|
||||
if ($user){
|
||||
return $user->id;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function getAuthUserPhoto(): string|null
|
||||
{
|
||||
$user = self::getAuthUser();
|
||||
if ($user){
|
||||
if ($user->user_photo) {
|
||||
return $user->user_photo;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function getByAccessToken(string $token)
|
||||
{
|
||||
return $this->getByField("access_token", $token);
|
||||
|
@ -32,6 +32,16 @@ $form->field(class: \itguild\forms\inputs\TextInput::class, name: "email", param
|
||||
->setLabel("Email")
|
||||
->render();
|
||||
|
||||
if (!empty($model->user_photo)){
|
||||
echo "<div><img src='$model->user_photo' width='200px'></div>";
|
||||
}
|
||||
$form->field(class: \itguild\forms\inputs\File::class, name: "user_photo", params: [
|
||||
'class' => "form-control",
|
||||
'value' => $model->user_photo ?? ''
|
||||
])
|
||||
->setLabel("Фото профиля")
|
||||
->render();
|
||||
|
||||
$entityRelations = new \kernel\EntityRelation();
|
||||
if (!isset($model)) {
|
||||
$model = new User();
|
||||
|
74
kernel/modules/user/views/form_profile.php
Normal file
@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/**
|
||||
* @var User $model
|
||||
*/
|
||||
|
||||
use kernel\modules\user\models\User;
|
||||
|
||||
$form = new \itguild\forms\ActiveForm();
|
||||
$form->beginForm("/admin/user/profile/edit", enctype: 'multipart/form-data');
|
||||
|
||||
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "username", params: [
|
||||
'class' => "form-control",
|
||||
'placeholder' => 'Логин',
|
||||
'value' => $model->username ?? ''
|
||||
])
|
||||
->setLabel("Логин")
|
||||
->render();
|
||||
|
||||
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "password", params: [
|
||||
'class' => "form-control",
|
||||
'type' => "password",
|
||||
])
|
||||
->setLabel("Пароль")
|
||||
->render();
|
||||
|
||||
$form->field(class: \itguild\forms\inputs\TextInput::class, name: "email", params: [
|
||||
'class' => "form-control",
|
||||
'type' => "email",
|
||||
'placeholder' => 'test@mail.ru',
|
||||
'value' => $model->email ?? ''
|
||||
])
|
||||
->setLabel("Email")
|
||||
->render();
|
||||
|
||||
if (!empty($model->user_photo)){
|
||||
echo "<div><img src='$model->user_photo' width='200px'></div>";
|
||||
}
|
||||
$form->field(class: \itguild\forms\inputs\File::class, name: "user_photo", params: [
|
||||
'class' => "form-control",
|
||||
'value' => $model->user_photo ?? ''
|
||||
])
|
||||
->setLabel("Фото профиля")
|
||||
->render();
|
||||
|
||||
$entityRelations = new \kernel\EntityRelation();
|
||||
if (!isset($model)) {
|
||||
$model = new User();
|
||||
}
|
||||
$entityRelations->renderEntityAdditionalPropertyFormBySlug("user", $model);
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-sm-2">
|
||||
<?php
|
||||
$form->field(\itguild\forms\inputs\Button::class, name: "btn-submit", params: [
|
||||
'class' => "btn btn-primary ",
|
||||
'value' => 'Отправить',
|
||||
'typeInput' => 'submit'
|
||||
])
|
||||
->render();
|
||||
?>
|
||||
</div>
|
||||
<div class="col-sm-2">
|
||||
<?php
|
||||
$form->field(\itguild\forms\inputs\Button::class, name: "btn-reset", params: [
|
||||
'class' => "btn btn-warning",
|
||||
'value' => 'Сбросить',
|
||||
'typeInput' => 'reset'
|
||||
])
|
||||
->render();
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
$form->endForm();
|
@ -17,13 +17,15 @@ use kernel\widgets\IconBtn\IconBtnDeleteWidget;
|
||||
use kernel\widgets\IconBtn\IconBtnEditWidget;
|
||||
use kernel\widgets\IconBtn\IconBtnViewWidget;
|
||||
|
||||
$get = (new \kernel\Request())->get();
|
||||
|
||||
$table = new ListEloquentTable(new EloquentDataProvider(User::class, [
|
||||
'currentPage' => $page_number,
|
||||
'perPage' => 3,
|
||||
'params' => ["class" => "table table-bordered", "border" => "2"],
|
||||
'baseUrl' => "/admin/user",
|
||||
'filters' => ['email'],
|
||||
]));
|
||||
'searchPrefix' => "",
|
||||
'searchParams' => $get,]));
|
||||
|
||||
$entityRelation = new \kernel\EntityRelation();
|
||||
$additionals = $entityRelation->getEntityRelationsBySlug("user");
|
||||
@ -37,9 +39,13 @@ foreach ($additionals as $additional) {
|
||||
$table->columns([
|
||||
'username' => [
|
||||
"filter" => [
|
||||
'class' => \Itguild\Tables\Filter\InputTextFilter::class
|
||||
'class' => \kernel\filters\BootstrapTextFilter::class,
|
||||
'value' => $get['username'] ?? null,
|
||||
]
|
||||
],
|
||||
'user_photo' => function ($data) {
|
||||
return $data ? "<img src='$data' width='150px'>" : "";
|
||||
},
|
||||
'created_at' => function ($data) {
|
||||
if (!$data){
|
||||
return null;
|
||||
|
@ -35,6 +35,9 @@ foreach ($additionals as $key => $additional) {
|
||||
}
|
||||
|
||||
$table->rows([
|
||||
'user_photo' => function ($data) {
|
||||
return $data ? "<img src='$data' width='300px'>" : "";
|
||||
},
|
||||
'created_at' => function ($data) {
|
||||
if (!$data){
|
||||
return null;
|
||||
|
56
kernel/modules/user/views/view_profile.php
Normal file
@ -0,0 +1,56 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @var \Illuminate\Database\Eloquent\Collection $user
|
||||
*/
|
||||
|
||||
use kernel\modules\user\models\User;
|
||||
use Itguild\EloquentTable\ViewEloquentTable;
|
||||
use Itguild\EloquentTable\ViewJsonTableEloquentModel;
|
||||
use kernel\IGTabel\btn\DangerBtn;
|
||||
use kernel\IGTabel\btn\PrimaryBtn;
|
||||
use kernel\IGTabel\btn\SuccessBtn;
|
||||
use kernel\widgets\IconBtn\IconBtnDeleteWidget;
|
||||
use kernel\widgets\IconBtn\IconBtnEditWidget;
|
||||
use kernel\widgets\IconBtn\IconBtnListWidget;
|
||||
|
||||
$table = new ViewEloquentTable(new ViewJsonTableEloquentModel($user, [
|
||||
'params' => ["class" => "table table-bordered", "border" => "2"],
|
||||
'baseUrl' => "/admin/user",
|
||||
]));
|
||||
$table->beforePrint(function () use ($user) {
|
||||
$btn = IconBtnEditWidget::create(['url' => '/admin/user/profile/edit'])->run();
|
||||
$btn .= IconBtnDeleteWidget::create(['url' => '/admin/user/delete/' . $user->id])->run();
|
||||
return $btn;
|
||||
});
|
||||
|
||||
$entityRelation = new \kernel\EntityRelation();
|
||||
$additionals = $entityRelation->getEntityAdditionalProperty("user", $user);
|
||||
|
||||
foreach ($additionals as $key => $additional) {
|
||||
$table->addRow($key, function () use ($additional) {
|
||||
return $additional;
|
||||
}, ['after' => 'email']);
|
||||
}
|
||||
|
||||
$table->rows([
|
||||
'user_photo' => function ($data) {
|
||||
return $data ? "<img src='$data' width='300px'>" : "";
|
||||
},
|
||||
'created_at' => function ($data) {
|
||||
if (!$data){
|
||||
return null;
|
||||
}
|
||||
|
||||
return (new DateTimeImmutable($data))->format("d-m-Y");
|
||||
},
|
||||
'updated_at' => function ($data) {
|
||||
if (!$data){
|
||||
return null;
|
||||
}
|
||||
|
||||
return (new DateTimeImmutable($data))->format("d-m-Y");
|
||||
}
|
||||
]);
|
||||
$table->create();
|
||||
$table->render();
|
@ -82,12 +82,22 @@ class AdminThemeService
|
||||
return $info;
|
||||
}
|
||||
|
||||
public function getAdminThemeInfoBySlug(string $slug)
|
||||
public function getAdminThemeInfoBySlug(string $slug): false|array|string
|
||||
{
|
||||
// TODO
|
||||
$dirs = $this->getAdminThemeDirs();
|
||||
foreach ($dirs as $dir) {
|
||||
foreach (new DirectoryIterator($dir) as $fileInfo) {
|
||||
if ($fileInfo->isDot()) continue;
|
||||
if ($this->getAdminThemeInfo($fileInfo->getPathname())['slug'] === $slug) {
|
||||
return $this->getAdminThemeInfo($fileInfo->getPathname());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function isInstall(string $slug): bool
|
||||
return false;
|
||||
}
|
||||
|
||||
public function getAdminThemeDirs(): array
|
||||
{
|
||||
$adminThemePaths = Option::where("key", "admin_theme_paths")->first();
|
||||
$dirs = [];
|
||||
@ -97,6 +107,12 @@ class AdminThemeService
|
||||
$dirs[] = getConst($p);
|
||||
}
|
||||
}
|
||||
return $dirs;
|
||||
}
|
||||
|
||||
public function isInstall(string $slug): bool
|
||||
{
|
||||
$dirs = $this->getAdminThemeDirs();
|
||||
foreach ($dirs as $dir) {
|
||||
foreach (new DirectoryIterator($dir) as $fileInfo) {
|
||||
if ($fileInfo->isDot()) continue;
|
||||
@ -116,8 +132,7 @@ class AdminThemeService
|
||||
|
||||
$modulesInfo = json_decode($modulesInfo->getBody()->getContents(), true);
|
||||
|
||||
$themeInfo = $this->getAdminThemeInfo($slug);
|
||||
// Debug::dd($themeInfo);
|
||||
$themeInfo = $this->getAdminThemeInfoBySlug($slug);
|
||||
foreach ($modulesInfo as $mod) {
|
||||
if ($mod['slug'] === $themeInfo['slug'] && $mod['version'] === $themeInfo['version']) {
|
||||
return true;
|
||||
@ -195,11 +210,20 @@ class AdminThemeService
|
||||
$this->setActiveAdminTheme(KERNEL_ADMIN_THEMES_DIR . '/default');
|
||||
}
|
||||
$fileHelper = new Files();
|
||||
if (file_exists(ROOT_DIR . $path)) {
|
||||
$fileHelper->recursiveRemoveDir(ROOT_DIR . $path);
|
||||
if (file_exists($path)) {
|
||||
$fileHelper->recursiveRemoveDir($path);
|
||||
}
|
||||
if (file_exists(RESOURCES_DIR . '/' . $themeInfo['slug'])) {
|
||||
$fileHelper->recursiveRemoveDir(RESOURCES_DIR . '/' . $themeInfo['slug']);
|
||||
}
|
||||
}
|
||||
|
||||
public function update(string $path): bool
|
||||
{
|
||||
if ($this->install($path)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
41
kernel/services/ThemeService.php
Normal file
@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace kernel\services;
|
||||
|
||||
use kernel\models\Option;
|
||||
|
||||
class ThemeService
|
||||
{
|
||||
protected Option $option;
|
||||
protected string $active_theme = "";
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->option = new Option();
|
||||
$this->findActiveAdminTheme();
|
||||
}
|
||||
|
||||
public function findActiveAdminTheme(): void
|
||||
{
|
||||
$model = $this->option::where("key", "active_theme")->first();
|
||||
$this->active_theme = $model->value;
|
||||
}
|
||||
|
||||
public function getActiveTheme(): string
|
||||
{
|
||||
return $this->active_theme;
|
||||
}
|
||||
|
||||
public function getThemeRout(string $path)
|
||||
{
|
||||
if (file_exists($path . "/manifest.json")){
|
||||
$manifest = json_decode(file_get_contents($path . "/manifest.json"), true);
|
||||
if ($manifest['routs']) {
|
||||
return $manifest['routs'];
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
@ -51,6 +51,16 @@ $table = new \Itguild\Tables\ListJsonTable(json_encode(
|
||||
]
|
||||
));
|
||||
|
||||
// Пример фильтра
|
||||
$table->columns([
|
||||
'title' => [
|
||||
'filter' => [
|
||||
'class' => \Itguild\Tables\Filter\InputTextFilter::class,
|
||||
'value' => $get['title'] ?? ''
|
||||
]
|
||||
],
|
||||
]
|
||||
|
||||
$table->beforePrint(function () {
|
||||
return IconBtnCreateWidget::create(['url' => '/admin/{slug}/create'])->run();
|
||||
});
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Responsive images (ensure images don't scale beyond their parents)
|
||||
// Responsive default_user_photo (ensure default_user_photo don't scale beyond their parents)
|
||||
//
|
||||
// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.
|
||||
// We previously tried the "images are responsive by default" approach in Bootstrap v2,
|
||||
// We previously tried the "default_user_photo are responsive by default" approach in Bootstrap v2,
|
||||
// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
|
||||
// which weren't expecting the images within themselves to be involuntarily resized.
|
||||
// which weren't expecting the default_user_photo within themselves to be involuntarily resized.
|
||||
// See also https://github.com/twbs/bootstrap/issues/18178
|
||||
.img-fluid {
|
||||
@include img-fluid;
|
||||
|
@ -249,7 +249,7 @@ figure {
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none; // Remove the border on images inside links in IE 10-.
|
||||
border-style: none; // Remove the border on default_user_photo inside links in IE 10-.
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -5,12 +5,12 @@
|
||||
|
||||
// Responsive image
|
||||
//
|
||||
// Keep images from scaling beyond the width of their parents.
|
||||
// Keep default_user_photo from scaling beyond the width of their parents.
|
||||
|
||||
@mixin img-fluid {
|
||||
// Part 1: Set a maximum relative to the parent
|
||||
max-width: 100%;
|
||||
// Part 2: Override the height to auto, otherwise images will be stretched
|
||||
// Part 2: Override the height to auto, otherwise default_user_photo will be stretched
|
||||
// when setting a width and height attribute on the img element.
|
||||
height: auto;
|
||||
}
|
||||
|
@ -1,9 +1,9 @@
|
||||
// Responsive images (ensure images don't scale beyond their parents)
|
||||
// Responsive default_user_photo (ensure default_user_photo don't scale beyond their parents)
|
||||
//
|
||||
// This is purposefully opt-in via an explicit class rather than being the default for all `<img>`s.
|
||||
// We previously tried the "images are responsive by default" approach in Bootstrap v2,
|
||||
// We previously tried the "default_user_photo are responsive by default" approach in Bootstrap v2,
|
||||
// and abandoned it in Bootstrap v3 because it breaks lots of third-party widgets (including Google Maps)
|
||||
// which weren't expecting the images within themselves to be involuntarily resized.
|
||||
// which weren't expecting the default_user_photo within themselves to be involuntarily resized.
|
||||
// See also https://github.com/twbs/bootstrap/issues/18178
|
||||
.img-fluid {
|
||||
@include img-fluid;
|
||||
|
@ -249,7 +249,7 @@ figure {
|
||||
|
||||
img {
|
||||
vertical-align: middle;
|
||||
border-style: none; // Remove the border on images inside links in IE 10-.
|
||||
border-style: none; // Remove the border on default_user_photo inside links in IE 10-.
|
||||
}
|
||||
|
||||
svg {
|
||||
|
@ -5,12 +5,12 @@
|
||||
|
||||
// Responsive image
|
||||
//
|
||||
// Keep images from scaling beyond the width of their parents.
|
||||
// Keep default_user_photo from scaling beyond the width of their parents.
|
||||
|
||||
@mixin img-fluid {
|
||||
// Part 1: Set a maximum relative to the parent
|
||||
max-width: 100%;
|
||||
// Part 2: Override the height to auto, otherwise images will be stretched
|
||||
// Part 2: Override the height to auto, otherwise default_user_photo will be stretched
|
||||
// when setting a width and height attribute on the img element.
|
||||
height: auto;
|
||||
}
|
||||
|
BIN
resources/default_user_photo/noPhoto.png
Normal file
After Width: | Height: | Size: 4.0 KiB |
1
resources/out/404.html
Normal file
@ -0,0 +1 @@
|
||||
self.__BUILD_MANIFEST=function(r,e,t,_){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},__routerFilterStatic:{numItems:5,errorRate:1e-4,numBits:96,numHashes:14,bitArray:[1,1,0,0,1,0,e,e,e,r,r,r,r,r,e,e,e,r,e,r,r,r,r,e,e,r,r,e,r,e,e,e,r,e,e,e,r,r,r,r,r,e,e,e,e,e,e,r,e,e,e,e,e,r,e,r,r,e,r,r,r,r,e,r,e,r,e,e,e,r,e,r,r,r,r,r,r,e,r,e,r,r,r,r,e,r,e,r,e,e,r,e,r,r,r,r]},__routerFilterDynamic:{numItems:2,errorRate:1e-4,numBits:39,numHashes:14,bitArray:[e,r,r,r,r,e,r,r,e,e,e,e,e,r,r,e,r,e,e,e,r,e,r,r,e,e,r,r,r,e,e,r,r,e,r,e,e,e,r]},"/_error":["static/chunks/pages/_error-4cc25812257ba5bd.js"],sortedPages:["/_app","/_error"]}}(1,0,0,0),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
|
@ -0,0 +1 @@
|
||||
self.__SSG_MANIFEST=new Set(["\u002Fevents\u002F[slug]","\u002Fparticipants\u002F[slug]"]);self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB()
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[492],{3868:(e,t,r)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_not-found/page",function(){return r(5623)}])},3384:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"HTTPAccessErrorFallback",{enumerable:!0,get:function(){return o}}),r(306);let l=r(5155);r(2115);let n={error:{fontFamily:'system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji"',height:"100vh",textAlign:"center",display:"flex",flexDirection:"column",alignItems:"center",justifyContent:"center"},desc:{display:"inline-block"},h1:{display:"inline-block",margin:"0 20px 0 0",padding:"0 23px 0 0",fontSize:24,fontWeight:500,verticalAlign:"top",lineHeight:"49px"},h2:{fontSize:14,fontWeight:400,lineHeight:"49px",margin:0}};function o(e){let{status:t,message:r}=e;return(0,l.jsxs)(l.Fragment,{children:[(0,l.jsx)("title",{children:t+": "+r}),(0,l.jsx)("div",{style:n.error,children:(0,l.jsxs)("div",{children:[(0,l.jsx)("style",{dangerouslySetInnerHTML:{__html:"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}),(0,l.jsx)("h1",{className:"next-error-h1",style:n.h1,children:t}),(0,l.jsx)("div",{style:n.desc,children:(0,l.jsx)("h2",{style:n.h2,children:r})})]})})]})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)},5623:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),Object.defineProperty(t,"default",{enumerable:!0,get:function(){return o}});let l=r(5155),n=r(3384);function o(){return(0,l.jsx)(n.HTTPAccessErrorFallback,{status:404,message:"This page could not be found."})}("function"==typeof t.default||"object"==typeof t.default&&null!==t.default)&&void 0===t.default.__esModule&&(Object.defineProperty(t.default,"__esModule",{value:!0}),Object.assign(t.default,t),e.exports=t.default)}},e=>{var t=t=>e(e.s=t);e.O(0,[441,517,358],()=>t(3868)),_N_E=e.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[706],{3062:(e,s,n)=>{Promise.resolve().then(n.bind(n,6919)),Promise.resolve().then(n.t.bind(n,8173,23)),Promise.resolve().then(n.t.bind(n,7970,23))},6919:(e,s,n)=>{"use strict";n.d(s,{default:()=>a});var l=n(5155),r=n(8173),t=n.n(r),i=n(6658);n(2115);let a=()=>{let e=(0,i.usePathname)().split("/").filter(e=>e),s={events:"мероприятия сообщества","event-1":"базовая программа подготовки гештальт-терапевтов - добор",participants:"участники",1:"кириллов кирилл кириллович"};return(0,l.jsx)("nav",{className:"max-w-[1032px] mx-auto",children:(0,l.jsxs)("ol",{className:"flex text-middleGrey font-[350] my-[50px]",children:[(0,l.jsx)("li",{children:(0,l.jsx)(t(),{href:"/",children:"главная"})}),e.map((n,r)=>{let i="/"+e.slice(0,r+1).join("/");return(0,l.jsx)("li",{children:(0,l.jsxs)(t(),{href:i,children:[(0,l.jsx)("span",{className:"mx-[2px]",children:"/"}),s[decodeURIComponent(n)]]})},i)})]})})}}},e=>{var s=s=>e(e.s=s);e.O(0,[742,441,517,358],()=>s(3062)),_N_E=e.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[177],{5691:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,9324,23)),Promise.resolve().then(n.t.bind(n,8173,23)),Promise.resolve().then(n.t.bind(n,7970,23))},9324:()=>{}},e=>{var s=s=>e(e.s=s);e.O(0,[722,742,441,517,358],()=>s(5691)),_N_E=e.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[974],{6993:(e,t,r)=>{Promise.resolve().then(r.bind(r,5360)),Promise.resolve().then(r.bind(r,5416)),Promise.resolve().then(r.t.bind(r,8173,23)),Promise.resolve().then(r.t.bind(r,7970,23))},5360:(e,t,r)=>{"use strict";r.d(t,{default:()=>a});var n=r(5155);r(2115);let a=e=>{let{className:t,name:r,variant:a="default",size:l="default"}=e,o={default:"bg-blue text-[16px] text-white",secondary:"text-[16px] text-blue border-[1px] border-blue"},d={default:"max-h-[39px] px-[25px] py-[10px]"},s=o[a]||o.default,u=d[l]||d.default;return(0,n.jsx)("button",{className:"".concat("flex items-center justify-center whitespace-nowrap rounded-[6px] font-[400]"," ").concat(s," ").concat(u," ").concat(t),children:r})}},5416:(e,t,r)=>{"use strict";r.d(t,{default:()=>l});var n=r(5155);r(2115);var a=r(5565);let l=e=>{let{className:t,name:r,variant:l="default"}=e;return(0,n.jsxs)("div",{className:"".concat(t," ").concat({default:"px-[25px] py-[10px]",secondary:"px-[36px] py-[7px] bg-white"}[l]," max-w-[225px] min-w-[180px] justify-center w-fit cursor-pointer border-blue border-[1px] flex gap-[10px] rounded-[10px]"),children:[(0,n.jsx)("p",{className:"text-blue font-[700] text-[16px]",children:r}),(0,n.jsx)(a.default,{src:"/images/chevronDown.svg",alt:"chevronDown",width:11,height:8})]})}},5565:(e,t,r)=>{"use strict";r.d(t,{default:()=>a.a});var n=r(4146),a=r.n(n)},4146:(e,t,r)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),function(e,t){for(var r in t)Object.defineProperty(e,r,{enumerable:!0,get:t[r]})}(t,{default:function(){return s},getImageProps:function(){return d}});let n=r(306),a=r(666),l=r(7970),o=n._(r(5514));function d(e){let{props:t}=(0,a.getImgProps)(e,{defaultLoader:o.default,imgConf:{deviceSizes:[640,750,828,1080,1200,1920,2048,3840],imageSizes:[16,32,48,64,96,128,256,384],path:"/_next/image",loader:"default",dangerouslyAllowSVG:!1,unoptimized:!1}});for(let[e,r]of Object.entries(t))void 0===r&&delete t[e];return{props:t}}let s=l.Image}},e=>{var t=t=>e(e.s=t);e.O(0,[742,441,517,358],()=>t(6993)),_N_E=e.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[731],{4585:(e,s,l)=>{Promise.resolve().then(l.bind(l,6919)),Promise.resolve().then(l.t.bind(l,7970,23))},6919:(e,s,l)=>{"use strict";l.d(s,{default:()=>a});var n=l(5155),r=l(8173),t=l.n(r),i=l(6658);l(2115);let a=()=>{let e=(0,i.usePathname)().split("/").filter(e=>e),s={events:"мероприятия сообщества","event-1":"базовая программа подготовки гештальт-терапевтов - добор",participants:"участники",1:"кириллов кирилл кириллович"};return(0,n.jsx)("nav",{className:"max-w-[1032px] mx-auto",children:(0,n.jsxs)("ol",{className:"flex text-middleGrey font-[350] my-[50px]",children:[(0,n.jsx)("li",{children:(0,n.jsx)(t(),{href:"/",children:"главная"})}),e.map((l,r)=>{let i="/"+e.slice(0,r+1).join("/");return(0,n.jsx)("li",{children:(0,n.jsxs)(t(),{href:i,children:[(0,n.jsx)("span",{className:"mx-[2px]",children:"/"}),s[decodeURIComponent(l)]]})},i)})]})})}}},e=>{var s=s=>e(e.s=s);e.O(0,[742,441,517,358],()=>s(4585)),_N_E=e.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[358],{4932:(e,s,n)=>{Promise.resolve().then(n.t.bind(n,7033,23)),Promise.resolve().then(n.t.bind(n,4547,23)),Promise.resolve().then(n.t.bind(n,4835,23)),Promise.resolve().then(n.t.bind(n,2328,23)),Promise.resolve().then(n.t.bind(n,5244,23)),Promise.resolve().then(n.t.bind(n,3866,23)),Promise.resolve().then(n.t.bind(n,6213,23))}},e=>{var s=s=>e(e.s=s);e.O(0,[441,517],()=>(s(7200),s(4932))),_N_E=e.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[636],{1788:(_,n,p)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return p(5203)}])}},_=>{var n=n=>_(_.s=n);_.O(0,[593,792],()=>(n(1788),n(4009))),_N_E=_.O()}]);
|
@ -0,0 +1 @@
|
||||
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[112],{6194:(_,n,e)=>{(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return e(6218)}])}},_=>{var n=n=>_(_.s=n);_.O(0,[636,593,792],()=>n(6194)),_N_E=_.O()}]);
|
@ -0,0 +1 @@
|
||||
(()=>{"use strict";var e={},t={};function r(o){var n=t[o];if(void 0!==n)return n.exports;var a=t[o]={exports:{}},i=!0;try{e[o](a,a.exports,r),i=!1}finally{i&&delete t[o]}return a.exports}r.m=e,(()=>{var e=[];r.O=(t,o,n,a)=>{if(o){a=a||0;for(var i=e.length;i>0&&e[i-1][2]>a;i--)e[i]=e[i-1];e[i]=[o,n,a];return}for(var u=1/0,i=0;i<e.length;i++){for(var[o,n,a]=e[i],l=!0,c=0;c<o.length;c++)(!1&a||u>=a)&&Object.keys(r.O).every(e=>r.O[e](o[c]))?o.splice(c--,1):(l=!1,a<u&&(u=a));if(l){e.splice(i--,1);var d=n();void 0!==d&&(t=d)}}return t}})(),r.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return r.d(t,{a:t}),t},(()=>{var e,t=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__;r.t=function(o,n){if(1&n&&(o=this(o)),8&n||"object"==typeof o&&o&&(4&n&&o.__esModule||16&n&&"function"==typeof o.then))return o;var a=Object.create(null);r.r(a);var i={};e=e||[null,t({}),t([]),t(t)];for(var u=2&n&&o;"object"==typeof u&&!~e.indexOf(u);u=t(u))Object.getOwnPropertyNames(u).forEach(e=>i[e]=()=>o[e]);return i.default=()=>o,r.d(a,i),a}})(),r.d=(e,t)=>{for(var o in t)r.o(t,o)&&!r.o(e,o)&&Object.defineProperty(e,o,{enumerable:!0,get:t[o]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce((t,o)=>(r.f[o](e,t),t),[])),r.u=e=>{},r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={},t="_N_E:";r.l=(o,n,a,i)=>{if(e[o]){e[o].push(n);return}if(void 0!==a)for(var u,l,c=document.getElementsByTagName("script"),d=0;d<c.length;d++){var f=c[d];if(f.getAttribute("src")==o||f.getAttribute("data-webpack")==t+a){u=f;break}}u||(l=!0,(u=document.createElement("script")).charset="utf-8",u.timeout=120,r.nc&&u.setAttribute("nonce",r.nc),u.setAttribute("data-webpack",t+a),u.src=r.tu(o)),e[o]=[n];var s=(t,r)=>{u.onerror=u.onload=null,clearTimeout(p);var n=e[o];if(delete e[o],u.parentNode&&u.parentNode.removeChild(u),n&&n.forEach(e=>e(r)),t)return t(r)},p=setTimeout(s.bind(null,void 0,{type:"timeout",target:u}),12e4);u.onerror=s.bind(null,u.onerror),u.onload=s.bind(null,u.onload),l&&document.head.appendChild(u)}})(),r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},(()=>{var e;r.tt=()=>(void 0===e&&(e={createScriptURL:e=>e},"undefined"!=typeof trustedTypes&&trustedTypes.createPolicy&&(e=trustedTypes.createPolicy("nextjs#bundler",e))),e)})(),r.tu=e=>r.tt().createScriptURL(e),r.p="/_next/",(()=>{var e={68:0,722:0};r.f.j=(t,o)=>{var n=r.o(e,t)?e[t]:void 0;if(0!==n){if(n)o.push(n[2]);else if(/^(68|722)$/.test(t))e[t]=0;else{var a=new Promise((r,o)=>n=e[t]=[r,o]);o.push(n[2]=a);var i=r.p+r.u(t),u=Error();r.l(i,o=>{if(r.o(e,t)&&(0!==(n=e[t])&&(e[t]=void 0),n)){var a=o&&("load"===o.type?"missing":o.type),i=o&&o.target&&o.target.src;u.message="Loading chunk "+t+" failed.\n("+a+": "+i+")",u.name="ChunkLoadError",u.type=a,u.request=i,n[1](u)}},"chunk-"+t,t)}}},r.O.j=t=>0===e[t];var t=(t,o)=>{var n,a,[i,u,l]=o,c=0;if(i.some(t=>0!==e[t])){for(n in u)r.o(u,n)&&(r.m[n]=u[n]);if(l)var d=l(r)}for(t&&t(o);c<i.length;c++)a=i[c],r.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return r.O(d)},o=self.webpackChunk_N_E=self.webpackChunk_N_E||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})()})();
|
3
resources/out/_next/static/css/0d3195690bab7456.css
Normal file
1
resources/out/events.html
Normal file
18
resources/out/events.txt
Normal file
1
resources/out/events/event-1.html
Normal file
15
resources/out/events/event-1.txt
Normal file
1
resources/out/events/event-2.html
Normal file
15
resources/out/events/event-2.txt
Normal file
1
resources/out/events/event-3.html
Normal file
15
resources/out/events/event-3.txt
Normal file
BIN
resources/out/favicon.ico
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
resources/out/fonts/gteestiprodisplay_bold.otf
Normal file
BIN
resources/out/fonts/gteestiprodisplay_light.otf
Normal file
BIN
resources/out/fonts/gteestiprodisplay_medium.otf
Normal file
BIN
resources/out/fonts/gteestiprodisplay_regular.otf
Normal file
BIN
resources/out/fonts/gteestiprodisplay_thin.otf
Normal file
BIN
resources/out/fonts/gteestiprodisplay_ultrabold.otf
Normal file
BIN
resources/out/images/avatar.png
Normal file
After Width: | Height: | Size: 12 KiB |
22
resources/out/images/avatar.svg
Normal file
After Width: | Height: | Size: 3.7 MiB |
3
resources/out/images/chevronDown.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="9" height="7" viewBox="0 0 9 7" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.28321 5.95799C4.88285 6.46232 4.11715 6.46231 3.71679 5.95799L1.0243 2.56633C0.504041 1.91098 0.970754 0.944579 1.80751 0.944579L7.19249 0.94458C8.02925 0.94458 8.49596 1.91098 7.9757 2.56634L5.28321 5.95799Z" fill="#87BFFF"/>
|
||||
</svg>
|
After Width: | Height: | Size: 338 B |
4
resources/out/images/clock.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10 19.5C14.9706 19.5 19 15.4706 19 10.5C19 5.52944 14.9706 1.5 10 1.5C5.02944 1.5 1 5.52944 1 10.5C1 15.4706 5.02944 19.5 10 19.5Z" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M10 5.09998V10.5L13.6 12.3" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 448 B |
6
resources/out/images/date.svg
Normal file
@ -0,0 +1,6 @@
|
||||
<svg width="20" height="21" viewBox="0 0 20 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M16.3913 3.06525H3.6087C2.60018 3.06525 1.78261 3.88281 1.78261 4.89133V17.6739C1.78261 18.6825 2.60018 19.5 3.6087 19.5H16.3913C17.3998 19.5 18.2174 18.6825 18.2174 17.6739V4.89133C18.2174 3.88281 17.3998 3.06525 16.3913 3.06525Z" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M13.5213 1.5V5.41304" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M6.47861 1.5V5.41304" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M1.78261 8.54346H18.2174" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 773 B |
13
resources/out/images/intro.svg
Normal file
After Width: | Height: | Size: 31 KiB |
4
resources/out/images/location.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="17" height="21" viewBox="0 0 17 21" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M15.8636 8.86364C15.8636 14.5909 8.5 19.5 8.5 19.5C8.5 19.5 1.13637 14.5909 1.13637 8.86364C1.13637 6.91068 1.91218 5.03771 3.29313 3.65676C4.67408 2.27581 6.54705 1.5 8.5 1.5C10.453 1.5 12.3259 2.27581 13.7069 3.65676C15.0878 5.03771 15.8636 6.91068 15.8636 8.86364Z" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M8.4996 11.3182C9.85521 11.3182 10.9542 10.2193 10.9542 8.86366C10.9542 7.50806 9.85521 6.40912 8.4996 6.40912C7.144 6.40912 6.04506 7.50806 6.04506 8.86366C6.04506 10.2193 7.144 11.3182 8.4996 11.3182Z" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 760 B |
3
resources/out/images/logo_tg.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="17" height="15" viewBox="0 0 17 15" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.64294 8.54805L11.0447 4.6533L12.3092 3.7878C12.9087 3.60138 12.8296 4.03191 12.7151 4.27048C11.6171 5.48551 9.13689 8.15192 8.00034 9.09731C6.86379 10.0427 7.52678 10.8117 8.00034 11.078C8.88501 11.6772 11.0665 13.1984 12.7151 14.49C14.3638 15.7816 15.0361 14.3181 15.1662 13.4248C15.7282 9.82965 16.8804 2.3231 16.9928 1.05814C17.1052 -0.20682 15.8739 -0.0792145 15.2443 0.142709L13.5426 0.825122C10.1079 2.3453 2.8047 5.59869 1.06865 6.45088C-0.66739 7.30306 0.0955118 7.90447 0.693968 8.09866L3.03575 8.84765C4.10985 9.35363 5.22142 8.85874 5.64294 8.54805Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 692 B |
3
resources/out/images/logo_vk.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="20" height="12" viewBox="0 0 20 12" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 0.412C0.117879 0.129939 0.33851 0.0100359 0.630078 0.0095077C1.43645 0.00792308 2.24335 0.00633847 3.04972 0.0095077C3.39971 0.0110923 3.64642 0.193323 3.77942 0.509718C3.9625 0.944432 4.11689 1.39182 4.29632 1.82865C4.87371 3.23632 5.545 4.59275 6.48437 5.79494C6.66849 6.03105 6.89121 6.23758 7.10663 6.44675C7.18382 6.52175 7.28762 6.57722 7.38881 6.61683C7.6543 6.72194 7.83737 6.62264 7.89005 6.33635C7.92291 6.15676 7.93126 5.97084 7.9323 5.78755C7.93595 4.76653 7.93387 3.74498 7.93439 2.72396C7.93439 2.10437 7.76904 1.54342 7.36481 1.06539C7.28501 0.970842 7.20677 0.871011 7.14679 0.763257C6.97206 0.450031 7.13792 0.0913796 7.48634 0.0206C7.56875 0.00369744 7.65429 0.00105641 7.73879 0.00105641C8.819 0 9.89869 0 10.9789 0C11.0311 0 11.0832 0.00105641 11.1348 0.00581026C11.4713 0.0338052 11.6377 0.197549 11.669 0.541939C11.682 0.686139 11.683 0.831396 11.683 0.976124C11.6841 2.294 11.683 3.61187 11.6846 4.92921C11.6846 5.05387 11.6914 5.17958 11.7081 5.30318C11.7602 5.69881 12.0299 5.85569 12.3548 5.62856C12.6772 5.40302 12.9813 5.13257 13.2384 4.83308C14.1048 3.82262 14.7583 2.66955 15.3425 1.47528C15.4838 1.18688 15.6116 0.891611 15.7446 0.598985C15.9121 0.231354 16.1869 0.0121487 16.5927 0.0095077C17.4189 0.00422565 18.2451 0 19.0708 0.0211282C19.474 0.0316923 19.6503 0.292626 19.5606 0.691421C19.5162 0.88897 19.4651 1.0918 19.3738 1.26981C19.0724 1.85876 18.7798 2.45616 18.4313 3.01658C17.8743 3.91295 17.2818 4.78713 16.6908 5.66184C16.2694 6.28565 16.2866 6.44728 16.8029 7.00295C17.6004 7.86128 18.3927 8.7249 19.16 9.61123C19.4312 9.92446 19.6534 10.2921 19.8422 10.6645C20.2026 11.3744 19.9345 11.8043 19.1506 11.8138C18.4543 11.8223 17.758 11.8096 17.0622 11.8181C16.6585 11.8228 16.3262 11.6718 16.0513 11.386C15.7107 11.0326 15.3769 10.6719 15.0441 10.3106C14.497 9.7174 13.9217 9.15433 13.2603 8.69109C12.939 8.46608 12.6052 8.26114 12.1879 8.27592C11.8703 8.28702 11.7373 8.39847 11.7133 8.72437C11.6903 9.03284 11.6804 9.34237 11.6778 9.6519C11.6736 10.113 11.6893 10.5747 11.6809 11.0353C11.6742 11.424 11.5255 11.6343 11.15 11.7056C10.7885 11.7742 10.4151 11.8096 10.0479 11.8065C8.59837 11.7938 7.30431 11.2846 6.11092 10.4854C4.96603 9.71898 4.05482 8.71751 3.27192 7.58398C2.12077 5.91749 1.10316 4.17863 0.416227 2.25966C0.250884 1.79854 0.137177 1.3184 0 0.846714C0 0.701985 0 0.556729 0 0.412Z" fill="white"/>
|
||||
</svg>
|
After Width: | Height: | Size: 2.4 KiB |
4
resources/out/images/mail.svg
Normal file
@ -0,0 +1,4 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M10.0004 13.5994C11.9886 13.5994 13.6004 11.9876 13.6004 9.99941C13.6004 8.01119 11.9886 6.39941 10.0004 6.39941C8.01216 6.39941 6.40039 8.01119 6.40039 9.99941C6.40039 11.9876 8.01216 13.5994 10.0004 13.5994Z" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
<path d="M13.6 6.39944V10.8994C13.6 11.6155 13.8845 12.3023 14.3908 12.8086C14.8972 13.315 15.5839 13.5994 16.3 13.5994C17.0161 13.5994 17.7028 13.315 18.2092 12.8086C18.7155 12.3023 19 11.6155 19 10.8994V9.99944C18.9999 7.96816 18.3126 5.99667 17.0499 4.40552C15.7873 2.81437 14.0235 1.69714 12.0454 1.23551C10.0673 0.773874 7.99115 0.994979 6.15462 1.86287C4.31809 2.73076 2.82917 4.1944 1.92994 6.01579C1.03071 7.83718 0.774078 9.9092 1.20176 11.8949C1.62944 13.8807 2.71629 15.6633 4.28557 16.9531C5.85486 18.2428 7.81429 18.9637 9.84527 18.9987C11.8762 19.0336 13.8593 18.3804 15.472 17.1454" stroke="#6D6D6D" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
9
resources/out/images/mok_human.svg
Normal file
After Width: | Height: | Size: 1.7 MiB |
9
resources/out/images/mok_human2.svg
Normal file
After Width: | Height: | Size: 1.7 MiB |
9
resources/out/images/oppgp.svg
Normal file
After Width: | Height: | Size: 37 KiB |