Changes
This commit is contained in:
Generated
+7
-1
@@ -6,7 +6,6 @@
|
|||||||
<sourceFolder url="file://$MODULE_DIR$/database/factories" isTestSource="false" packagePrefix="Database\Factories\" />
|
<sourceFolder url="file://$MODULE_DIR$/database/factories" isTestSource="false" packagePrefix="Database\Factories\" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" />
|
<sourceFolder url="file://$MODULE_DIR$/database/seeders" isTestSource="false" packagePrefix="Database\Seeders\" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
|
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="Tests\" />
|
||||||
<sourceFolder url="file://$MODULE_DIR$/spec" isTestSource="true" />
|
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/brick/math" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/brick/math" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/carbonphp/carbon-doctrine-types" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/carbonphp/carbon-doctrine-types" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
|
||||||
@@ -173,6 +172,13 @@
|
|||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/bezhansalleh/filament-shield" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/bezhansalleh/filament-shield" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-permission" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-permission" />
|
||||||
<excludeFolder url="file://$MODULE_DIR$/vendor/vkcom/vk-php-sdk" />
|
<excludeFolder url="file://$MODULE_DIR$/vendor/vkcom/vk-php-sdk" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/nicmart/tree" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/browsershot" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/crawler" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/laravel-sitemap" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/robots-txt" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/spatie/temporary-directory" />
|
||||||
|
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dom-crawler" />
|
||||||
</content>
|
</content>
|
||||||
<orderEntry type="inheritedJdk" />
|
<orderEntry type="inheritedJdk" />
|
||||||
<orderEntry type="sourceFolder" forTests="false" />
|
<orderEntry type="sourceFolder" forTests="false" />
|
||||||
|
|||||||
Generated
+7
@@ -183,6 +183,13 @@
|
|||||||
<path value="$PROJECT_DIR$/vendor/bezhansalleh/filament-shield" />
|
<path value="$PROJECT_DIR$/vendor/bezhansalleh/filament-shield" />
|
||||||
<path value="$PROJECT_DIR$/vendor/spatie/laravel-permission" />
|
<path value="$PROJECT_DIR$/vendor/spatie/laravel-permission" />
|
||||||
<path value="$PROJECT_DIR$/vendor/vkcom/vk-php-sdk" />
|
<path value="$PROJECT_DIR$/vendor/vkcom/vk-php-sdk" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/symfony/dom-crawler" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/nicmart/tree" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/spatie/temporary-directory" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/spatie/robots-txt" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/spatie/laravel-sitemap" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/spatie/browsershot" />
|
||||||
|
<path value="$PROJECT_DIR$/vendor/spatie/crawler" />
|
||||||
</include_path>
|
</include_path>
|
||||||
</component>
|
</component>
|
||||||
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
|
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
|
||||||
|
|||||||
@@ -1,32 +1,42 @@
|
|||||||
server {
|
server {
|
||||||
client_max_body_size 200M;
|
client_max_body_size 200M; # Максимальный размер тела запроса
|
||||||
large_client_header_buffers 4 128k;
|
large_client_header_buffers 4 128k; # Размеры буферов для заголовков
|
||||||
|
|
||||||
|
|
||||||
root /var/www/public;
|
root /var/www/public;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
add_header Access-Control-Allow-Origin *;
|
add_header Access-Control-Allow-Origin *; # Заголовок для CORS
|
||||||
try_files $uri /index.php?$args;
|
try_files $uri /index.php?$args; # Обработка запросов
|
||||||
}
|
}
|
||||||
|
|
||||||
location /sveden/ {
|
location /sveden/ {
|
||||||
alias /var/www/public/sveden/;
|
alias /var/www/public/sveden/;
|
||||||
index index.html;
|
index index.html;
|
||||||
try_files $uri $uri/ /sveden/index.html;
|
try_files $uri $uri/ /sveden/index.html; # Обработка статических файлов
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
location ~ \.php$ {
|
location ~ \.php$ {
|
||||||
try_files $uri =404;
|
try_files $uri =404; # Если файл не найден, возвращаем 404
|
||||||
fastcgi_split_path_info ^(.+\.php)(/.+)$;
|
fastcgi_split_path_info ^(.+\.php)(/.+)$; # Разделение пути
|
||||||
fastcgi_pass app:9000;
|
fastcgi_pass app:9000; # Указываем сервер PHP-FPM
|
||||||
fastcgi_index index.php;
|
fastcgi_index index.php; # Индексный файл
|
||||||
include fastcgi_params;
|
include fastcgi_params; # Включаем параметры FastCGI
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; # Путь к скрипту
|
||||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
fastcgi_param PATH_INFO $fastcgi_path_info; # Информация о пути
|
||||||
|
fastcgi_buffers 16 16k; # Увеличение буферов FastCGI
|
||||||
|
fastcgi_buffer_size 32k; # Размер буфера FastCGI
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Защита от доступа к конфиденциальным файлам
|
||||||
|
location ~ /\.ht {
|
||||||
|
deny all; # Запрет доступа к файлам .htaccess
|
||||||
|
}
|
||||||
|
|
||||||
|
# Настройки кэширования для статических файлов
|
||||||
|
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|woff|woff2|ttf|otf)$ {
|
||||||
|
expires 30d; # Кэширование на 30 дней
|
||||||
|
add_header Cache-Control "public, no-transform"; # Заголовок кэширования
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,97 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
|
use App\Enums\PostStatus;
|
||||||
|
use App\Models\Event;
|
||||||
|
use App\Models\Page;
|
||||||
|
use App\Models\Post;
|
||||||
|
use Illuminate\Console\Command;
|
||||||
|
use Spatie\Sitemap\Sitemap;
|
||||||
|
use Spatie\Sitemap\Tags\Url;
|
||||||
|
|
||||||
|
class GenerateSitemap extends Command
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name and signature of the console command.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $signature = 'sitemap:generate';
|
||||||
|
/**
|
||||||
|
* The console command description.
|
||||||
|
*
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
protected $description = 'Генерирует карту сайта';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the console command.
|
||||||
|
*/
|
||||||
|
public function handle()
|
||||||
|
{
|
||||||
|
$sitemap = Sitemap::create();
|
||||||
|
|
||||||
|
$this->generatePages($sitemap);
|
||||||
|
$this->generatePosts($sitemap);
|
||||||
|
$this->generateEvents($sitemap);
|
||||||
|
|
||||||
|
$sitemap->writeToFile(public_path('sitemap.xml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePages(Sitemap $sitemap)
|
||||||
|
{
|
||||||
|
$pages = Page::query()
|
||||||
|
->where('is_visible', true)
|
||||||
|
->where('code', 200)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$this->addUrlsToSitemap($sitemap, $pages, function($page) {
|
||||||
|
return [
|
||||||
|
'path' => "/{$page->path}",
|
||||||
|
'lastModificationDate' => $page->updated_at,
|
||||||
|
'priority' => 0.5,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generateEvents(Sitemap $sitemap)
|
||||||
|
{
|
||||||
|
$events = Event::query()
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$this->addUrlsToSitemap($sitemap, $events, function($event) {
|
||||||
|
return [
|
||||||
|
'path' => "/events/{$event->slug}",
|
||||||
|
'lastModificationDate' => $event->updated_at,
|
||||||
|
'priority' => 0.5,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePosts(Sitemap $sitemap)
|
||||||
|
{
|
||||||
|
$posts = Post::query()
|
||||||
|
->where('status', PostStatus::PUBLISHED)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$this->addUrlsToSitemap($sitemap, $posts, function($post) {
|
||||||
|
return [
|
||||||
|
'path' => "/news/{$post->slug}",
|
||||||
|
'lastModificationDate' => $post->updated_at,
|
||||||
|
'priority' => 0.5,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addUrlsToSitemap(Sitemap $sitemap, $items, callable $callback)
|
||||||
|
{
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$urlData = $callback($item);
|
||||||
|
$sitemap->add(Url::create($urlData['path'])
|
||||||
|
->setLastModificationDate($urlData['lastModificationDate'])
|
||||||
|
->setPriority($urlData['priority']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,20 +29,15 @@ class CreateAcademicJournal extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['about_program']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['main_info']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,22 +63,6 @@ class CreateAcademicJournal extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,41 +28,19 @@ class EditAcademicJournal extends EditRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['about_program']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['main_info']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+19
-20
@@ -11,10 +11,14 @@ class CreateAdditionalEducation extends CreateRecord
|
|||||||
{
|
{
|
||||||
protected static string $resource = AdditionalEducationResource::class;
|
protected static string $resource = AdditionalEducationResource::class;
|
||||||
|
|
||||||
|
protected array $seoData;
|
||||||
|
|
||||||
protected function mutateFormDataBeforeCreate(array $data): array
|
protected function mutateFormDataBeforeCreate(array $data): array
|
||||||
{
|
{
|
||||||
$this->seoData = $this->generateSeo($data);
|
$this->seoData = $this->generateSeo($data);
|
||||||
|
|
||||||
|
$data['search_data'] = $this->generateSearchData($data['content']);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,17 +31,16 @@ class CreateAdditionalEducation extends CreateRecord
|
|||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
$description = strip_tags($rowData['data']['content']);
|
if ($rowData !== null) {
|
||||||
// $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
$description = strip_tags($rowData['data']['content']);
|
||||||
|
} else {
|
||||||
|
$description = null;
|
||||||
|
}
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit($description, 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => "",
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getFirstBlockByName(string $name, array $content) : array|null
|
private function getFirstBlockByName(string $name, array $content) : array|null
|
||||||
{
|
{
|
||||||
$data = null;
|
$data = null;
|
||||||
@@ -48,21 +51,17 @@ class CreateAdditionalEducation extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
private function generateSearchData(array $data) : string
|
||||||
{
|
{
|
||||||
$data = [];
|
$result = "";
|
||||||
foreach ($content as $block) {
|
foreach ($data as $block) {
|
||||||
if ($block['type'] === $name) {
|
$result .= $this->getDataFromBlocks($block);
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
$block = null;
|
// Удаляем лишние пробелы и переносы строк
|
||||||
foreach ($data as $item) {
|
$result = preg_replace('/\s+/', ' ', $result);
|
||||||
if ($item['data']['seo_active'] === true) {
|
$result = trim($result);
|
||||||
$block = $item;
|
|
||||||
}
|
return strtolower($result);
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
|
|||||||
+60
-6
@@ -14,33 +14,37 @@ class EditAdditionalEducation extends EditRecord
|
|||||||
protected array $seoData;
|
protected array $seoData;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected function mutateFormDataBeforeSave(array $data): array
|
protected function mutateFormDataBeforeSave(array $data): array
|
||||||
{
|
{
|
||||||
$this->seoData = $this->generateSeo($data);
|
$this->seoData = $this->generateSeo($data);
|
||||||
|
|
||||||
|
$data['search_data'] = $this->generateSearchData($data['content']);
|
||||||
|
|
||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function afterSave(): void
|
protected function afterSave(): void
|
||||||
{
|
{
|
||||||
$this->record->seo()->update($this->seoData);
|
$this->record->seo()->update($this->seoData);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
$description = strip_tags($rowData['data']['content']);
|
if ($rowData !== null) {
|
||||||
// $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
$description = strip_tags($rowData['data']['content']);
|
||||||
|
} else {
|
||||||
|
$description = null;
|
||||||
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit($description, 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => "",
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getFirstBlockByName(string $name, array $content) : array|null
|
private function getFirstBlockByName(string $name, array $content) : array|null
|
||||||
{
|
{
|
||||||
$data = null;
|
$data = null;
|
||||||
@@ -51,6 +55,56 @@ class EditAdditionalEducation extends EditRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function generateSearchData(array $data) : string
|
||||||
|
{
|
||||||
|
$result = "";
|
||||||
|
foreach ($data as $block) {
|
||||||
|
$result .= $this->getDataFromBlocks($block);
|
||||||
|
}
|
||||||
|
// Удаляем лишние пробелы и переносы строк
|
||||||
|
$result = preg_replace('/\s+/', ' ', $result);
|
||||||
|
$result = trim($result);
|
||||||
|
|
||||||
|
return strtolower($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getDataFromBlocks($block) : string
|
||||||
|
{
|
||||||
|
$data = "";
|
||||||
|
switch ($block['type']) {
|
||||||
|
case 'paragraph':
|
||||||
|
$data .= strip_tags($block['data']['content']) . " ";
|
||||||
|
break;
|
||||||
|
case 'heading':
|
||||||
|
$data .= strip_tags($block['data']['content']) . " ";
|
||||||
|
break;
|
||||||
|
case 'files':
|
||||||
|
foreach ($block['data']['file'] as $file) {
|
||||||
|
$data .= $file['title'] . " ";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'person':
|
||||||
|
$data .= $block['data']['name'] . " ";
|
||||||
|
break;
|
||||||
|
case 'stepper':
|
||||||
|
$data .= $block['data']['step_name'] . " ";
|
||||||
|
foreach ($block['data']['steps'] as $step) {
|
||||||
|
$data .= $step['title'] . " ";
|
||||||
|
$data .= strip_tags($step['content']) . " ";
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'tabs':
|
||||||
|
foreach ($block['data']['tab'] as $item) {
|
||||||
|
foreach ($item['content'] as $block) {
|
||||||
|
$data .= $this->getDataFromBlocks($block);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected function getHeaderActions(): array
|
protected function getHeaderActions(): array
|
||||||
|
|||||||
@@ -2,25 +2,43 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources;
|
namespace App\Filament\Resources;
|
||||||
|
|
||||||
|
use App\Enums\CustomFormStatus;
|
||||||
|
use App\Enums\PostStatus;
|
||||||
use App\Filament\Resources\DepartmentResource\Pages;
|
use App\Filament\Resources\DepartmentResource\Pages;
|
||||||
use App\Filament\Resources\DepartmentResource\RelationManagers;
|
use App\Filament\Resources\DepartmentResource\RelationManagers;
|
||||||
|
use App\Helpers\ByteConverter;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\CustomForm;
|
||||||
use App\Models\Department;
|
use App\Models\Department;
|
||||||
use App\Models\Faculty;
|
use App\Models\Faculty;
|
||||||
|
use App\Models\Page;
|
||||||
|
use App\Models\PageReferenceList;
|
||||||
|
use App\Models\Post;
|
||||||
use Filament\Forms;
|
use Filament\Forms;
|
||||||
|
use Filament\Forms\Components\Builder;
|
||||||
|
use Filament\Forms\Components\FileUpload;
|
||||||
|
use Filament\Forms\Components\Hidden;
|
||||||
|
use Filament\Forms\Components\RichEditor;
|
||||||
|
use Filament\Forms\Components\Section;
|
||||||
|
use Filament\Forms\Components\Select;
|
||||||
|
use Filament\Forms\Components\Tabs;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Components\Toggle;
|
use Filament\Forms\Components\Toggle;
|
||||||
use Filament\Forms\Form;
|
use Filament\Forms\Form;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Tables;
|
use Filament\Tables;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||||
|
|
||||||
class DepartmentResource extends Resource
|
class DepartmentResource extends Resource
|
||||||
{
|
{
|
||||||
protected static ?string $model = Department::class;
|
protected static ?string $model = Department::class;
|
||||||
|
|
||||||
|
protected static ?string $navigationGroup = 'Структура института';
|
||||||
|
|
||||||
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
|
||||||
|
|
||||||
protected static ?string $pluralLabel = 'Кафедры';
|
protected static ?string $pluralLabel = 'Кафедры';
|
||||||
@@ -34,21 +52,402 @@ class DepartmentResource extends Resource
|
|||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('title')->label('Название кафедры')->required()
|
Section::make()
|
||||||
->live(onBlur: true)
|
->schema([
|
||||||
->afterStateUpdated(function (string $operation, $state, Forms\Set $set) {
|
Tabs::make('Tabs')
|
||||||
$set('slug', Str::slug($state));
|
->tabs([
|
||||||
}),
|
Tabs\Tab::make('Основная информация')
|
||||||
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
->schema([
|
||||||
Forms\Components\Select::make('faculty_id')
|
TextInput::make('title')->label('Название факультета')->required()
|
||||||
->options(Faculty::all()->pluck('title', 'id'))
|
->live(onBlur: true)
|
||||||
->label('Факультет')
|
->afterStateUpdated(function (string $operation, string|null $state, Forms\Set $set) {
|
||||||
->required(),
|
$set('slug', Str::slug($state));
|
||||||
Toggle::make('is_active')->default(true)->label('Активная кафедра')->inline(false),
|
$set('seo.title', $state);
|
||||||
|
}),
|
||||||
|
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
||||||
|
Toggle::make('is_active')->default(true)->label('Активный факультет')->inline(false),
|
||||||
|
Forms\Components\Select::make('faculty_id')
|
||||||
|
->options(Faculty::all()->pluck('title', 'id'))
|
||||||
|
->label('Факультет')
|
||||||
|
->required(),
|
||||||
|
]),
|
||||||
|
Tabs\Tab::make('Описание факультета')
|
||||||
|
->schema([
|
||||||
|
Builder::make('content')->label('')->blocks([
|
||||||
|
Builder\Block::make('heading')->label('Заголовок')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('id')->hidden()->integer()->default(rand(2335235,324634264263426)),
|
||||||
|
TextInput::make('content')
|
||||||
|
->label('')
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string $state, Forms\Set $set, $get) {
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('paragraph')
|
||||||
|
->schema([
|
||||||
|
RichEditor::make('content')
|
||||||
|
->toolbarButtons([
|
||||||
|
'blockquote',
|
||||||
|
'bold',
|
||||||
|
'bulletList',
|
||||||
|
'italic',
|
||||||
|
'link',
|
||||||
|
'orderedList',
|
||||||
|
'redo',
|
||||||
|
'strike',
|
||||||
|
'underline',
|
||||||
|
'undo',
|
||||||
|
])
|
||||||
|
->label(''),
|
||||||
|
])->label('Текст'),
|
||||||
|
Builder\Block::make('files')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('file')->schema([
|
||||||
|
Hidden::make('expansion')->required(),
|
||||||
|
Hidden::make('size')->required(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->getUploadedFileNameForStorageUsing(
|
||||||
|
fn (TemporaryUploadedFile $file): string =>
|
||||||
|
str(Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) . '-' . Carbon::now()->timestamp ) . '.' . $file->getClientOriginalExtension())
|
||||||
|
)
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
'application/zip'
|
||||||
|
])
|
||||||
|
->maxSize(512000)
|
||||||
|
->disk('public')
|
||||||
|
->directory('files')
|
||||||
|
->downloadable()
|
||||||
|
->afterStateUpdated(function ($set, $state) {
|
||||||
|
$set('expansion', $state?->getClientOriginalExtension());
|
||||||
|
$set('size', ByteConverter::bytesToHuman($state?->getSize()));
|
||||||
|
})
|
||||||
|
->visibility('public')
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('person')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Имя')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
FileUpload::make('photo')
|
||||||
|
->label('Фотография')
|
||||||
|
->image()
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor(),
|
||||||
|
Forms\Components\Repeater::make('info')->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('column')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
TextInput::make('content')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
]),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('stepper')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('step_name')
|
||||||
|
->label('Название шага')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\Repeater::make('steps')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
RichEditor::make('content')->required(),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('tabs')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('tab')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
\Filament\Forms\Components\Builder::make('content')->label('')->blocks([
|
||||||
|
Builder\Block::make('heading')->label('Заголовок')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('id')->hidden()->integer()->default(rand(2335235,324634264263426)),
|
||||||
|
TextInput::make('content')
|
||||||
|
->label('')
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string $state, Forms\Set $set, $get) {
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('paragraph')
|
||||||
|
->schema([
|
||||||
|
RichEditor::make('content')
|
||||||
|
->toolbarButtons([
|
||||||
|
'blockquote',
|
||||||
|
'bold',
|
||||||
|
'bulletList',
|
||||||
|
'italic',
|
||||||
|
'link',
|
||||||
|
'orderedList',
|
||||||
|
'redo',
|
||||||
|
'strike',
|
||||||
|
'underline',
|
||||||
|
'undo',
|
||||||
|
])
|
||||||
|
->label(''),
|
||||||
|
])->label('Текст'),
|
||||||
|
Builder\Block::make('files')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('file')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
'application/zip'
|
||||||
|
])
|
||||||
|
->maxSize(512000)
|
||||||
|
->disk('public')
|
||||||
|
->directory('files')
|
||||||
|
->downloadable()
|
||||||
|
->visibility('public')
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('person')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Имя')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
FileUpload::make('photo')
|
||||||
|
->label('Фотография')
|
||||||
|
->image()
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor(),
|
||||||
|
Forms\Components\Repeater::make('info')->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('column')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
TextInput::make('content')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
]),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('stepper')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('step_name')
|
||||||
|
->label('Название шага')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\Repeater::make('steps')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
RichEditor::make('content')->required(),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('images')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Слайдер изображений'),
|
||||||
|
Builder\Block::make('image')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Изображение'),
|
||||||
|
Builder\Block::make('video')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('mime')->readOnly(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'video/mp4',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/avi',
|
||||||
|
'video/webm',
|
||||||
|
'video/ogg',
|
||||||
|
'video/3gpp',
|
||||||
|
'video/3gpp2',
|
||||||
|
'video/x-m4v',
|
||||||
|
])
|
||||||
|
->disk('public')
|
||||||
|
->directory('videos')
|
||||||
|
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('postsList')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('count')
|
||||||
|
->label('Количество запией')
|
||||||
|
->integer(),
|
||||||
|
Select::make('category')
|
||||||
|
->options(Category::all()->pluck('title', 'id'))
|
||||||
|
]),
|
||||||
|
])->label('Список новостей'),
|
||||||
|
])
|
||||||
|
->collapsed()
|
||||||
|
->blockNumbers(false)
|
||||||
|
->collapsible()
|
||||||
|
->addActionLabel('Добавить новый блок'),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('images')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Слайдер изображений'),
|
||||||
|
Builder\Block::make('image')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Изображение'),
|
||||||
|
Builder\Block::make('video')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('mime')->readOnly(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'video/mp4',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/avi',
|
||||||
|
'video/webm',
|
||||||
|
'video/ogg',
|
||||||
|
'video/3gpp',
|
||||||
|
'video/3gpp2',
|
||||||
|
'video/x-m4v',
|
||||||
|
])
|
||||||
|
->disk('public')
|
||||||
|
->directory('videos')
|
||||||
|
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('postsList')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('count')
|
||||||
|
->label('Количество запией')
|
||||||
|
->integer(),
|
||||||
|
Select::make('category')
|
||||||
|
->options(Category::all()->pluck('title', 'id'))
|
||||||
|
]),
|
||||||
|
])->label('Список новостей'),
|
||||||
|
Builder\Block::make('postItem')
|
||||||
|
->schema([
|
||||||
|
Select::make('post')
|
||||||
|
->options(Post::query()->where('status', PostStatus::PUBLISHED)->pluck('title', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Новость'),
|
||||||
|
Builder\Block::make('pageItem')
|
||||||
|
->schema([
|
||||||
|
Select::make('page')
|
||||||
|
->options(Page::query()->where('title', '!=' , null)->where('is_visible', true)->pluck('title', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Страница'),
|
||||||
|
Builder\Block::make('customForm')
|
||||||
|
->schema([
|
||||||
|
Select::make('form')
|
||||||
|
->options(CustomForm::query()->where('status', CustomFormStatus::PUBLISHED)->pluck('title', 'form_id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Форма'),
|
||||||
|
Builder\Block::make('pageResourceList')
|
||||||
|
->schema([
|
||||||
|
Select::make('resource')
|
||||||
|
->options(PageReferenceList::query()->where('is_active', true)->pluck('title', 'slug'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Ресурсы'),
|
||||||
|
])
|
||||||
|
->collapsed()
|
||||||
|
->blockNumbers(false)
|
||||||
|
->collapsible()
|
||||||
|
->required()
|
||||||
|
->blockPickerColumns(3)
|
||||||
|
->blockPickerWidth('2xl')
|
||||||
|
->addActionLabel('Добавить новый блок'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public static function table(Table $table): Table
|
public static function table(Table $table): Table
|
||||||
{
|
{
|
||||||
return $table
|
return $table
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ class CreateDepartment extends CreateRecord
|
|||||||
|
|
||||||
protected array $seoData;
|
protected array $seoData;
|
||||||
|
|
||||||
|
|
||||||
protected function mutateFormDataBeforeCreate(array $data): array
|
protected function mutateFormDataBeforeCreate(array $data): array
|
||||||
{
|
{
|
||||||
$this->seoData = $this->generateSeo($data);
|
$this->seoData = $this->generateSeo($data);
|
||||||
@@ -29,20 +28,15 @@ class CreateDepartment extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,22 +62,6 @@ class CreateDepartment extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,41 +28,19 @@ class EditDepartment extends EditRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,20 +29,15 @@ class CreateDivision extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['description']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -28,41 +28,19 @@ class EditDivision extends EditRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['description']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-24
@@ -33,20 +33,15 @@ class CreateEducationalProgram extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -72,23 +67,6 @@ class CreateEducationalProgram extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
{
|
{
|
||||||
$data = "";
|
$data = "";
|
||||||
|
|||||||
@@ -13,10 +13,8 @@ class EditEducationalProgram extends EditRecord
|
|||||||
{
|
{
|
||||||
protected static string $resource = EducationalProgramResource::class;
|
protected static string $resource = EducationalProgramResource::class;
|
||||||
|
|
||||||
|
|
||||||
protected array $seoData;
|
protected array $seoData;
|
||||||
|
|
||||||
|
|
||||||
protected function mutateFormDataBeforeSave(array $data): array
|
protected function mutateFormDataBeforeSave(array $data): array
|
||||||
{
|
{
|
||||||
$this->seoData = $this->generateSeo($data);
|
$this->seoData = $this->generateSeo($data);
|
||||||
@@ -30,42 +28,18 @@ class EditEducationalProgram extends EditRecord
|
|||||||
$this->record->seo()->update($this->seoData);
|
$this->record->seo()->update($this->seoData);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+402
-8
@@ -2,17 +2,33 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources\FacultyRecourceResource\RelationManagers;
|
namespace App\Filament\Resources\FacultyRecourceResource\RelationManagers;
|
||||||
|
|
||||||
|
use App\Enums\CustomFormStatus;
|
||||||
|
use App\Enums\PostStatus;
|
||||||
|
use App\Helpers\ByteConverter;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\CustomForm;
|
||||||
use App\Models\Faculty;
|
use App\Models\Faculty;
|
||||||
|
use App\Models\Page;
|
||||||
|
use App\Models\PageReferenceList;
|
||||||
|
use App\Models\Post;
|
||||||
use Filament\Forms;
|
use Filament\Forms;
|
||||||
|
use Filament\Forms\Components\Builder;
|
||||||
|
use Filament\Forms\Components\FileUpload;
|
||||||
|
use Filament\Forms\Components\Hidden;
|
||||||
|
use Filament\Forms\Components\RichEditor;
|
||||||
|
use Filament\Forms\Components\Section;
|
||||||
|
use Filament\Forms\Components\Select;
|
||||||
|
use Filament\Forms\Components\Tabs;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Components\Toggle;
|
use Filament\Forms\Components\Toggle;
|
||||||
use Filament\Forms\Form;
|
use Filament\Forms\Form;
|
||||||
use Filament\Resources\RelationManagers\RelationManager;
|
use Filament\Resources\RelationManagers\RelationManager;
|
||||||
use Filament\Tables;
|
use Filament\Tables;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||||
|
|
||||||
class DepartmentsRelationManager extends RelationManager
|
class DepartmentsRelationManager extends RelationManager
|
||||||
{
|
{
|
||||||
@@ -25,13 +41,391 @@ class DepartmentsRelationManager extends RelationManager
|
|||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('title')->label('Название кафедры')->required()
|
Section::make()
|
||||||
->live(onBlur: true)
|
->schema([
|
||||||
->afterStateUpdated(function (string $operation, $state, Forms\Set $set) {
|
Tabs::make('Tabs')
|
||||||
$set('slug', Str::slug($state));
|
->tabs([
|
||||||
}),
|
Tabs\Tab::make('Основная информация')
|
||||||
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
->schema([
|
||||||
Toggle::make('is_active')->default(true)->label('Активная кафедра')->inline(false),
|
TextInput::make('title')->label('Название факультета')->required()
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string|null $state, Forms\Set $set) {
|
||||||
|
$set('slug', Str::slug($state));
|
||||||
|
$set('seo.title', $state);
|
||||||
|
}),
|
||||||
|
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
||||||
|
Toggle::make('is_active')->default(true)->label('Активный факультет')->inline(false),
|
||||||
|
]),
|
||||||
|
Tabs\Tab::make('Описание факультета')
|
||||||
|
->schema([
|
||||||
|
Builder::make('content')->label('')->blocks([
|
||||||
|
Builder\Block::make('heading')->label('Заголовок')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('id')->hidden()->integer()->default(rand(2335235,324634264263426)),
|
||||||
|
TextInput::make('content')
|
||||||
|
->label('')
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string $state, Forms\Set $set, $get) {
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('paragraph')
|
||||||
|
->schema([
|
||||||
|
RichEditor::make('content')
|
||||||
|
->toolbarButtons([
|
||||||
|
'blockquote',
|
||||||
|
'bold',
|
||||||
|
'bulletList',
|
||||||
|
'italic',
|
||||||
|
'link',
|
||||||
|
'orderedList',
|
||||||
|
'redo',
|
||||||
|
'strike',
|
||||||
|
'underline',
|
||||||
|
'undo',
|
||||||
|
])
|
||||||
|
->label(''),
|
||||||
|
])->label('Текст'),
|
||||||
|
Builder\Block::make('files')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('file')->schema([
|
||||||
|
Hidden::make('expansion')->required(),
|
||||||
|
Hidden::make('size')->required(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->getUploadedFileNameForStorageUsing(
|
||||||
|
fn (TemporaryUploadedFile $file): string =>
|
||||||
|
str(Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) . '-' . Carbon::now()->timestamp ) . '.' . $file->getClientOriginalExtension())
|
||||||
|
)
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
'application/zip'
|
||||||
|
])
|
||||||
|
->maxSize(512000)
|
||||||
|
->disk('public')
|
||||||
|
->directory('files')
|
||||||
|
->downloadable()
|
||||||
|
->afterStateUpdated(function ($set, $state) {
|
||||||
|
$set('expansion', $state?->getClientOriginalExtension());
|
||||||
|
$set('size', ByteConverter::bytesToHuman($state?->getSize()));
|
||||||
|
})
|
||||||
|
->visibility('public')
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('person')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Имя')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
FileUpload::make('photo')
|
||||||
|
->label('Фотография')
|
||||||
|
->image()
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor(),
|
||||||
|
Forms\Components\Repeater::make('info')->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('column')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
TextInput::make('content')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
]),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('stepper')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('step_name')
|
||||||
|
->label('Название шага')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\Repeater::make('steps')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
RichEditor::make('content')->required(),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('tabs')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('tab')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
\Filament\Forms\Components\Builder::make('content')->label('')->blocks([
|
||||||
|
Builder\Block::make('heading')->label('Заголовок')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('id')->hidden()->integer()->default(rand(2335235,324634264263426)),
|
||||||
|
TextInput::make('content')
|
||||||
|
->label('')
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string $state, Forms\Set $set, $get) {
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('paragraph')
|
||||||
|
->schema([
|
||||||
|
RichEditor::make('content')
|
||||||
|
->toolbarButtons([
|
||||||
|
'blockquote',
|
||||||
|
'bold',
|
||||||
|
'bulletList',
|
||||||
|
'italic',
|
||||||
|
'link',
|
||||||
|
'orderedList',
|
||||||
|
'redo',
|
||||||
|
'strike',
|
||||||
|
'underline',
|
||||||
|
'undo',
|
||||||
|
])
|
||||||
|
->label(''),
|
||||||
|
])->label('Текст'),
|
||||||
|
Builder\Block::make('files')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('file')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
'application/zip'
|
||||||
|
])
|
||||||
|
->maxSize(512000)
|
||||||
|
->disk('public')
|
||||||
|
->directory('files')
|
||||||
|
->downloadable()
|
||||||
|
->visibility('public')
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('person')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Имя')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
FileUpload::make('photo')
|
||||||
|
->label('Фотография')
|
||||||
|
->image()
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor(),
|
||||||
|
Forms\Components\Repeater::make('info')->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('column')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
TextInput::make('content')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
]),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('stepper')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('step_name')
|
||||||
|
->label('Название шага')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\Repeater::make('steps')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
RichEditor::make('content')->required(),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('images')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Слайдер изображений'),
|
||||||
|
Builder\Block::make('image')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Изображение'),
|
||||||
|
Builder\Block::make('video')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('mime')->readOnly(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'video/mp4',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/avi',
|
||||||
|
'video/webm',
|
||||||
|
'video/ogg',
|
||||||
|
'video/3gpp',
|
||||||
|
'video/3gpp2',
|
||||||
|
'video/x-m4v',
|
||||||
|
])
|
||||||
|
->disk('public')
|
||||||
|
->directory('videos')
|
||||||
|
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('postsList')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('count')
|
||||||
|
->label('Количество запией')
|
||||||
|
->integer(),
|
||||||
|
Select::make('category')
|
||||||
|
->options(Category::all()->pluck('title', 'id'))
|
||||||
|
]),
|
||||||
|
])->label('Список новостей'),
|
||||||
|
])
|
||||||
|
->collapsed()
|
||||||
|
->blockNumbers(false)
|
||||||
|
->collapsible()
|
||||||
|
->addActionLabel('Добавить новый блок'),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('images')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Слайдер изображений'),
|
||||||
|
Builder\Block::make('image')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Изображение'),
|
||||||
|
Builder\Block::make('video')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('mime')->readOnly(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'video/mp4',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/avi',
|
||||||
|
'video/webm',
|
||||||
|
'video/ogg',
|
||||||
|
'video/3gpp',
|
||||||
|
'video/3gpp2',
|
||||||
|
'video/x-m4v',
|
||||||
|
])
|
||||||
|
->disk('public')
|
||||||
|
->directory('videos')
|
||||||
|
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('postsList')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('count')
|
||||||
|
->label('Количество запией')
|
||||||
|
->integer(),
|
||||||
|
Select::make('category')
|
||||||
|
->options(Category::all()->pluck('title', 'id'))
|
||||||
|
]),
|
||||||
|
])->label('Список новостей'),
|
||||||
|
Builder\Block::make('postItem')
|
||||||
|
->schema([
|
||||||
|
Select::make('post')
|
||||||
|
->options(Post::query()->where('status', PostStatus::PUBLISHED)->pluck('title', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Новость'),
|
||||||
|
Builder\Block::make('pageItem')
|
||||||
|
->schema([
|
||||||
|
Select::make('page')
|
||||||
|
->options(Page::query()->where('title', '!=' , null)->where('is_visible', true)->pluck('title', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Страница'),
|
||||||
|
Builder\Block::make('customForm')
|
||||||
|
->schema([
|
||||||
|
Select::make('form')
|
||||||
|
->options(CustomForm::query()->where('status', CustomFormStatus::PUBLISHED)->pluck('title', 'form_id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Форма'),
|
||||||
|
Builder\Block::make('pageResourceList')
|
||||||
|
->schema([
|
||||||
|
Select::make('resource')
|
||||||
|
->options(PageReferenceList::query()->where('is_active', true)->pluck('title', 'slug'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Ресурсы'),
|
||||||
|
])
|
||||||
|
->collapsed()
|
||||||
|
->blockNumbers(false)
|
||||||
|
->collapsible()
|
||||||
|
->required()
|
||||||
|
->blockPickerColumns(3)
|
||||||
|
->blockPickerWidth('2xl')
|
||||||
|
->addActionLabel('Добавить новый блок'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,21 +2,37 @@
|
|||||||
|
|
||||||
namespace App\Filament\Resources;
|
namespace App\Filament\Resources;
|
||||||
|
|
||||||
|
use App\Enums\CustomFormStatus;
|
||||||
|
use App\Enums\PostStatus;
|
||||||
use App\Filament\Resources\FacultyRecourceResource\RelationManagers\DepartmentsRelationManager;
|
use App\Filament\Resources\FacultyRecourceResource\RelationManagers\DepartmentsRelationManager;
|
||||||
use App\Filament\Resources\FacultyResource\Pages;
|
use App\Filament\Resources\FacultyResource\Pages;
|
||||||
use App\Filament\Resources\FacultyResource\RelationManagers;
|
use App\Filament\Resources\FacultyResource\RelationManagers;
|
||||||
use App\Filament\Resources\FacultyResource\RelationManagers\WorkersRelationManager;
|
use App\Filament\Resources\FacultyResource\RelationManagers\WorkersRelationManager;
|
||||||
|
use App\Helpers\ByteConverter;
|
||||||
|
use App\Models\Category;
|
||||||
|
use App\Models\CustomForm;
|
||||||
use App\Models\Faculty;
|
use App\Models\Faculty;
|
||||||
|
use App\Models\Page;
|
||||||
|
use App\Models\PageReferenceList;
|
||||||
|
use App\Models\Post;
|
||||||
use Filament\Forms;
|
use Filament\Forms;
|
||||||
|
use Filament\Forms\Components\Builder;
|
||||||
|
use Filament\Forms\Components\FileUpload;
|
||||||
|
use Filament\Forms\Components\Hidden;
|
||||||
|
use Filament\Forms\Components\RichEditor;
|
||||||
|
use Filament\Forms\Components\Section;
|
||||||
|
use Filament\Forms\Components\Select;
|
||||||
|
use Filament\Forms\Components\Tabs;
|
||||||
use Filament\Forms\Components\TextInput;
|
use Filament\Forms\Components\TextInput;
|
||||||
use Filament\Forms\Components\Toggle;
|
use Filament\Forms\Components\Toggle;
|
||||||
use Filament\Forms\Form;
|
use Filament\Forms\Form;
|
||||||
use Filament\Resources\Resource;
|
use Filament\Resources\Resource;
|
||||||
use Filament\Tables;
|
use Filament\Tables;
|
||||||
use Filament\Tables\Table;
|
use Filament\Tables\Table;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
|
||||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||||
|
use Illuminate\Support\Carbon;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
|
||||||
|
|
||||||
class FacultyResource extends Resource
|
class FacultyResource extends Resource
|
||||||
{
|
{
|
||||||
@@ -36,16 +52,392 @@ class FacultyResource extends Resource
|
|||||||
{
|
{
|
||||||
return $form
|
return $form
|
||||||
->schema([
|
->schema([
|
||||||
TextInput::make('title')->label('Название факультета')->required(),
|
Section::make()
|
||||||
TextInput::make('abbreviation')->label('Аббревиатура')->required()
|
->schema([
|
||||||
->live(onBlur: true)
|
Tabs::make('Tabs')
|
||||||
->afterStateUpdated(function (string $operation, $state, Forms\Set $set) {
|
->tabs([
|
||||||
$set('slug', Str::slug($state));
|
Tabs\Tab::make('Основная информация')
|
||||||
}),
|
->schema([
|
||||||
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
TextInput::make('title')->label('Название факультета')->required()
|
||||||
Toggle::make('is_active')->default(true)->label('Активный факультет')->inline(false),
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string|null $state, Forms\Set $set) {
|
||||||
]);
|
$set('slug', Str::slug($state));
|
||||||
|
$set('seo.title', $state);
|
||||||
|
}),
|
||||||
|
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
||||||
|
Toggle::make('is_active')->default(true)->label('Активный факультет')->inline(false),
|
||||||
|
]),
|
||||||
|
Tabs\Tab::make('Описание факультета')
|
||||||
|
->schema([
|
||||||
|
Builder::make('content')->label('')->blocks([
|
||||||
|
Builder\Block::make('heading')->label('Заголовок')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('id')->hidden()->integer()->default(rand(2335235,324634264263426)),
|
||||||
|
TextInput::make('content')
|
||||||
|
->label('')
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string $state, Forms\Set $set, $get) {
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('paragraph')
|
||||||
|
->schema([
|
||||||
|
RichEditor::make('content')
|
||||||
|
->toolbarButtons([
|
||||||
|
'blockquote',
|
||||||
|
'bold',
|
||||||
|
'bulletList',
|
||||||
|
'italic',
|
||||||
|
'link',
|
||||||
|
'orderedList',
|
||||||
|
'redo',
|
||||||
|
'strike',
|
||||||
|
'underline',
|
||||||
|
'undo',
|
||||||
|
])
|
||||||
|
->label(''),
|
||||||
|
])->label('Текст'),
|
||||||
|
Builder\Block::make('files')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('file')->schema([
|
||||||
|
Hidden::make('expansion')->required(),
|
||||||
|
Hidden::make('size')->required(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->getUploadedFileNameForStorageUsing(
|
||||||
|
fn (TemporaryUploadedFile $file): string =>
|
||||||
|
str(Str::slug(pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME) . '-' . Carbon::now()->timestamp ) . '.' . $file->getClientOriginalExtension())
|
||||||
|
)
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
'application/zip'
|
||||||
|
])
|
||||||
|
->maxSize(512000)
|
||||||
|
->disk('public')
|
||||||
|
->directory('files')
|
||||||
|
->downloadable()
|
||||||
|
->afterStateUpdated(function ($set, $state) {
|
||||||
|
$set('expansion', $state?->getClientOriginalExtension());
|
||||||
|
$set('size', ByteConverter::bytesToHuman($state?->getSize()));
|
||||||
|
})
|
||||||
|
->visibility('public')
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('person')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Имя')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
FileUpload::make('photo')
|
||||||
|
->label('Фотография')
|
||||||
|
->image()
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor(),
|
||||||
|
Forms\Components\Repeater::make('info')->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('column')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
TextInput::make('content')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
]),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('stepper')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('step_name')
|
||||||
|
->label('Название шага')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\Repeater::make('steps')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
RichEditor::make('content')->required(),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('tabs')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('tab')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
\Filament\Forms\Components\Builder::make('content')->label('')->blocks([
|
||||||
|
Builder\Block::make('heading')->label('Заголовок')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('id')->hidden()->integer()->default(rand(2335235,324634264263426)),
|
||||||
|
TextInput::make('content')
|
||||||
|
->label('')
|
||||||
|
->live(onBlur: true)
|
||||||
|
->afterStateUpdated(function (string $operation, string $state, Forms\Set $set, $get) {
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('paragraph')
|
||||||
|
->schema([
|
||||||
|
RichEditor::make('content')
|
||||||
|
->toolbarButtons([
|
||||||
|
'blockquote',
|
||||||
|
'bold',
|
||||||
|
'bulletList',
|
||||||
|
'italic',
|
||||||
|
'link',
|
||||||
|
'orderedList',
|
||||||
|
'redo',
|
||||||
|
'strike',
|
||||||
|
'underline',
|
||||||
|
'undo',
|
||||||
|
])
|
||||||
|
->label(''),
|
||||||
|
])->label('Текст'),
|
||||||
|
Builder\Block::make('files')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Repeater::make('file')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'application/pdf',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
|
'application/zip'
|
||||||
|
])
|
||||||
|
->maxSize(512000)
|
||||||
|
->disk('public')
|
||||||
|
->directory('files')
|
||||||
|
->downloadable()
|
||||||
|
->visibility('public')
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('person')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('name')
|
||||||
|
->label('Имя')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
FileUpload::make('photo')
|
||||||
|
->label('Фотография')
|
||||||
|
->image()
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor(),
|
||||||
|
Forms\Components\Repeater::make('info')->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('column')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
TextInput::make('content')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
]),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('stepper')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('step_name')
|
||||||
|
->label('Название шага')
|
||||||
|
->required()
|
||||||
|
->maxLength(255),
|
||||||
|
Forms\Components\Repeater::make('steps')->schema([
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)->columnSpanFull(),
|
||||||
|
RichEditor::make('content')->required(),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('images')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Слайдер изображений'),
|
||||||
|
Builder\Block::make('image')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Изображение'),
|
||||||
|
Builder\Block::make('video')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('mime')->readOnly(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'video/mp4',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/avi',
|
||||||
|
'video/webm',
|
||||||
|
'video/ogg',
|
||||||
|
'video/3gpp',
|
||||||
|
'video/3gpp2',
|
||||||
|
'video/x-m4v',
|
||||||
|
])
|
||||||
|
->disk('public')
|
||||||
|
->directory('videos')
|
||||||
|
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('postsList')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('count')
|
||||||
|
->label('Количество запией')
|
||||||
|
->integer(),
|
||||||
|
Select::make('category')
|
||||||
|
->options(Category::all()->pluck('title', 'id'))
|
||||||
|
]),
|
||||||
|
])->label('Список новостей'),
|
||||||
|
])
|
||||||
|
->collapsed()
|
||||||
|
->blockNumbers(false)
|
||||||
|
->collapsible()
|
||||||
|
->addActionLabel('Добавить новый блок'),
|
||||||
|
])->minItems(1),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('images')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Слайдер изображений'),
|
||||||
|
Builder\Block::make('image')
|
||||||
|
->schema([
|
||||||
|
FileUpload::make('url')
|
||||||
|
->label('Изображение(-я)')
|
||||||
|
->image()
|
||||||
|
->multiple()
|
||||||
|
->reorderable()
|
||||||
|
->maxFiles(5)
|
||||||
|
->disk('public')
|
||||||
|
->directory('images')
|
||||||
|
->imageEditor()
|
||||||
|
->required(),
|
||||||
|
TextInput::make('alt')
|
||||||
|
->label('Описание')
|
||||||
|
->placeholder('Необязяательно')
|
||||||
|
])->label('Изображение'),
|
||||||
|
Builder\Block::make('video')
|
||||||
|
->schema([
|
||||||
|
TextInput::make('mime')->readOnly(),
|
||||||
|
TextInput::make('title')
|
||||||
|
->required()
|
||||||
|
->maxLength(255)
|
||||||
|
->autofocus(),
|
||||||
|
FileUpload::make('path')
|
||||||
|
->required()
|
||||||
|
->acceptedFileTypes([
|
||||||
|
'video/mp4',
|
||||||
|
'video/quicktime',
|
||||||
|
'video/x-msvideo',
|
||||||
|
'video/x-ms-wmv',
|
||||||
|
'video/avi',
|
||||||
|
'video/webm',
|
||||||
|
'video/ogg',
|
||||||
|
'video/3gpp',
|
||||||
|
'video/3gpp2',
|
||||||
|
'video/x-m4v',
|
||||||
|
])
|
||||||
|
->disk('public')
|
||||||
|
->directory('videos')
|
||||||
|
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||||
|
]),
|
||||||
|
Builder\Block::make('postsList')
|
||||||
|
->schema([
|
||||||
|
Forms\Components\Grid::make(2)->schema([
|
||||||
|
TextInput::make('count')
|
||||||
|
->label('Количество запией')
|
||||||
|
->integer(),
|
||||||
|
Select::make('category')
|
||||||
|
->options(Category::all()->pluck('title', 'id'))
|
||||||
|
]),
|
||||||
|
])->label('Список новостей'),
|
||||||
|
Builder\Block::make('postItem')
|
||||||
|
->schema([
|
||||||
|
Select::make('post')
|
||||||
|
->options(Post::query()->where('status', PostStatus::PUBLISHED)->pluck('title', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Новость'),
|
||||||
|
Builder\Block::make('pageItem')
|
||||||
|
->schema([
|
||||||
|
Select::make('page')
|
||||||
|
->options(Page::query()->where('title', '!=' , null)->where('is_visible', true)->pluck('title', 'id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Страница'),
|
||||||
|
Builder\Block::make('customForm')
|
||||||
|
->schema([
|
||||||
|
Select::make('form')
|
||||||
|
->options(CustomForm::query()->where('status', CustomFormStatus::PUBLISHED)->pluck('title', 'form_id'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Форма'),
|
||||||
|
Builder\Block::make('pageResourceList')
|
||||||
|
->schema([
|
||||||
|
Select::make('resource')
|
||||||
|
->options(PageReferenceList::query()->where('is_active', true)->pluck('title', 'slug'))
|
||||||
|
->searchable()
|
||||||
|
->required(),
|
||||||
|
])->label('Ресурсы'),
|
||||||
|
])
|
||||||
|
->collapsed()
|
||||||
|
->blockNumbers(false)
|
||||||
|
->collapsible()
|
||||||
|
->required()
|
||||||
|
->blockPickerColumns(3)
|
||||||
|
->blockPickerWidth('2xl')
|
||||||
|
->addActionLabel('Добавить новый блок'),
|
||||||
|
]),
|
||||||
|
]),
|
||||||
|
])
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function table(Table $table): Table
|
public static function table(Table $table): Table
|
||||||
@@ -70,7 +462,6 @@ class FacultyResource extends Resource
|
|||||||
public static function getRelations(): array
|
public static function getRelations(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
DepartmentsRelationManager::class,
|
|
||||||
WorkersRelationManager::class
|
WorkersRelationManager::class
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,20 +29,15 @@ class CreateFaculty extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,22 +63,6 @@ class CreateFaculty extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,41 +28,19 @@ class EditFaculty extends EditRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,20 +29,15 @@ class CreateLibraryNews extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,22 +63,6 @@ class CreateLibraryNews extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -28,41 +28,18 @@ class EditLibraryNews extends EditRecord
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,20 +29,15 @@ class CreateVirtualExhibition extends CreateRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
|
}
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,22 +63,6 @@ class CreateVirtualExhibition extends CreateRecord
|
|||||||
return $data;
|
return $data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getBlockBySeoActiveState(string $name, array $content) : array|null
|
|
||||||
{
|
|
||||||
$data = [];
|
|
||||||
foreach ($content as $block) {
|
|
||||||
if ($block['type'] === $name) {
|
|
||||||
$data[] = $block;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$block = null;
|
|
||||||
foreach ($data as $item) {
|
|
||||||
if ($item['data']['seo_active'] === true) {
|
|
||||||
$block = $item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return $block;
|
|
||||||
}
|
|
||||||
|
|
||||||
private function getDataFromBlocks($block) : string
|
private function getDataFromBlocks($block) : string
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -48,21 +48,15 @@ class EditVirtualExhibition extends EditRecord
|
|||||||
private function generateSeo(array $data) : array
|
private function generateSeo(array $data) : array
|
||||||
{
|
{
|
||||||
$title = $data['title'];
|
$title = $data['title'];
|
||||||
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
|
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||||
if ($rowData === null) {
|
|
||||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
|
||||||
}
|
|
||||||
if ($rowData !== null) {
|
if ($rowData !== null) {
|
||||||
$description = strip_tags($rowData['data']['content']);
|
$description = strip_tags($rowData['data']['content']);
|
||||||
} else {
|
} else {
|
||||||
$description = null;
|
$description = null;
|
||||||
}
|
}
|
||||||
$image = ($this->record->preview !== null) ? $this->record->preview : null;
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'title' => $title,
|
'title' => $title,
|
||||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||||
'image' => $image,
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -134,6 +134,8 @@ class ClientAdditionalEducationController extends Controller
|
|||||||
$breadcrumbs = null;
|
$breadcrumbs = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inertia::render('Client/Additional-educations/Show', compact('additionalEducation', 'breadcrumbs'));
|
$seo = $additionalEducation->seo;
|
||||||
|
|
||||||
|
return Inertia::render('Client/Additional-educations/Show', compact('additionalEducation', 'breadcrumbs', 'seo'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ class ClientDepartmentController extends Controller
|
|||||||
->with(['faculty', 'workers.userDetail', 'teachers.userDetail', 'programs.directionStudy'])
|
->with(['faculty', 'workers.userDetail', 'teachers.userDetail', 'programs.directionStudy'])
|
||||||
->first());
|
->first());
|
||||||
$directions = $this->groupProgramsByDirection($department->programs);
|
$directions = $this->groupProgramsByDirection($department->programs);
|
||||||
return Inertia::render('Client/Departments/Show', compact('department', 'departments', 'directions'));
|
|
||||||
|
$seo = $department->seo;
|
||||||
|
return Inertia::render('Client/Departments/Show', compact('department', 'departments', 'directions', 'seo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ class ClientDivisionController extends Controller
|
|||||||
{
|
{
|
||||||
$divisions = DivisionResource::collection(Division::query()->where('is_active', true)->get());
|
$divisions = DivisionResource::collection(Division::query()->where('is_active', true)->get());
|
||||||
$division = new DivisionResource(Division::with('workers.userDetail')->where('is_active', true)->where('slug', $slug)->first());
|
$division = new DivisionResource(Division::with('workers.userDetail')->where('is_active', true)->where('slug', $slug)->first());
|
||||||
return Inertia::render('Client/Divisions/Show', compact('divisions', 'division'));
|
$seo = $division->seo;
|
||||||
|
return Inertia::render('Client/Divisions/Show', compact('divisions', 'division', 'seo'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,10 +16,12 @@ class ClientFacultyController extends Controller
|
|||||||
return Inertia::render('Client/Faculties/Index', compact('faculties'));
|
return Inertia::render('Client/Faculties/Index', compact('faculties'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public function show(string $slug)
|
public function show(string $slug)
|
||||||
{
|
{
|
||||||
$faculties = FacultyResource::collection(Faculty::query()->where('is_active', true)->get());
|
$faculties = FacultyResource::collection(Faculty::query()->where('is_active', true)->get());
|
||||||
$faculty = new FullFacultyResource(Faculty::where('slug', $slug)->where('is_active', true)->with(['departments.faculty', 'workers.userDetail'])->first());
|
$faculty = new FullFacultyResource(Faculty::where('slug', $slug)->where('is_active', true)->with(['departments.faculty', 'workers.userDetail'])->first());
|
||||||
return Inertia::render('Client/Faculties/Show', compact('faculty', 'faculties'));
|
$seo = $faculty->seo;
|
||||||
|
return Inertia::render('Client/Faculties/Show', compact('faculty', 'faculties', 'seo'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,9 @@ class ClientProgramController extends Controller
|
|||||||
$formsEdu = $formsEducational->mapWithKeys(function ($formEducational) {
|
$formsEdu = $formsEducational->mapWithKeys(function ($formEducational) {
|
||||||
return [$formEducational->value => $formEducational->getLabel()];
|
return [$formEducational->value => $formEducational->getLabel()];
|
||||||
});
|
});
|
||||||
return Inertia::render('Client/Programs/Show', compact('program', 'formsEdu'));
|
|
||||||
|
$seo = $this->seo;
|
||||||
|
return Inertia::render('Client/Programs/Show', compact('program', 'formsEdu', 'seo'));
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getAdmissionCampaignName() : string
|
private function getAdmissionCampaignName() : string
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Enums\PostStatus;
|
||||||
|
use App\Models\Page;
|
||||||
|
use App\Models\Post;
|
||||||
|
use Spatie\Sitemap\Sitemap;
|
||||||
|
use Spatie\Sitemap\Tags\Url;
|
||||||
|
|
||||||
|
class GenerateSitemapController extends Controller
|
||||||
|
{
|
||||||
|
public function index()
|
||||||
|
{
|
||||||
|
$sitemap = Sitemap::create();
|
||||||
|
|
||||||
|
$this->generatePages($sitemap);
|
||||||
|
$this->generatePosts($sitemap);
|
||||||
|
|
||||||
|
$sitemap->writeToFile(public_path('sitemap.xml'));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePages(Sitemap $sitemap)
|
||||||
|
{
|
||||||
|
$pages = Page::query()
|
||||||
|
->where('is_visible', true)
|
||||||
|
->where('code', 200)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$this->addUrlsToSitemap($sitemap, $pages, function($page) {
|
||||||
|
return [
|
||||||
|
'path' => "/{$page->path}",
|
||||||
|
'lastModificationDate' => $page->updated_at,
|
||||||
|
'priority' => 0.5,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function generatePosts(Sitemap $sitemap)
|
||||||
|
{
|
||||||
|
$posts = Post::query()
|
||||||
|
->where('status', PostStatus::PUBLISHED)
|
||||||
|
->get();
|
||||||
|
|
||||||
|
$this->addUrlsToSitemap($sitemap, $posts, function($post) {
|
||||||
|
return [
|
||||||
|
'path' => "/news/{$post->slug}",
|
||||||
|
'lastModificationDate' => $post->updated_at,
|
||||||
|
'priority' => 0.5,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addUrlsToSitemap(Sitemap $sitemap, $items, callable $callback)
|
||||||
|
{
|
||||||
|
foreach ($items as $item) {
|
||||||
|
$urlData = $callback($item);
|
||||||
|
$sitemap->add(Url::create($urlData['path'])
|
||||||
|
->setLastModificationDate($urlData['lastModificationDate'])
|
||||||
|
->setPriority($urlData['priority']));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -14,8 +14,10 @@ use App\Models\AdditionalEducation;
|
|||||||
use App\Models\EducationalGroup;
|
use App\Models\EducationalGroup;
|
||||||
use App\Models\EducationalProgram;
|
use App\Models\EducationalProgram;
|
||||||
use App\Models\Event;
|
use App\Models\Event;
|
||||||
|
use App\Models\Faculty;
|
||||||
use App\Models\Page;
|
use App\Models\Page;
|
||||||
use App\Models\Post;
|
use App\Models\Post;
|
||||||
|
use App\Models\User;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Pagination\LengthAwarePaginator;
|
use Illuminate\Pagination\LengthAwarePaginator;
|
||||||
use Illuminate\Support\Collection;
|
use Illuminate\Support\Collection;
|
||||||
@@ -43,6 +45,8 @@ class SearchController extends Controller
|
|||||||
->add(AdditionalEducation::where('is_active', '=', true), 'title')
|
->add(AdditionalEducation::where('is_active', '=', true), 'title')
|
||||||
->add(EducationalGroup::with('schedules'), 'title')
|
->add(EducationalGroup::with('schedules'), 'title')
|
||||||
->add(EducationalProgram::where('status', '=', true)->whereHas('admission_plans'), 'name')
|
->add(EducationalProgram::where('status', '=', true)->whereHas('admission_plans'), 'name')
|
||||||
|
->add(Faculty::where('is_active', '=', true), 'title')
|
||||||
|
->add(User::whereHas('userDetail'), ['name', 'userDetail.education', 'userDetail.awards', 'userDetail.publications',])
|
||||||
->beginWithWildcard()
|
->beginWithWildcard()
|
||||||
->orderByRelevance()
|
->orderByRelevance()
|
||||||
->includeModelType()
|
->includeModelType()
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class AppServiceProvider extends ServiceProvider
|
|||||||
setlocale(LC_TIME, 'ru_RU.UTF-8');
|
setlocale(LC_TIME, 'ru_RU.UTF-8');
|
||||||
Carbon::setLocale(config('app.locale'));
|
Carbon::setLocale(config('app.locale'));
|
||||||
Model::preventLazyLoading(!app()->isProduction());
|
Model::preventLazyLoading(!app()->isProduction());
|
||||||
URL::forceScheme('https');
|
// URL::forceScheme('https');
|
||||||
self::registerFilamentNavigationGroups();
|
self::registerFilamentNavigationGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
"nesbot/carbon": "^2.71",
|
"nesbot/carbon": "^2.71",
|
||||||
"protonemedia/laravel-cross-eloquent-search": "^3.4",
|
"protonemedia/laravel-cross-eloquent-search": "^3.4",
|
||||||
"pxlrbt/filament-excel": "^2.3",
|
"pxlrbt/filament-excel": "^2.3",
|
||||||
|
"spatie/laravel-sitemap": "^7.2",
|
||||||
"symfony/filesystem": "^6.3",
|
"symfony/filesystem": "^6.3",
|
||||||
"tightenco/ziggy": "^1.0",
|
"tightenco/ziggy": "^1.0",
|
||||||
"vkcom/vk-php-sdk": "^5.131",
|
"vkcom/vk-php-sdk": "^5.131",
|
||||||
|
|||||||
Generated
+454
-3
@@ -4,7 +4,7 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"content-hash": "4ec8fd7d71eed92d6bd7cd1106725919",
|
"content-hash": "54c73bafbbc855a5a9df56d74018c728",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "anourvalar/eloquent-serialize",
|
"name": "anourvalar/eloquent-serialize",
|
||||||
@@ -4859,6 +4859,60 @@
|
|||||||
},
|
},
|
||||||
"time": "2024-08-07T15:39:19+00:00"
|
"time": "2024-08-07T15:39:19+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "nicmart/tree",
|
||||||
|
"version": "0.8.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/nicmart/Tree.git",
|
||||||
|
"reference": "8d02952acc9779a2c14f7a9c4ac1650c3dacb545"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/nicmart/Tree/zipball/8d02952acc9779a2c14f7a9c4ac1650c3dacb545",
|
||||||
|
"reference": "8d02952acc9779a2c14f7a9c4ac1650c3dacb545",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"ergebnis/composer-normalize": "^2.31.0",
|
||||||
|
"ergebnis/license": "^2.4.0",
|
||||||
|
"ergebnis/php-cs-fixer-config": "^6.13.0",
|
||||||
|
"fakerphp/faker": "^1.23.0",
|
||||||
|
"infection/infection": "~0.26.19",
|
||||||
|
"phpunit/phpunit": "^9.6.14",
|
||||||
|
"psalm/plugin-phpunit": "~0.18.4",
|
||||||
|
"vimeo/psalm": "^5.16.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Tree\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Nicolò Martini",
|
||||||
|
"email": "nicmartnic@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Andreas Möller",
|
||||||
|
"email": "am@localheinz.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "A basic but flexible php tree data structure and a fluent tree builder implementation.",
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/nicmart/Tree/issues",
|
||||||
|
"source": "https://github.com/nicmart/Tree/tree/0.8.0"
|
||||||
|
},
|
||||||
|
"time": "2023-12-02T13:24:56+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "nikic/php-parser",
|
"name": "nikic/php-parser",
|
||||||
"version": "v5.2.0",
|
"version": "v5.2.0",
|
||||||
@@ -6329,6 +6383,74 @@
|
|||||||
],
|
],
|
||||||
"time": "2022-12-17T21:53:22+00:00"
|
"time": "2022-12-17T21:53:22+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/browsershot",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/browsershot.git",
|
||||||
|
"reference": "601f2758191d8c46b2ea587eea935a87da4f39e8"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/browsershot/zipball/601f2758191d8c46b2ea587eea935a87da4f39e8",
|
||||||
|
"reference": "601f2758191d8c46b2ea587eea935a87da4f39e8",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"ext-fileinfo": "*",
|
||||||
|
"ext-json": "*",
|
||||||
|
"php": "^8.2",
|
||||||
|
"spatie/temporary-directory": "^2.0",
|
||||||
|
"symfony/process": "^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"pestphp/pest": "^1.20",
|
||||||
|
"spatie/image": "^3.6",
|
||||||
|
"spatie/pdf-to-text": "^1.52",
|
||||||
|
"spatie/phpunit-snapshot-assertions": "^4.2.3"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\Browsershot\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://github.com/freekmurze",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Convert a webpage to an image or pdf using headless Chrome",
|
||||||
|
"homepage": "https://github.com/spatie/browsershot",
|
||||||
|
"keywords": [
|
||||||
|
"chrome",
|
||||||
|
"convert",
|
||||||
|
"headless",
|
||||||
|
"image",
|
||||||
|
"pdf",
|
||||||
|
"puppeteer",
|
||||||
|
"screenshot",
|
||||||
|
"webpage"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/spatie/browsershot/tree/4.3.0"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-08-22T09:14:07+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/color",
|
"name": "spatie/color",
|
||||||
"version": "1.6.0",
|
"version": "1.6.0",
|
||||||
@@ -6388,6 +6510,74 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-09-20T14:00:15+00:00"
|
"time": "2024-09-20T14:00:15+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/crawler",
|
||||||
|
"version": "8.2.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/crawler.git",
|
||||||
|
"reference": "c659f2fe4954249755990e42394a14d6d847a0a7"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/crawler/zipball/c659f2fe4954249755990e42394a14d6d847a0a7",
|
||||||
|
"reference": "c659f2fe4954249755990e42394a14d6d847a0a7",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "^7.3",
|
||||||
|
"guzzlehttp/psr7": "^2.0",
|
||||||
|
"illuminate/collections": "^10.0|^11.0",
|
||||||
|
"nicmart/tree": "^0.8.0",
|
||||||
|
"php": "^8.1",
|
||||||
|
"spatie/browsershot": "^3.45|^4.0",
|
||||||
|
"spatie/robots-txt": "^2.0",
|
||||||
|
"symfony/dom-crawler": "^6.0|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"pestphp/pest": "^2.0",
|
||||||
|
"spatie/ray": "^1.37"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\Crawler\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Crawl all internal links found on a website",
|
||||||
|
"homepage": "https://github.com/spatie/crawler",
|
||||||
|
"keywords": [
|
||||||
|
"crawler",
|
||||||
|
"link",
|
||||||
|
"spatie",
|
||||||
|
"website"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/crawler/issues",
|
||||||
|
"source": "https://github.com/spatie/crawler/tree/8.2.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-07-31T10:46:19+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/eloquent-sortable",
|
"name": "spatie/eloquent-sortable",
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
@@ -6663,6 +6853,79 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-06-22T23:04:52+00:00"
|
"time": "2024-06-22T23:04:52+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/laravel-sitemap",
|
||||||
|
"version": "7.2.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/laravel-sitemap.git",
|
||||||
|
"reference": "6d3d7637690a9710456a01bacabf5088f93ffe11"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/laravel-sitemap/zipball/6d3d7637690a9710456a01bacabf5088f93ffe11",
|
||||||
|
"reference": "6d3d7637690a9710456a01bacabf5088f93ffe11",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "^7.8",
|
||||||
|
"illuminate/support": "^10.0|^11.0",
|
||||||
|
"nesbot/carbon": "^2.71|^3.0",
|
||||||
|
"php": "^8.2",
|
||||||
|
"spatie/crawler": "^8.0.1",
|
||||||
|
"spatie/laravel-package-tools": "^1.16.1",
|
||||||
|
"symfony/dom-crawler": "^6.3.4|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "^1.6.6",
|
||||||
|
"orchestra/testbench": "^8.14|^9.0",
|
||||||
|
"pestphp/pest": "^2.24",
|
||||||
|
"spatie/pest-plugin-snapshots": "^2.1",
|
||||||
|
"spatie/phpunit-snapshot-assertions": "^5.1.2",
|
||||||
|
"spatie/temporary-directory": "^2.2"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"laravel": {
|
||||||
|
"providers": [
|
||||||
|
"Spatie\\Sitemap\\SitemapServiceProvider"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\Sitemap\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Freek Van der Herten",
|
||||||
|
"email": "freek@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Create and generate sitemaps with ease",
|
||||||
|
"homepage": "https://github.com/spatie/laravel-sitemap",
|
||||||
|
"keywords": [
|
||||||
|
"laravel-sitemap",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/spatie/laravel-sitemap/tree/7.2.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-05-21T12:31:34+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/laravel-tags",
|
"name": "spatie/laravel-tags",
|
||||||
"version": "4.6.1",
|
"version": "4.6.1",
|
||||||
@@ -6815,6 +7078,66 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-07-24T14:26:27+00:00"
|
"time": "2024-07-24T14:26:27+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/robots-txt",
|
||||||
|
"version": "2.2.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/robots-txt.git",
|
||||||
|
"reference": "31763e5ca23fb0efa6dc6b700beb5ebfeab89432"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/robots-txt/zipball/31763e5ca23fb0efa6dc6b700beb5ebfeab89432",
|
||||||
|
"reference": "31763e5ca23fb0efa6dc6b700beb5ebfeab89432",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.1"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.0|^10.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\Robots\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Brent Roose",
|
||||||
|
"email": "brent@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Determine if a page may be crawled from robots.txt and robots meta tags",
|
||||||
|
"homepage": "https://github.com/spatie/robots-txt",
|
||||||
|
"keywords": [
|
||||||
|
"robots-txt",
|
||||||
|
"spatie"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/robots-txt/issues",
|
||||||
|
"source": "https://github.com/spatie/robots-txt/tree/2.2.3"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-10-22T08:17:03+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "spatie/shiki-php",
|
"name": "spatie/shiki-php",
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@@ -6879,6 +7202,67 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-02-19T09:00:59+00:00"
|
"time": "2024-02-19T09:00:59+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "spatie/temporary-directory",
|
||||||
|
"version": "2.2.1",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/spatie/temporary-directory.git",
|
||||||
|
"reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/spatie/temporary-directory/zipball/76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a",
|
||||||
|
"reference": "76949fa18f8e1a7f663fd2eaa1d00e0bcea0752a",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": "^8.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "^9.5"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Spatie\\TemporaryDirectory\\": "src"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Alex Vanderbist",
|
||||||
|
"email": "alex@spatie.be",
|
||||||
|
"homepage": "https://spatie.be",
|
||||||
|
"role": "Developer"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Easily create, use and destroy temporary directories",
|
||||||
|
"homepage": "https://github.com/spatie/temporary-directory",
|
||||||
|
"keywords": [
|
||||||
|
"php",
|
||||||
|
"spatie",
|
||||||
|
"temporary-directory"
|
||||||
|
],
|
||||||
|
"support": {
|
||||||
|
"issues": "https://github.com/spatie/temporary-directory/issues",
|
||||||
|
"source": "https://github.com/spatie/temporary-directory/tree/2.2.1"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://spatie.be/open-source/support-us",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/spatie",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2023-12-25T11:46:58+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/console",
|
"name": "symfony/console",
|
||||||
"version": "v6.4.12",
|
"version": "v6.4.12",
|
||||||
@@ -7105,6 +7489,73 @@
|
|||||||
],
|
],
|
||||||
"time": "2024-04-18T09:32:20+00:00"
|
"time": "2024-04-18T09:32:20+00:00"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "symfony/dom-crawler",
|
||||||
|
"version": "v7.1.6",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/symfony/dom-crawler.git",
|
||||||
|
"reference": "794ddd5481ba15d8a04132c95e211cd5656e09fb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/symfony/dom-crawler/zipball/794ddd5481ba15d8a04132c95e211cd5656e09fb",
|
||||||
|
"reference": "794ddd5481ba15d8a04132c95e211cd5656e09fb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"masterminds/html5": "^2.6",
|
||||||
|
"php": ">=8.2",
|
||||||
|
"symfony/polyfill-ctype": "~1.8",
|
||||||
|
"symfony/polyfill-mbstring": "~1.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"symfony/css-selector": "^6.4|^7.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Symfony\\Component\\DomCrawler\\": ""
|
||||||
|
},
|
||||||
|
"exclude-from-classmap": [
|
||||||
|
"/Tests/"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Fabien Potencier",
|
||||||
|
"email": "fabien@symfony.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Symfony Community",
|
||||||
|
"homepage": "https://symfony.com/contributors"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Eases DOM navigation for HTML and XML documents",
|
||||||
|
"homepage": "https://symfony.com",
|
||||||
|
"support": {
|
||||||
|
"source": "https://github.com/symfony/dom-crawler/tree/v7.1.6"
|
||||||
|
},
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"url": "https://symfony.com/sponsor",
|
||||||
|
"type": "custom"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://github.com/fabpot",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||||
|
"type": "tidelift"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"time": "2024-10-25T15:11:02+00:00"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "symfony/error-handler",
|
"name": "symfony/error-handler",
|
||||||
"version": "v6.4.10",
|
"version": "v6.4.10",
|
||||||
@@ -11802,13 +12253,13 @@
|
|||||||
],
|
],
|
||||||
"aliases": [],
|
"aliases": [],
|
||||||
"minimum-stability": "dev",
|
"minimum-stability": "dev",
|
||||||
"stability-flags": [],
|
"stability-flags": {},
|
||||||
"prefer-stable": true,
|
"prefer-stable": true,
|
||||||
"prefer-lowest": false,
|
"prefer-lowest": false,
|
||||||
"platform": {
|
"platform": {
|
||||||
"php": "^8.1",
|
"php": "^8.1",
|
||||||
"ext-curl": "*"
|
"ext-curl": "*"
|
||||||
},
|
},
|
||||||
"platform-dev": [],
|
"platform-dev": {},
|
||||||
"plugin-api-version": "2.6.0"
|
"plugin-api-version": "2.6.0"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use GuzzleHttp\RequestOptions;
|
||||||
|
use Spatie\Sitemap\Crawler\Profile;
|
||||||
|
|
||||||
|
return [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* These options will be passed to GuzzleHttp\Client when it is created.
|
||||||
|
* For in-depth information on all options see the Guzzle docs:
|
||||||
|
*
|
||||||
|
* http://docs.guzzlephp.org/en/stable/request-options.html
|
||||||
|
*/
|
||||||
|
'guzzle_options' => [
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Whether or not cookies are used in a request.
|
||||||
|
*/
|
||||||
|
RequestOptions::COOKIES => true,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The number of seconds to wait while trying to connect to a server.
|
||||||
|
* Use 0 to wait indefinitely.
|
||||||
|
*/
|
||||||
|
RequestOptions::CONNECT_TIMEOUT => 10,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The timeout of the request in seconds. Use 0 to wait indefinitely.
|
||||||
|
*/
|
||||||
|
RequestOptions::TIMEOUT => 10,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Describes the redirect behavior of a request.
|
||||||
|
*/
|
||||||
|
RequestOptions::ALLOW_REDIRECTS => false,
|
||||||
|
],
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The sitemap generator can execute JavaScript on each page so it will
|
||||||
|
* discover links that are generated by your JS scripts. This feature
|
||||||
|
* is powered by headless Chrome.
|
||||||
|
*/
|
||||||
|
'execute_javascript' => false,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The package will make an educated guess as to where Google Chrome is installed.
|
||||||
|
* You can also manually pass its location here.
|
||||||
|
*/
|
||||||
|
'chrome_binary_path' => null,
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The sitemap generator uses a CrawlProfile implementation to determine
|
||||||
|
* which urls should be crawled for the sitemap.
|
||||||
|
*/
|
||||||
|
'crawl_profile' => Profile::class,
|
||||||
|
|
||||||
|
];
|
||||||
@@ -17,11 +17,13 @@ import ProgramTitle from "@/Components/BuilderUi/AdditionalEducationPrograms/Pro
|
|||||||
import ProgramBuilder from "@/Components/BuilderUi/AdditionalEducationPrograms/ProgramBuilder.vue";
|
import ProgramBuilder from "@/Components/BuilderUi/AdditionalEducationPrograms/ProgramBuilder.vue";
|
||||||
import AdditionalEducationProgramItemBreadcrumbs
|
import AdditionalEducationProgramItemBreadcrumbs
|
||||||
from "@/Components/BuilderUi/AdditionalEducationPrograms/AdditionalEducationProgramItemBreadcrumbs.vue";
|
from "@/Components/BuilderUi/AdditionalEducationPrograms/AdditionalEducationProgramItemBreadcrumbs.vue";
|
||||||
|
import AppHead from "@/Components/AppHead.vue";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Show",
|
name: "Show",
|
||||||
components: {
|
components: {
|
||||||
|
AppHead,
|
||||||
AdditionalEducationProgramItemBreadcrumbs,
|
AdditionalEducationProgramItemBreadcrumbs,
|
||||||
ProgramBuilder,
|
ProgramBuilder,
|
||||||
ProgramTitle,
|
ProgramTitle,
|
||||||
@@ -34,7 +36,7 @@ export default {
|
|||||||
AdminIndexHeader,
|
AdminIndexHeader,
|
||||||
ClientPost,
|
ClientPost,
|
||||||
ClientPostFilter,
|
ClientPostFilter,
|
||||||
ClientFooterDown, ClientScrollTimeline, Link, FsLightbox, Head},
|
ClientFooterDown, ClientScrollTimeline, Link, Head},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
|
||||||
@@ -45,7 +47,10 @@ export default {
|
|||||||
type: Object,
|
type: Object,
|
||||||
},
|
},
|
||||||
breadcrumbs: {
|
breadcrumbs: {
|
||||||
type: Object
|
type: Object,
|
||||||
|
},
|
||||||
|
seo: {
|
||||||
|
type: Object,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -65,10 +70,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Head>
|
<AppHead
|
||||||
<title>Образовательная программа</title>
|
:title="seo.title"
|
||||||
<meta name="description" content="Your page description">
|
:description="seo.description"
|
||||||
</Head>
|
/>
|
||||||
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
||||||
|
|
||||||
<div class="flex flex-col h-screen">
|
<div class="flex flex-col h-screen">
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<Head>
|
|
||||||
<title>{{ department.data.title }}</title>
|
<AppHead
|
||||||
<meta name="description" content="Your page description">
|
:title="seo.title"
|
||||||
</Head>
|
:description="seo.description"
|
||||||
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
/>
|
||||||
|
|
||||||
|
<MainPageNavBar class="border-b" :sections="$page.props.navigation" />
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-col h-screen justify-between">
|
<div class="flex flex-col h-screen justify-between">
|
||||||
<div class="relative mb-auto mx-auto mt-[67px] max-w-screen-xl px-4 py-10 md:flex md:flex-row md:py-10">
|
<div class="relative mb-auto mx-auto mt-[67px] max-w-screen-xl px-4 py-10 md:flex md:flex-row md:py-10">
|
||||||
@@ -166,6 +169,7 @@ import DepartmentBuilder from "@/Components/BuilderUi/Departments/DepartmentBuil
|
|||||||
import DepartmentBackButton from "@/Components/BuilderUi/Departments/DepartmentBackButton.vue";
|
import DepartmentBackButton from "@/Components/BuilderUi/Departments/DepartmentBackButton.vue";
|
||||||
import MainPageNavBar from "@/Navbars/MainPageNavbar.vue";
|
import MainPageNavBar from "@/Navbars/MainPageNavbar.vue";
|
||||||
import DepartmentItemBreadcrumbs from "@/Components/BuilderUi/Departments/DepartmentItemBreadcrumbs.vue";
|
import DepartmentItemBreadcrumbs from "@/Components/BuilderUi/Departments/DepartmentItemBreadcrumbs.vue";
|
||||||
|
import AppHead from "@/Components/AppHead.vue";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -187,9 +191,13 @@ export default {
|
|||||||
directions: {
|
directions: {
|
||||||
type: Object
|
type: Object
|
||||||
},
|
},
|
||||||
|
seo: {
|
||||||
|
type: Object
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
AppHead,
|
||||||
DepartmentItemBreadcrumbs,
|
DepartmentItemBreadcrumbs,
|
||||||
MainPageNavBar,
|
MainPageNavBar,
|
||||||
DepartmentBackButton,
|
DepartmentBackButton,
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<Head>
|
<AppHead
|
||||||
<title>{{ division.data.title }}</title>
|
:title="seo.title"
|
||||||
<meta name="description" content="Your page description">
|
:description="seo.description"
|
||||||
</Head>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-col h-screen">
|
<div class="flex flex-col h-screen">
|
||||||
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
||||||
@@ -142,6 +140,7 @@ import axios from "axios";
|
|||||||
import MainPageNavBar from "@/Navbars/MainPageNavbar.vue";
|
import MainPageNavBar from "@/Navbars/MainPageNavbar.vue";
|
||||||
import DivisionBuilder from "@/Components/BuilderUi/Divisions/DivisionBuilder.vue";
|
import DivisionBuilder from "@/Components/BuilderUi/Divisions/DivisionBuilder.vue";
|
||||||
import DivisionItemBreadcrumbs from "@/Components/BuilderUi/Divisions/DivisionItemBreadcrumbs.vue";
|
import DivisionItemBreadcrumbs from "@/Components/BuilderUi/Divisions/DivisionItemBreadcrumbs.vue";
|
||||||
|
import AppHead from "@/Components/AppHead.vue";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -160,9 +159,13 @@ export default {
|
|||||||
divisions: {
|
divisions: {
|
||||||
type: Object
|
type: Object
|
||||||
},
|
},
|
||||||
|
seo: {
|
||||||
|
type: Object,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
AppHead,
|
||||||
DivisionItemBreadcrumbs,
|
DivisionItemBreadcrumbs,
|
||||||
DivisionBuilder,
|
DivisionBuilder,
|
||||||
MainPageNavBar,
|
MainPageNavBar,
|
||||||
|
|||||||
@@ -1,11 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<Head>
|
<AppHead
|
||||||
<title>{{ faculty.data.title }}</title>
|
:title="seo.title"
|
||||||
<meta name="description" content="Your page description">
|
:description="seo.description"
|
||||||
</Head>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div class="flex flex-col h-screen justify-between">
|
<div class="flex flex-col h-screen justify-between">
|
||||||
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
||||||
@@ -161,6 +158,7 @@ import PostBuilder from "@/Components/BuilderUi/Posts/PostBuilder.vue";
|
|||||||
import FacultyBuilder from "@/Components/BuilderUi/Faculties/FacultyBuilder.vue";
|
import FacultyBuilder from "@/Components/BuilderUi/Faculties/FacultyBuilder.vue";
|
||||||
import MainPageNavBar from "@/Navbars/MainPageNavbar.vue";
|
import MainPageNavBar from "@/Navbars/MainPageNavbar.vue";
|
||||||
import FacultyItemBreadcrumbs from "@/Components/BuilderUi/Faculties/FacultyItemBreadcrumbs.vue";
|
import FacultyItemBreadcrumbs from "@/Components/BuilderUi/Faculties/FacultyItemBreadcrumbs.vue";
|
||||||
|
import AppHead from "@/Components/AppHead.vue";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
@@ -179,9 +177,13 @@ export default {
|
|||||||
faculties: {
|
faculties: {
|
||||||
type: Object
|
type: Object
|
||||||
},
|
},
|
||||||
|
seo: {
|
||||||
|
type: Object,
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
components: {
|
components: {
|
||||||
|
AppHead,
|
||||||
FacultyItemBreadcrumbs,
|
FacultyItemBreadcrumbs,
|
||||||
MainPageNavBar,
|
MainPageNavBar,
|
||||||
FacultyBuilder,
|
FacultyBuilder,
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ export default {
|
|||||||
}}
|
}}
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
|
|
||||||
<AppHead
|
<AppHead
|
||||||
:title="seo.title"
|
:title="seo.title"
|
||||||
:description="seo.description"
|
:description="seo.description"
|
||||||
|
|||||||
@@ -19,11 +19,13 @@ import ProgramTitle from "@/Components/BuilderUi/AdditionalEducationPrograms/Pro
|
|||||||
import ProgramBuilder from "@/Components/BuilderUi/AdditionalEducationPrograms/ProgramBuilder.vue";
|
import ProgramBuilder from "@/Components/BuilderUi/AdditionalEducationPrograms/ProgramBuilder.vue";
|
||||||
import ProgramBackButton from "@/Components/BuilderUi/Programs/ProgramBackButton.vue";
|
import ProgramBackButton from "@/Components/BuilderUi/Programs/ProgramBackButton.vue";
|
||||||
import BaseBuilder from "@/Components/BaseComponents/BaseBuilderUi/BaseBuilder.vue";
|
import BaseBuilder from "@/Components/BaseComponents/BaseBuilderUi/BaseBuilder.vue";
|
||||||
|
import AppHead from "@/Components/AppHead.vue";
|
||||||
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Show",
|
name: "Show",
|
||||||
components: {
|
components: {
|
||||||
|
AppHead,
|
||||||
BaseBuilder,
|
BaseBuilder,
|
||||||
ProgramBackButton, ProgramBuilder, ProgramTitle, AdditionalEducationProgramItemBreadcrumbs,
|
ProgramBackButton, ProgramBuilder, ProgramTitle, AdditionalEducationProgramItemBreadcrumbs,
|
||||||
ProgramItemBreadcrumbs,
|
ProgramItemBreadcrumbs,
|
||||||
@@ -53,6 +55,9 @@ export default {
|
|||||||
},
|
},
|
||||||
formsEdu: {
|
formsEdu: {
|
||||||
type: Array
|
type: Array
|
||||||
|
},
|
||||||
|
seo: {
|
||||||
|
type: Object,
|
||||||
}
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
@@ -73,10 +78,10 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Head>
|
<AppHead
|
||||||
<title>Образовательная программа</title>
|
:title="seo.title"
|
||||||
<meta name="description" content="Your page description">
|
:description="seo.description"
|
||||||
</Head>
|
/>
|
||||||
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
<MainPageNavBar class="border-b" :sections="$page.props.navigation"></MainPageNavBar>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+7
-4
@@ -15,6 +15,7 @@ use App\Http\Controllers\ClientVacantPositionController;
|
|||||||
use App\Http\Controllers\ClientVirtualExhibitionController;
|
use App\Http\Controllers\ClientVirtualExhibitionController;
|
||||||
use App\Http\Controllers\ClientWidgetFormController;
|
use App\Http\Controllers\ClientWidgetFormController;
|
||||||
use App\Http\Controllers\EducationalProgramController;
|
use App\Http\Controllers\EducationalProgramController;
|
||||||
|
use App\Http\Controllers\GenerateSitemapController;
|
||||||
use App\Http\Controllers\LinkToolController;
|
use App\Http\Controllers\LinkToolController;
|
||||||
use App\Http\Controllers\MainController;
|
use App\Http\Controllers\MainController;
|
||||||
use App\Http\Controllers\PageController;
|
use App\Http\Controllers\PageController;
|
||||||
@@ -25,18 +26,20 @@ use App\Http\Controllers\UpdateEduDataApiController;
|
|||||||
use App\Http\Controllers\UpdateViconDataApi;
|
use App\Http\Controllers\UpdateViconDataApi;
|
||||||
use App\Http\Controllers\VkAuthController;
|
use App\Http\Controllers\VkAuthController;
|
||||||
use App\Http\Controllers\VkPostController;
|
use App\Http\Controllers\VkPostController;
|
||||||
|
use App\Models\Post;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
use Inertia\Inertia;
|
use Inertia\Inertia;
|
||||||
|
use Spatie\Sitemap\Sitemap;
|
||||||
|
use Spatie\Sitemap\SitemapGenerator;
|
||||||
|
use Spatie\Sitemap\Tags\Url;
|
||||||
|
|
||||||
|
|
||||||
Route::middleware('signed')->get('invitation/{invitation}/accept', \App\Livewire\AcceptInvitation::class)
|
Route::middleware('signed')->get('invitation/{invitation}/accept', \App\Livewire\AcceptInvitation::class)
|
||||||
->name('invitation.accept');
|
->name('invitation.accept');
|
||||||
|
|
||||||
Route::middleware('access-check')->group(function () {
|
Route::get('/generate-sitemap', [GenerateSitemapController::class, 'index']);
|
||||||
|
|
||||||
// Route::get('/dashboard/schedule/create', function () {
|
Route::middleware('access-check')->group(function () {
|
||||||
// return Inertia::render('Dashboard/CreateSchedule');
|
|
||||||
// });
|
|
||||||
|
|
||||||
// Главная страница
|
// Главная страница
|
||||||
Route::get('/', [MainController::class, 'index'])->name('index');
|
Route::get('/', [MainController::class, 'index'])->name('index');
|
||||||
|
|||||||
Reference in New Issue
Block a user