This commit is contained in:
f4ilji
2024-11-05 15:08:08 +05:00
parent e3af1778f0
commit 4b693240e0
41 changed files with 2106 additions and 413 deletions
+97
View File
@@ -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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['about_program']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['main_info']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -68,22 +63,6 @@ class CreateAcademicJournal extends CreateRecord
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
{
@@ -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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['about_program']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['main_info']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -11,10 +11,14 @@ class CreateAdditionalEducation extends CreateRecord
{
protected static string $resource = AdditionalEducationResource::class;
protected array $seoData;
protected function mutateFormDataBeforeCreate(array $data): array
{
$this->seoData = $this->generateSeo($data);
$data['search_data'] = $this->generateSearchData($data['content']);
return $data;
}
@@ -27,17 +31,16 @@ class CreateAdditionalEducation extends CreateRecord
{
$title = $data['title'];
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
$description = strip_tags($rowData['data']['content']);
// $image = ($data['preview'] !== null) ? $data['preview'] : null;
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
return [
'title' => $title,
'description' => Str::limit($description, 160),
'image' => "",
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
];
}
private function getFirstBlockByName(string $name, array $content) : array|null
{
$data = null;
@@ -48,21 +51,17 @@ class CreateAdditionalEducation extends CreateRecord
return $data;
}
private function getBlockBySeoActiveState(string $name, array $content) : array|null
private function generateSearchData(array $data) : string
{
$data = [];
foreach ($content as $block) {
if ($block['type'] === $name) {
$data[] = $block;
}
$result = "";
foreach ($data as $block) {
$result .= $this->getDataFromBlocks($block);
}
$block = null;
foreach ($data as $item) {
if ($item['data']['seo_active'] === true) {
$block = $item;
}
}
return $block;
// Удаляем лишние пробелы и переносы строк
$result = preg_replace('/\s+/', ' ', $result);
$result = trim($result);
return strtolower($result);
}
private function getDataFromBlocks($block) : string
@@ -14,33 +14,37 @@ class EditAdditionalEducation extends EditRecord
protected array $seoData;
protected function mutateFormDataBeforeSave(array $data): array
{
$this->seoData = $this->generateSeo($data);
$data['search_data'] = $this->generateSearchData($data['content']);
return $data;
}
protected function afterSave(): void
{
$this->record->seo()->update($this->seoData);
}
private function generateSeo(array $data) : array
{
$title = $data['title'];
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
$description = strip_tags($rowData['data']['content']);
// $image = ($data['preview'] !== null) ? $data['preview'] : null;
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
return [
'title' => $title,
'description' => Str::limit($description, 160),
'image' => "",
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
];
}
private function getFirstBlockByName(string $name, array $content) : array|null
{
$data = null;
@@ -51,6 +55,56 @@ class EditAdditionalEducation extends EditRecord
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
+412 -13
View File
@@ -2,25 +2,43 @@
namespace App\Filament\Resources;
use App\Enums\CustomFormStatus;
use App\Enums\PostStatus;
use App\Filament\Resources\DepartmentResource\Pages;
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\Faculty;
use App\Models\Page;
use App\Models\PageReferenceList;
use App\Models\Post;
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\Toggle;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
class DepartmentResource extends Resource
{
protected static ?string $model = Department::class;
protected static ?string $navigationGroup = 'Структура института';
protected static ?string $navigationIcon = 'heroicon-o-rectangle-stack';
protected static ?string $pluralLabel = 'Кафедры';
@@ -34,21 +52,402 @@ class DepartmentResource extends Resource
{
return $form
->schema([
TextInput::make('title')->label('Название кафедры')->required()
->live(onBlur: true)
->afterStateUpdated(function (string $operation, $state, Forms\Set $set) {
$set('slug', Str::slug($state));
}),
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
Forms\Components\Select::make('faculty_id')
->options(Faculty::all()->pluck('title', 'id'))
->label('Факультет')
->required(),
Toggle::make('is_active')->default(true)->label('Активная кафедра')->inline(false),
Section::make()
->schema([
Tabs::make('Tabs')
->tabs([
Tabs\Tab::make('Основная информация')
->schema([
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),
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
{
return $table
@@ -13,7 +13,6 @@ class CreateDepartment extends CreateRecord
protected array $seoData;
protected function mutateFormDataBeforeCreate(array $data): array
{
$this->seoData = $this->generateSeo($data);
@@ -29,20 +28,15 @@ class CreateDepartment extends CreateRecord
private function generateSeo(array $data) : array
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -68,22 +62,6 @@ class CreateDepartment extends CreateRecord
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
{
@@ -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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['description']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['description']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['description']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -33,20 +33,15 @@ class CreateEducationalProgram extends CreateRecord
private function generateSeo(array $data) : array
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -72,23 +67,6 @@ class CreateEducationalProgram extends CreateRecord
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
{
$data = "";
@@ -13,10 +13,8 @@ class EditEducationalProgram extends EditRecord
{
protected static string $resource = EducationalProgramResource::class;
protected array $seoData;
protected function mutateFormDataBeforeSave(array $data): array
{
$this->seoData = $this->generateSeo($data);
@@ -30,42 +28,18 @@ class EditEducationalProgram extends EditRecord
$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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['about_program']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -2,17 +2,33 @@
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\Page;
use App\Models\PageReferenceList;
use App\Models\Post;
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\Toggle;
use Filament\Forms\Form;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
class DepartmentsRelationManager extends RelationManager
{
@@ -25,13 +41,391 @@ class DepartmentsRelationManager extends RelationManager
{
return $form
->schema([
TextInput::make('title')->label('Название кафедры')->required()
->live(onBlur: true)
->afterStateUpdated(function (string $operation, $state, Forms\Set $set) {
$set('slug', Str::slug($state));
}),
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
Toggle::make('is_active')->default(true)->label('Активная кафедра')->inline(false),
Section::make()
->schema([
Tabs::make('Tabs')
->tabs([
Tabs\Tab::make('Основная информация')
->schema([
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('Добавить новый блок'),
]),
]),
])
]);
}
+403 -12
View File
@@ -2,21 +2,37 @@
namespace App\Filament\Resources;
use App\Enums\CustomFormStatus;
use App\Enums\PostStatus;
use App\Filament\Resources\FacultyRecourceResource\RelationManagers\DepartmentsRelationManager;
use App\Filament\Resources\FacultyResource\Pages;
use App\Filament\Resources\FacultyResource\RelationManagers;
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\Page;
use App\Models\PageReferenceList;
use App\Models\Post;
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\Toggle;
use Filament\Forms\Form;
use Filament\Resources\Resource;
use Filament\Tables;
use Filament\Tables\Table;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Support\Carbon;
use Illuminate\Support\Str;
use Livewire\Features\SupportFileUploads\TemporaryUploadedFile;
class FacultyResource extends Resource
{
@@ -36,16 +52,392 @@ class FacultyResource extends Resource
{
return $form
->schema([
TextInput::make('title')->label('Название факультета')->required(),
TextInput::make('abbreviation')->label('Аббревиатура')->required()
->live(onBlur: true)
->afterStateUpdated(function (string $operation, $state, Forms\Set $set) {
$set('slug', Str::slug($state));
}),
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
Toggle::make('is_active')->default(true)->label('Активный факультет')->inline(false),
]);
Section::make()
->schema([
Tabs::make('Tabs')
->tabs([
Tabs\Tab::make('Основная информация')
->schema([
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('Добавить новый блок'),
]),
]),
])
]);
}
public static function table(Table $table): Table
@@ -70,7 +462,6 @@ class FacultyResource extends Resource
public static function getRelations(): array
{
return [
DepartmentsRelationManager::class,
WorkersRelationManager::class
];
}
@@ -29,20 +29,15 @@ class CreateFaculty extends CreateRecord
private function generateSeo(array $data) : array
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -68,22 +63,6 @@ class CreateFaculty extends CreateRecord
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
{
@@ -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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -68,22 +63,6 @@ class CreateLibraryNews extends CreateRecord
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
{
@@ -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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'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
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
} $image = ($data['preview'] !== null) ? $data['preview'] : null;
}
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -68,22 +63,6 @@ class CreateVirtualExhibition extends CreateRecord
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
{
@@ -48,21 +48,15 @@ class EditVirtualExhibition extends EditRecord
private function generateSeo(array $data) : array
{
$title = $data['title'];
$rowData = $this->getBlockBySeoActiveState('paragraph', $data['content']);
if ($rowData === null) {
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
}
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
if ($rowData !== null) {
$description = strip_tags($rowData['data']['content']);
} else {
$description = null;
}
$image = ($this->record->preview !== null) ? $this->record->preview : null;
return [
'title' => $title,
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
'image' => $image,
];
}
@@ -134,6 +134,8 @@ class ClientAdditionalEducationController extends Controller
$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'])
->first());
$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());
$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'));
}
public function show(string $slug)
{
$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());
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) {
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
@@ -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\EducationalProgram;
use App\Models\Event;
use App\Models\Faculty;
use App\Models\Page;
use App\Models\Post;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
@@ -43,6 +45,8 @@ class SearchController extends Controller
->add(AdditionalEducation::where('is_active', '=', true), 'title')
->add(EducationalGroup::with('schedules'), 'title')
->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()
->orderByRelevance()
->includeModelType()
+1 -1
View File
@@ -31,7 +31,7 @@ class AppServiceProvider extends ServiceProvider
setlocale(LC_TIME, 'ru_RU.UTF-8');
Carbon::setLocale(config('app.locale'));
Model::preventLazyLoading(!app()->isProduction());
URL::forceScheme('https');
// URL::forceScheme('https');
self::registerFilamentNavigationGroups();
}