Rework frontend
This commit is contained in:
@@ -11,6 +11,7 @@ use App\Models\CustomForm;
|
||||
use App\Models\Page;
|
||||
use App\Models\PageReferenceList;
|
||||
use App\Models\Post;
|
||||
use App\Models\Slider;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
@@ -415,6 +416,13 @@ class ContentBuilderItem
|
||||
->searchable()
|
||||
->required(),
|
||||
])->label('Контакты'),
|
||||
Builder\Block::make('slider')
|
||||
->schema([
|
||||
Select::make('slider')
|
||||
->options(Slider::query()->whereHas('slides')->where('is_active', true)->pluck('title', 'slug'))
|
||||
->searchable()
|
||||
->required(),
|
||||
])->label('Слайдеры'),
|
||||
])
|
||||
->collapsed()
|
||||
->blockNumbers(false)
|
||||
|
||||
@@ -192,6 +192,7 @@ class PostForm
|
||||
]),
|
||||
]),
|
||||
])
|
||||
->hidden(fn(Forms\Get $get) => !$get('is_slider_enabled'))
|
||||
|
||||
|
||||
]),
|
||||
|
||||
@@ -31,11 +31,15 @@ class AdmissionCampaignResource extends Resource
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
TextInput::make('name')->label('Название')->required()->columnSpanFull(),
|
||||
Forms\Components\Select::make('academic_year')->label('Академический год')->required()
|
||||
->options(['2024' => '2024/2025', '2025' => '2025/2026']),
|
||||
Forms\Components\Select::make('status')->label('Статус')->required()
|
||||
->options(['1' => 'Активный', '2' => 'Архивный', '3' => 'Скрыт']),
|
||||
Forms\Components\Section::make()->schema([
|
||||
TextInput::make('name')->label('Название')->required()->columnSpanFull(),
|
||||
Forms\Components\Grid::make()->schema([
|
||||
Forms\Components\Select::make('academic_year')->label('Академический год')->required()
|
||||
->options(self::generateAcademicYears()),
|
||||
Forms\Components\Select::make('status')->label('Статус')->required()
|
||||
->options(['1' => 'Активный', '2' => 'Архивный', '3' => 'Скрыт']),
|
||||
]),
|
||||
]),
|
||||
Forms\Components\Section::make()->schema([
|
||||
Forms\Components\Repeater::make('info')->schema([
|
||||
Forms\Components\Select::make('edu_name')->options(LevelEducational::class),
|
||||
@@ -91,4 +95,19 @@ class AdmissionCampaignResource extends Resource
|
||||
'edit' => Pages\EditAdmissionCampaign::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
|
||||
protected static function generateAcademicYears(): array
|
||||
{
|
||||
$currentYear = (int) date('Y') - 5;
|
||||
$yearsAhead = 10; // Количество лет вперед
|
||||
$academicYears = [];
|
||||
|
||||
for ($i = 0; $i < $yearsAhead; $i++) {
|
||||
$startYear = $currentYear + $i;
|
||||
$endYear = $startYear + 1;
|
||||
$academicYears[$startYear] = "{$startYear}/{$endYear}";
|
||||
}
|
||||
|
||||
return $academicYears;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Filament\Resources\AdmissionCampaignResource\Pages;
|
||||
|
||||
use App\Filament\Resources\AdmissionCampaignResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Notifications\Notification;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListAdmissionCampaigns extends ListRecords
|
||||
@@ -13,7 +14,51 @@ class ListAdmissionCampaigns extends ListRecords
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
Actions\CreateAction::make(), // Стандартная кнопка "Создать"
|
||||
Actions\Action::make('fetchData') // Кастомная кнопка
|
||||
->label('Обновить данные')
|
||||
->color('primary') // Цвет кнопки
|
||||
->icon('heroicon-o-arrow-path') // Иконка
|
||||
->action(function () {
|
||||
// Отправляем запрос в фоновом режиме
|
||||
$this->js(<<<JS
|
||||
fetch('/api/get-data', {
|
||||
method: 'GET',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content,
|
||||
},
|
||||
})
|
||||
.then(response => response.json())
|
||||
.then(data => {
|
||||
// Показываем уведомление об успешном завершении
|
||||
window.dispatchEvent(new CustomEvent('filament-notify', {
|
||||
detail: {
|
||||
type: 'success',
|
||||
title: 'Данные обновлены',
|
||||
body: 'Данные успешно обновлены.',
|
||||
},
|
||||
}));
|
||||
})
|
||||
.catch(error => {
|
||||
// Показываем уведомление об ошибке
|
||||
window.dispatchEvent(new CustomEvent('filament-notify', {
|
||||
detail: {
|
||||
type: 'danger',
|
||||
title: 'Ошибка',
|
||||
body: 'Произошла ошибка при обновлении данных.',
|
||||
},
|
||||
}));
|
||||
});
|
||||
JS);
|
||||
|
||||
// Показываем уведомление
|
||||
Notification::make()
|
||||
->title('Данные обновляются')
|
||||
->body('Данные обновляются в фоновом режиме.')
|
||||
->success()
|
||||
->send();
|
||||
}),
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Enums\BudgetEducation;
|
||||
use App\Enums\EducationalProgramStatus;
|
||||
use App\Enums\FormEducation;
|
||||
use App\Filament\Resources\AdmissionPlanResource\Pages;
|
||||
use App\Filament\Resources\AdmissionPlanResource\RelationManagers;
|
||||
use App\Filament\Resources\EducationalProgramResource\RelationManagers\AdmissionPlansRelationManager;
|
||||
@@ -39,13 +41,15 @@ class AdmissionPlanResource extends Resource
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Select::make('educational_programs_id')
|
||||
->searchable()
|
||||
->label('Образовательная программа')
|
||||
->options(EducationalProgram::whereIn('status', [EducationalProgramStatus::PUBLISHED, EducationalProgramStatus::IN_PROGRESS])->pluck('name', 'id')),
|
||||
Forms\Components\Select::make('admission_campaigns_id')
|
||||
->label('Приемная компания')
|
||||
->options(AdmissionCampaign::all()->pluck('name', 'id')),
|
||||
Section::make()->schema([
|
||||
Forms\Components\Select::make('educational_programs_id')
|
||||
->searchable()
|
||||
->label('Образовательная программа')
|
||||
->options(EducationalProgram::whereIn('status', [EducationalProgramStatus::PUBLISHED, EducationalProgramStatus::IN_PROGRESS])->pluck('name', 'id')),
|
||||
Forms\Components\Select::make('admission_campaigns_id')
|
||||
->label('Приемная компания')
|
||||
->options(AdmissionCampaign::all()->pluck('name', 'id')),
|
||||
]),
|
||||
Section::make('План приема')->schema([
|
||||
Forms\Components\Repeater::make('exams')->label('Вступительные испытания')->schema([
|
||||
TextInput::make('title')->label('Название-предмета'),
|
||||
@@ -59,12 +63,11 @@ class AdmissionPlanResource extends Resource
|
||||
return "Вступительное испытание #" . $count;
|
||||
}),
|
||||
Forms\Components\Repeater::make('contests')->label('Условия поступления')->schema([
|
||||
Forms\Components\Select::make('form_education')->label('Форма образования')
|
||||
->options(['och' => 'Очная форма обучения', 'zaoch' => 'Заочная форма обучения', 'och_zaoch' => 'Очно-заочная форма обучения']),
|
||||
Forms\Components\Select::make('form_education')->label('Форма обучения')
|
||||
->options(FormEducation::class),
|
||||
Forms\Components\Select::make('financing_source')->label('Источник финансирования')
|
||||
->options(['budget' => 'Бюджетное место', 'non_budget' => 'С оплатой обучения']),
|
||||
TextInput::make('budget_quantity_position')->label('Количество бюджетных мест')->integer(),
|
||||
TextInput::make('non_budget_quantity_position')->label('Количество платных мест')->integer()
|
||||
->options(BudgetEducation::class),
|
||||
TextInput::make('position_count')->label('Количество мест на прием')->integer(),
|
||||
])->live()->maxItems(2)->collapsed()->addActionLabel('Добавить группу')->columns(3)
|
||||
->itemLabel(function (Get $get) {
|
||||
static $count = 0;
|
||||
|
||||
@@ -31,18 +31,16 @@ class DirectionStudyResource extends Resource
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
//
|
||||
]);
|
||||
->schema([]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('name'),
|
||||
Tables\Columns\TextColumn::make('code'),
|
||||
Tables\Columns\TextColumn::make('lvl_edu')
|
||||
Tables\Columns\TextColumn::make('name')->label('Название'),
|
||||
Tables\Columns\TextColumn::make('code')->label('Код направления'),
|
||||
Tables\Columns\TextColumn::make('lvl_edu')->label('Уровень образования')
|
||||
->formatStateUsing(fn ($state) => $state->getLabel())
|
||||
])
|
||||
->filters([
|
||||
|
||||
@@ -241,9 +241,8 @@ class EducationalProgramResource extends Resource
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
Tables\Columns\TextColumn::make('name')->sortable()->searchable(),
|
||||
Tables\Columns\TextColumn::make('code_napr'),
|
||||
Tables\Columns\TextColumn::make('directionStudy.lvl_edu')->limit(30),
|
||||
Tables\Columns\TextColumn::make('name')->label('Название программы')->sortable()->searchable(),
|
||||
Tables\Columns\TextColumn::make('directionStudy.lvl_edu')->label('Уровень образования')->limit(30),
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\ExternalVacancyResource\Pages;
|
||||
use App\Filament\Resources\ExternalVacancyResource\RelationManagers;
|
||||
use App\Models\ExternalVacancy;
|
||||
use Filament\Forms;
|
||||
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;
|
||||
|
||||
class ExternalVacancyResource extends Resource
|
||||
{
|
||||
protected static ?string $model = ExternalVacancy::class;
|
||||
|
||||
protected static ?string $navigationGroup = 'Вакансии';
|
||||
|
||||
public static ?string $label = 'Вакансия для студентов';
|
||||
|
||||
protected static ?string $pluralLabel = 'Вакансии для студентов прочих организаций';
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-briefcase';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('city')->required()->columnSpan('full')->label('Город'),
|
||||
Forms\Components\TagsInput::make('position')->label('Должность')->placeholder('')->required(),
|
||||
Forms\Components\TextInput::make('salary')->integer()->label('Зарплата')->prefix('₽'),
|
||||
Forms\Components\RichEditor::make('conditions')->label('Условия работы'),
|
||||
Forms\Components\RichEditor::make('contacts')->label('Контакты')->required(),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
//
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListExternalVacancies::route('/'),
|
||||
'create' => Pages\CreateExternalVacancy::route('/create'),
|
||||
'edit' => Pages\EditExternalVacancy::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ExternalVacancyResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ExternalVacancyResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateExternalVacancy extends CreateRecord
|
||||
{
|
||||
protected static string $resource = ExternalVacancyResource::class;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ExternalVacancyResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ExternalVacancyResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditExternalVacancy extends EditRecord
|
||||
{
|
||||
protected static string $resource = ExternalVacancyResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\ExternalVacancyResource\Pages;
|
||||
|
||||
use App\Filament\Resources\ExternalVacancyResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListExternalVacancies extends ListRecords
|
||||
{
|
||||
protected static string $resource = ExternalVacancyResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,177 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\LibraryNewsResource\Pages;
|
||||
use App\Filament\Resources\LibraryNewsResource\RelationManagers;
|
||||
use App\Models\LibraryNews;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Section;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Forms\Components\Builder;
|
||||
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor;
|
||||
|
||||
class LibraryNewsResource extends Resource
|
||||
{
|
||||
protected static ?string $model = LibraryNews::class;
|
||||
|
||||
protected static ?string $navigationGroup = 'Библиотека';
|
||||
|
||||
public static ?string $label = 'Новость';
|
||||
|
||||
protected static ?string $pluralLabel = 'Новости библиотеки';
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-newspaper';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\Grid::make()->schema([
|
||||
Forms\Components\TextInput::make('title')->required()->label('Заголовок'),
|
||||
Forms\Components\TextInput::make('category')->required()->label('Категория (Необязательно)'),
|
||||
]),
|
||||
|
||||
Forms\Components\Textarea::make('preview_text')->required()->label('Текст анонса')
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
|
||||
Section::make('Контент')->schema([
|
||||
\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('')
|
||||
->required()
|
||||
|
||||
]),
|
||||
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([
|
||||
Hidden::make('mime'),
|
||||
|
||||
TextInput::make('title')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autofocus(),
|
||||
|
||||
FileUpload::make('path')
|
||||
->required()
|
||||
->acceptedFileTypes(['video/mp4','video/ogg','video/webm'])
|
||||
->maxSize(512000)
|
||||
->disk('videos')
|
||||
->visibility('public')
|
||||
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||
]),
|
||||
Builder\Block::make('files')
|
||||
->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')
|
||||
])
|
||||
])
|
||||
->collapsed()
|
||||
->blockNumbers(false)
|
||||
->collapsible()
|
||||
->addActionLabel('Добавить новый блок'),
|
||||
|
||||
]),
|
||||
Forms\Components\Toggle::make('is_active')->required()->label('Активная заметка')->default(true),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
//
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListLibraryNews::route('/'),
|
||||
'create' => Pages\CreateLibraryNews::route('/create'),
|
||||
'edit' => Pages\EditLibraryNews::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\LibraryNewsResource\Pages;
|
||||
|
||||
use App\Filament\Resources\LibraryNewsResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CreateLibraryNews extends CreateRecord
|
||||
{
|
||||
protected static string $resource = LibraryNewsResource::class;
|
||||
|
||||
protected array $seoData;
|
||||
|
||||
|
||||
protected function mutateFormDataBeforeCreate(array $data): array
|
||||
{
|
||||
$this->seoData = $this->generateSeo($data);
|
||||
$data['search_data'] = $this->generateSearchData($data['content']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function afterCreate(): void
|
||||
{
|
||||
$this->record->seo()->create($this->seoData);
|
||||
}
|
||||
|
||||
private function generateSeo(array $data) : array
|
||||
{
|
||||
$title = $data['title'];
|
||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||
if ($rowData !== null) {
|
||||
$description = strip_tags($rowData['data']['content']);
|
||||
} else {
|
||||
$description = null;
|
||||
}
|
||||
return [
|
||||
'title' => $title,
|
||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||
];
|
||||
}
|
||||
|
||||
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 getFirstBlockByName(string $name, array $content) : array|null
|
||||
{
|
||||
$data = null;
|
||||
foreach ($content as $block) {
|
||||
$data = ($block['type'] === $name) ? $block : null;
|
||||
break;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\LibraryNewsResource\Pages;
|
||||
|
||||
use App\Filament\Resources\LibraryNewsResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class EditLibraryNews extends EditRecord
|
||||
{
|
||||
protected static string $resource = LibraryNewsResource::class;
|
||||
|
||||
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']);
|
||||
if ($rowData !== null) {
|
||||
$description = strip_tags($rowData['data']['content']);
|
||||
} else {
|
||||
$description = null;
|
||||
}
|
||||
return [
|
||||
'title' => $title,
|
||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||
];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 getFirstBlockByName(string $name, array $content) : array|null
|
||||
{
|
||||
$data = null;
|
||||
foreach ($content as $block) {
|
||||
$data = ($block['type'] === $name) ? $block : null;
|
||||
break;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\LibraryNewsResource\Pages;
|
||||
|
||||
use App\Filament\Resources\LibraryNewsResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListLibraryNews extends ListRecords
|
||||
{
|
||||
protected static string $resource = LibraryNewsResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -7,6 +7,7 @@ use App\Models\Event;
|
||||
use App\Models\Page;
|
||||
use App\Models\Post;
|
||||
use App\Models\Slide;
|
||||
use App\Models\Slider;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\ColorPicker;
|
||||
use Filament\Forms\Components\DateTimePicker;
|
||||
@@ -92,7 +93,10 @@ class SlideResource extends Resource
|
||||
}),
|
||||
]),
|
||||
]),
|
||||
Forms\Components\Section::make('Слайдер')->schema([
|
||||
Forms\Components\Section::make('Выбрать слайдер')->schema([
|
||||
Forms\Components\Select::make('slider_id')->label('')->options(Slider::where('is_active', true)->pluck('title', 'id')),
|
||||
]),
|
||||
Forms\Components\Section::make('Тело слайда')->schema([
|
||||
|
||||
Forms\Components\Section::make('Информация слайда')->schema([
|
||||
Forms\Components\TextInput::make('title')
|
||||
|
||||
@@ -14,6 +14,7 @@ use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class SliderResource extends Resource
|
||||
{
|
||||
@@ -27,7 +28,13 @@ class SliderResource extends Resource
|
||||
->schema([
|
||||
Forms\Components\Section::make()->schema([
|
||||
Forms\Components\TextInput::make('title')
|
||||
->label('Заголовок слайдера'),
|
||||
->live(onBlur: true)
|
||||
->afterStateUpdated(function (string $operation, string|null $state, Forms\Set $set) {
|
||||
$set('slug', Str::slug($state));
|
||||
})
|
||||
->label('Заголовок слайдера')
|
||||
->required(),
|
||||
TextInput::make('slug')->label('Slug')->unique(ignoreRecord: true)->readOnly()->required(),
|
||||
Toggle::make('is_active')->default(true)->label('Активный слайдер')->inline(false),
|
||||
]),
|
||||
]);
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\VacantPositionResource\Pages;
|
||||
use App\Filament\Resources\VacantPositionResource\RelationManagers;
|
||||
use App\Models\VacantPosition;
|
||||
use Filament\Forms;
|
||||
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;
|
||||
|
||||
class VacantPositionResource extends Resource
|
||||
{
|
||||
protected static ?string $model = VacantPosition::class;
|
||||
|
||||
protected static ?string $navigationGroup = 'Вакансии';
|
||||
|
||||
|
||||
public static ?string $label = 'Вакансия института';
|
||||
|
||||
protected static ?string $pluralLabel = 'Вакансии института';
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-briefcase';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Forms\Components\TextInput::make('department')->label('Стурктурное подразделение')->required(),
|
||||
Forms\Components\TextInput::make('position')->label('Должность')->required(),
|
||||
Forms\Components\TextInput::make('fraction')->integer()->maxValue(1)->step(0.1)->minValue(0)->label('Объем ставок')->required(),
|
||||
Forms\Components\TextInput::make('salary')->integer()->required()->minValue(0)->label('Зарплата'),
|
||||
Forms\Components\TextInput::make('notice')->label('Примечание'),
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
//
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListVacantPositions::route('/'),
|
||||
'create' => Pages\CreateVacantPosition::route('/create'),
|
||||
'edit' => Pages\EditVacantPosition::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\VacantPositionResource\Pages;
|
||||
|
||||
use App\Filament\Resources\VacantPositionResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
|
||||
class CreateVacantPosition extends CreateRecord
|
||||
{
|
||||
protected static string $resource = VacantPositionResource::class;
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\VacantPositionResource\Pages;
|
||||
|
||||
use App\Filament\Resources\VacantPositionResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
|
||||
class EditVacantPosition extends EditRecord
|
||||
{
|
||||
protected static string $resource = VacantPositionResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\VacantPositionResource\Pages;
|
||||
|
||||
use App\Filament\Resources\VacantPositionResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListVacantPositions extends ListRecords
|
||||
{
|
||||
protected static string $resource = VacantPositionResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources;
|
||||
|
||||
use App\Filament\Resources\VirtualExhibitionResource\Pages;
|
||||
use App\Filament\Resources\VirtualExhibitionResource\RelationManagers;
|
||||
use App\Models\VirtualExhibition;
|
||||
use Filament\Forms;
|
||||
use Filament\Forms\Components\FileUpload;
|
||||
use Filament\Forms\Components\Hidden;
|
||||
use Filament\Forms\Components\RichEditor;
|
||||
use Filament\Forms\Components\Section;
|
||||
use Filament\Forms\Components\Tabs;
|
||||
use Filament\Forms\Components\TextInput;
|
||||
use Filament\Forms\Form;
|
||||
use Filament\Resources\Resource;
|
||||
use Filament\Tables;
|
||||
use Filament\Tables\Table;
|
||||
use Filament\Forms\Components\Builder;
|
||||
use Illuminate\Database\Eloquent\SoftDeletingScope;
|
||||
use Mohamedsabil83\FilamentFormsTinyeditor\Components\TinyEditor;
|
||||
|
||||
class VirtualExhibitionResource extends Resource
|
||||
{
|
||||
protected static ?string $model = VirtualExhibition::class;
|
||||
|
||||
protected static ?string $navigationGroup = 'Библиотека';
|
||||
|
||||
public static ?string $label = 'Виртуальная выставка';
|
||||
|
||||
protected static ?string $pluralLabel = 'Виртуальные выставки';
|
||||
|
||||
protected static ?string $navigationIcon = 'heroicon-o-cube-transparent';
|
||||
|
||||
public static function form(Form $form): Form
|
||||
{
|
||||
return $form
|
||||
->schema([
|
||||
Section::make()
|
||||
->schema([
|
||||
Tabs::make('Tabs')
|
||||
->tabs([
|
||||
Tabs\Tab::make('Основная информация')
|
||||
->schema([
|
||||
Forms\Components\Grid::make()->schema([
|
||||
Forms\Components\TextInput::make('title')->required()->label('Заголовок'),
|
||||
Forms\Components\TextInput::make('category')->required()->label('Категория (Необязательно)'),
|
||||
]),
|
||||
Forms\Components\Textarea::make('preview_text')->required()->label('Текст анонса')
|
||||
->required()
|
||||
->columnSpanFull(),
|
||||
Forms\Components\Toggle::make('is_active')->required()->label('Активно')->default(true),
|
||||
]),
|
||||
Tabs\Tab::make('Содержание выставки')
|
||||
->schema([
|
||||
\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('')
|
||||
->required()
|
||||
|
||||
]),
|
||||
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([
|
||||
Hidden::make('mime'),
|
||||
|
||||
TextInput::make('title')
|
||||
->required()
|
||||
->maxLength(255)
|
||||
->autofocus(),
|
||||
|
||||
FileUpload::make('path')
|
||||
->required()
|
||||
->acceptedFileTypes(['video/mp4','video/ogg','video/webm'])
|
||||
->maxSize(512000)
|
||||
->disk('videos')
|
||||
->visibility('public')
|
||||
->afterStateUpdated(fn (callable $set, $state) => $set('mime', $state?->getMimeType())),
|
||||
]),
|
||||
Builder\Block::make('files')
|
||||
->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')
|
||||
])
|
||||
])
|
||||
->collapsed()
|
||||
->blockNumbers(false)
|
||||
->collapsible()
|
||||
->addActionLabel('Добавить новый блок'),
|
||||
]),
|
||||
]),
|
||||
]),
|
||||
|
||||
]);
|
||||
}
|
||||
|
||||
public static function table(Table $table): Table
|
||||
{
|
||||
return $table
|
||||
->columns([
|
||||
//
|
||||
])
|
||||
->filters([
|
||||
//
|
||||
])
|
||||
->actions([
|
||||
Tables\Actions\EditAction::make(),
|
||||
])
|
||||
->bulkActions([
|
||||
Tables\Actions\BulkActionGroup::make([
|
||||
Tables\Actions\DeleteBulkAction::make(),
|
||||
]),
|
||||
]);
|
||||
}
|
||||
|
||||
public static function getRelations(): array
|
||||
{
|
||||
return [
|
||||
//
|
||||
];
|
||||
}
|
||||
|
||||
public static function getPages(): array
|
||||
{
|
||||
return [
|
||||
'index' => Pages\ListVirtualExhibitions::route('/'),
|
||||
'create' => Pages\CreateVirtualExhibition::route('/create'),
|
||||
'edit' => Pages\EditVirtualExhibition::route('/{record}/edit'),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\VirtualExhibitionResource\Pages;
|
||||
|
||||
use App\Filament\Resources\VirtualExhibitionResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\CreateRecord;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class CreateVirtualExhibition extends CreateRecord
|
||||
{
|
||||
protected static string $resource = VirtualExhibitionResource::class;
|
||||
|
||||
protected array $seoData;
|
||||
|
||||
|
||||
protected function mutateFormDataBeforeCreate(array $data): array
|
||||
{
|
||||
$this->seoData = $this->generateSeo($data);
|
||||
$data['search_data'] = $this->generateSearchData($data['content']);
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function afterCreate(): void
|
||||
{
|
||||
$this->record->seo()->create($this->seoData);
|
||||
}
|
||||
|
||||
private function generateSeo(array $data) : array
|
||||
{
|
||||
$title = $data['title'];
|
||||
$rowData = $this->getFirstBlockByName('paragraph', $data['content']);
|
||||
if ($rowData !== null) {
|
||||
$description = strip_tags($rowData['data']['content']);
|
||||
} else {
|
||||
$description = null;
|
||||
}
|
||||
return [
|
||||
'title' => $title,
|
||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||
];
|
||||
}
|
||||
|
||||
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 getFirstBlockByName(string $name, array $content) : array|null
|
||||
{
|
||||
$data = null;
|
||||
foreach ($content as $block) {
|
||||
$data = ($block['type'] === $name) ? $block : null;
|
||||
break;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -1,129 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\VirtualExhibitionResource\Pages;
|
||||
|
||||
use App\Filament\Resources\VirtualExhibitionResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\EditRecord;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class EditVirtualExhibition extends EditRecord
|
||||
{
|
||||
protected static string $resource = VirtualExhibitionResource::class;
|
||||
|
||||
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 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->getFirstBlockByName('paragraph', $data['content']);
|
||||
if ($rowData !== null) {
|
||||
$description = strip_tags($rowData['data']['content']);
|
||||
} else {
|
||||
$description = null;
|
||||
}
|
||||
return [
|
||||
'title' => $title,
|
||||
'description' => Str::limit(htmlspecialchars($description, ENT_QUOTES, 'UTF-8'), 160),
|
||||
];
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
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 getFirstBlockByName(string $name, array $content) : array|null
|
||||
{
|
||||
$data = null;
|
||||
foreach ($content as $block) {
|
||||
$data = ($block['type'] === $name) ? $block : null;
|
||||
break;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\DeleteAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Filament\Resources\VirtualExhibitionResource\Pages;
|
||||
|
||||
use App\Filament\Resources\VirtualExhibitionResource;
|
||||
use Filament\Actions;
|
||||
use Filament\Resources\Pages\ListRecords;
|
||||
|
||||
class ListVirtualExhibitions extends ListRecords
|
||||
{
|
||||
protected static string $resource = VirtualExhibitionResource::class;
|
||||
|
||||
protected function getHeaderActions(): array
|
||||
{
|
||||
return [
|
||||
Actions\CreateAction::make(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,7 @@ use App\Http\Resources\ClientNavigationResource;
|
||||
use App\Models\Event;
|
||||
use App\Models\EventCategory;
|
||||
use App\Models\Page;
|
||||
use App\Services\App\Breadcrumb\BreadcrumbService;
|
||||
use Carbon\Carbon;
|
||||
use DateTime;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -19,58 +20,48 @@ use Inertia\Inertia;
|
||||
|
||||
class ClientEventController extends Controller
|
||||
{
|
||||
public function index(Request $request)
|
||||
public function __construct(private readonly BreadcrumbService $breadcrumbService){}
|
||||
|
||||
|
||||
public function index(Request $request): \Inertia\Response
|
||||
{
|
||||
$currentDate = $this->getCurrentDate($request);
|
||||
$filters = $this->getFilters();
|
||||
$eventDates = $this->getEventDates($filters); // Передаем фильтры
|
||||
$eventDates = $this->getEventDates($filters);
|
||||
|
||||
$events = $this->getEvents($currentDate);
|
||||
$categories = ClientEventCategoryResource::collection(EventCategory::has('events')->get());
|
||||
|
||||
$routeUrl = route('client.event.index');
|
||||
$path = ltrim(parse_url($routeUrl, PHP_URL_PATH), '/');
|
||||
$breadcrumbs = $this->breadcrumbService->generateBreadcrumbs('client.event.index');
|
||||
|
||||
$page = Page::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
|
||||
|
||||
if (isset($page->section)) {
|
||||
$breadcrumbs = [
|
||||
'mainSection' => new ClientBreadcrumbSection($page->section->mainSection),
|
||||
'subSection' => new ClientBreadcrumbSubSection($page->section),
|
||||
'page' => new ClientBreadcrumbPage($page),
|
||||
];
|
||||
} else {
|
||||
$breadcrumbs = null;
|
||||
}
|
||||
|
||||
return Inertia::render('Client/Events/Index', compact('eventDates', 'events', 'currentDate', 'filters', 'categories', 'breadcrumbs'));
|
||||
}
|
||||
|
||||
public function show(string $slug)
|
||||
public function show(string $slug): \Inertia\Response
|
||||
{
|
||||
$event = new ClientEventFullResource(Event::where('slug', '=', $slug)->with('category')->first());
|
||||
|
||||
|
||||
$routeUrl = route('client.event.index');
|
||||
$path = ltrim(parse_url($routeUrl, PHP_URL_PATH), '/');
|
||||
|
||||
$page = Page::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
|
||||
|
||||
if (isset($page->section)) {
|
||||
$breadcrumbs = [
|
||||
'mainSection' => new ClientBreadcrumbSection($page->section->mainSection),
|
||||
'subSection' => new ClientBreadcrumbSubSection($page->section),
|
||||
'page' => new ClientBreadcrumbPage($page),
|
||||
];
|
||||
} else {
|
||||
$breadcrumbs = null;
|
||||
}
|
||||
$breadcrumbs = $this->breadcrumbService->generateBreadcrumbs('client.event.index');
|
||||
|
||||
$seo = $event->seo ?? null;
|
||||
|
||||
return Inertia::render('Client/Events/Show', compact('event', 'breadcrumbs', 'seo'));
|
||||
}
|
||||
|
||||
public function archive(Request $request): \Inertia\Response
|
||||
{
|
||||
$filters = $this->getFilters();
|
||||
|
||||
$events = $this->getEventsArchive();
|
||||
$categories = ClientEventCategoryResource::collection(EventCategory::has('events')->get());
|
||||
|
||||
$breadcrumbs = $this->breadcrumbService->generateBreadcrumbs('client.event.archive');
|
||||
|
||||
|
||||
return Inertia::render('Client/Events/Archive', compact('events', 'filters', 'categories', 'breadcrumbs'));
|
||||
}
|
||||
|
||||
private function getCurrentDate(Request $request): array
|
||||
{
|
||||
$dateInput = $request->input('date');
|
||||
@@ -107,6 +98,9 @@ class ClientEventController extends Controller
|
||||
->when(request()->input('is_online'), function ($query, $value) {
|
||||
$this->applyOnlineFilter($query, $value);
|
||||
})
|
||||
->when(request()->input('search'), function ($query, $search) {
|
||||
$query->whereRaw('LOWER(title) like ?', ["%".strtolower($search)."%"]);
|
||||
})
|
||||
->when(request()->input('category'), function ($query) {
|
||||
$slugs = request()->input('category');
|
||||
if (is_array($slugs)) {
|
||||
@@ -119,6 +113,33 @@ class ClientEventController extends Controller
|
||||
->get());
|
||||
}
|
||||
|
||||
private function getEventsArchive()
|
||||
{
|
||||
return ClientEventResource::collection(Event::select('title', 'slug', 'event_date_start', 'event_time_start', 'address', 'is_online', 'category_id')
|
||||
->whereDate('event_date_start', '<', now())
|
||||
->with('category')
|
||||
->when(request()->input('is_online'), function ($query, $value) {
|
||||
$this->applyOnlineFilter($query, $value);
|
||||
})
|
||||
->when(request()->input('search'), function ($query, $search) {
|
||||
$query->whereRaw('LOWER(title) like ?', ["%".strtolower($search)."%"]);
|
||||
})
|
||||
->when(request()->input('category'), function ($query) {
|
||||
$slugs = request()->input('category');
|
||||
if (is_array($slugs)) {
|
||||
$query->whereHas('category', function ($query) use ($slugs) {
|
||||
$query->whereIn('slug', $slugs);
|
||||
});
|
||||
}
|
||||
})
|
||||
->when(request()->input('sort', 'desc'), function ($query, $sort) {
|
||||
$query->orderBy('event_date_start', $sort);
|
||||
})
|
||||
->orderBy('event_time_start', 'asc')
|
||||
->paginate(6)
|
||||
->withQueryString());
|
||||
}
|
||||
|
||||
private function getEventDates(array $filters): \Illuminate\Support\Collection
|
||||
{
|
||||
// Получаем события с учетом фильтров
|
||||
@@ -163,6 +184,8 @@ class ClientEventController extends Controller
|
||||
->sortKeys() // Сортируем ключи по возрастанию
|
||||
->values(); // Получаем массив без ключей
|
||||
|
||||
|
||||
|
||||
// Извлекаем уникальные даты из событий
|
||||
return $mappingDates;
|
||||
}
|
||||
@@ -177,6 +200,11 @@ class ClientEventController extends Controller
|
||||
}
|
||||
|
||||
return [
|
||||
'search_filter' => [
|
||||
'type' => 'search',
|
||||
'value' => request()->input('search'),
|
||||
'param' => 'search'
|
||||
],
|
||||
'category_filter' => [
|
||||
'type' => 'category',
|
||||
'value' => request()->input('category'),
|
||||
@@ -231,7 +259,7 @@ class ClientEventController extends Controller
|
||||
return $russianMonths[$month] ?? '';
|
||||
}
|
||||
|
||||
private function applyOnlineFilter($query, $isOnline)
|
||||
private function applyOnlineFilter($query, $isOnline): void
|
||||
{
|
||||
if ($isOnline === 'online') {
|
||||
$query->where('is_online', true);
|
||||
|
||||
@@ -17,6 +17,7 @@ use App\Models\MainSection;
|
||||
use App\Models\Page;
|
||||
use App\Models\Post;
|
||||
use App\Models\Tag;
|
||||
use App\Services\App\Breadcrumb\BreadcrumbService;
|
||||
use Carbon\Carbon;
|
||||
use Doctrine\DBAL\Schema\Column;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -26,6 +27,8 @@ use Inertia\Inertia;
|
||||
|
||||
class ClientPostController extends Controller
|
||||
{
|
||||
public function __construct(private readonly BreadcrumbService $breadcrumbService){}
|
||||
|
||||
public function index(Request $request)
|
||||
{
|
||||
// Кешируем список тегов
|
||||
@@ -129,23 +132,9 @@ class ClientPostController extends Controller
|
||||
],
|
||||
];
|
||||
|
||||
$routeUrl = route('client.post.index');
|
||||
$path = ltrim(parse_url($routeUrl, PHP_URL_PATH), '/');
|
||||
$breadcrumbs = $this->breadcrumbService->generateBreadcrumbs('client.post.index');
|
||||
|
||||
// Кешируем страницу
|
||||
$page = Cache::remember('page_' . $path, now()->addHours(1), function () use ($path) {
|
||||
return Page::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
|
||||
});
|
||||
|
||||
if (isset($page->section)) {
|
||||
$breadcrumbs = [
|
||||
'mainSection' => new ClientBreadcrumbSection($page->section->mainSection),
|
||||
'subSection' => new ClientBreadcrumbSubSection($page->section),
|
||||
'page' => new ClientBreadcrumbPage($page),
|
||||
];
|
||||
} else {
|
||||
$breadcrumbs = null;
|
||||
}
|
||||
|
||||
return Inertia::render('Client/Posts/Index', compact('filters', 'posts', 'categories', 'tags', 'breadcrumbs'));
|
||||
}
|
||||
@@ -165,24 +154,7 @@ class ClientPostController extends Controller
|
||||
// Преобразуем пост в ресурс
|
||||
$postResource = new PostResource($post);
|
||||
|
||||
// Получаем путь для страницы
|
||||
$routeUrl = route('client.post.index');
|
||||
$path = ltrim(parse_url($routeUrl, PHP_URL_PATH), '/');
|
||||
|
||||
// Получаем данные страницы
|
||||
$page = Page::where('path', '=', $path)
|
||||
->with('section.pages.section', 'section.mainSection')
|
||||
->first();
|
||||
|
||||
// Формируем хлебные крошки
|
||||
$breadcrumbs = null;
|
||||
if (isset($page->section)) {
|
||||
$breadcrumbs = [
|
||||
'mainSection' => new ClientBreadcrumbSection($page->section->mainSection),
|
||||
'subSection' => new ClientBreadcrumbSubSection($page->section),
|
||||
'page' => new ClientBreadcrumbPage($page),
|
||||
];
|
||||
}
|
||||
$breadcrumbs = $this->breadcrumbService->generateBreadcrumbs('client.post.index');
|
||||
|
||||
// SEO-данные
|
||||
$seo = $post->seo ?? null;
|
||||
|
||||
@@ -45,6 +45,7 @@ class ClientProgramController extends Controller
|
||||
DirectionStudy::query()
|
||||
->withAdmissionCampaignByYear($activeCampaign->academic_year)
|
||||
->withActivePrograms()
|
||||
->with('programs.admission_plans')
|
||||
->when($level, function ($query) use ($level) {
|
||||
$query->where('lvl_edu', LevelEducational::fromName($level)->value);
|
||||
})
|
||||
@@ -149,12 +150,13 @@ class ClientProgramController extends Controller
|
||||
{
|
||||
$budgetValue = Str::of(BudgetEducation::fromName($budget)->value)->toString();
|
||||
|
||||
|
||||
$query->whereHas('programs.admission_plans', function ($query) use ($budgetValue) {
|
||||
$query->whereJsonContains('contests', [['places' => ['form_budget' => $budgetValue]]]);
|
||||
$query->whereJsonContains('contests', ['financing_source' => $budgetValue]);
|
||||
})
|
||||
->with(['programs' => function ($query) use ($budgetValue) {
|
||||
$query->whereHas('admission_plans', function ($query) use ($budgetValue) {
|
||||
$query->whereJsonContains('contests', [['places' => ['form_budget' => $budgetValue]]]);
|
||||
$query->whereJsonContains('contests', ['financing_source' => $budgetValue]);
|
||||
});
|
||||
}]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use App\Models\Slider;
|
||||
|
||||
class ClientWidgetSliderController extends Controller
|
||||
{
|
||||
public function show(string $slug): ?object
|
||||
{
|
||||
$cacheKey = 'slider_' . $slug;
|
||||
|
||||
return Cache::remember($cacheKey, now()->addHour(), function () use ($slug) {
|
||||
$slider = Slider::query()
|
||||
->where('slug', $slug)
|
||||
->where('is_active', true)
|
||||
->with('slides')
|
||||
->first();
|
||||
|
||||
return $slider ?: null;
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -43,21 +43,21 @@ class MainController extends Controller
|
||||
// return $this->getAdmissionCampaign();
|
||||
// });
|
||||
|
||||
$educations = Cache::remember('educations_data', now()->addHour(), function () {
|
||||
return $this->getEducationsData();
|
||||
});
|
||||
// $educations = Cache::remember('educations_data', now()->addHour(), function () {
|
||||
// return $this->getEducationsData();
|
||||
// });
|
||||
|
||||
$sliders = Cache::remember('active_sliders', now()->addHour(), function () {
|
||||
return $this->getActiveSliders();
|
||||
});
|
||||
$educations = $this->getEducationsData();
|
||||
|
||||
$posts = Cache::remember('recent_posts', now()->addHour(), function () {
|
||||
return $this->getRecentPosts();
|
||||
});
|
||||
|
||||
$events = Cache::remember('upcoming_events', now()->addHour(), function () {
|
||||
return $this->getUpcomingEvents();
|
||||
});
|
||||
// $events = Cache::remember('upcoming_events', now()->addHour(), function () {
|
||||
// return $this->getUpcomingEvents();
|
||||
// });
|
||||
|
||||
$events = $this->getUpcomingEvents();
|
||||
|
||||
$path = route('index', null, false);
|
||||
$page = Cache::remember('page_' . $path, now()->addHour(), function () use ($path) {
|
||||
@@ -66,7 +66,7 @@ class MainController extends Controller
|
||||
|
||||
$seo = $page->seo ?? null;
|
||||
|
||||
return Inertia::render('Main', compact('posts', 'events', 'sliders', 'educations', 'seo'));
|
||||
return Inertia::render('Main', compact('posts', 'events', 'educations', 'seo'));
|
||||
}
|
||||
|
||||
private function getAdmissionCampaign()
|
||||
@@ -99,13 +99,6 @@ class MainController extends Controller
|
||||
];
|
||||
}
|
||||
|
||||
private function getActiveSliders()
|
||||
{
|
||||
return (ClientMainSliderResource::collection(
|
||||
MainSlider::where('is_active', true)
|
||||
->orderBy('sort', 'asc')
|
||||
->get()));
|
||||
}
|
||||
|
||||
private function getRecentPosts()
|
||||
{
|
||||
|
||||
@@ -7,9 +7,7 @@ use App\Http\Resources\EducationalProgramSearchResource;
|
||||
use App\Http\Resources\EducationGroupSearchResource;
|
||||
use App\Http\Resources\EventSearchResource;
|
||||
use App\Http\Resources\FacultySearchResource;
|
||||
use App\Http\Resources\PageResource;
|
||||
use App\Http\Resources\PageSearchResource;
|
||||
use App\Http\Resources\PostResource;
|
||||
use App\Http\Resources\PostSearchResource;
|
||||
use App\Http\Resources\UserSearchResource;
|
||||
use App\Models\AdditionalEducation;
|
||||
|
||||
@@ -23,6 +23,15 @@ class Page extends Model
|
||||
return $this->morphOne(Seo::class, 'seoable');
|
||||
}
|
||||
|
||||
public function getBreadcrumbs(string $url) : array
|
||||
{
|
||||
$path = ltrim(parse_url(route($url), PHP_URL_PATH), '/');
|
||||
|
||||
$page = self::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
|
||||
|
||||
dd($page);
|
||||
}
|
||||
|
||||
protected $casts = [
|
||||
'content' => 'array',
|
||||
'settings' => 'array',
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\ExternalVacancy;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class ExternalVacancyPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, ExternalVacancy $externalVacancy): bool
|
||||
{
|
||||
return $user->can('view_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, ExternalVacancy $externalVacancy): bool
|
||||
{
|
||||
return $user->can('update_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, ExternalVacancy $externalVacancy): bool
|
||||
{
|
||||
return $user->can('delete_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, ExternalVacancy $externalVacancy): bool
|
||||
{
|
||||
return $user->can('force_delete_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, ExternalVacancy $externalVacancy): bool
|
||||
{
|
||||
return $user->can('restore_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, ExternalVacancy $externalVacancy): bool
|
||||
{
|
||||
return $user->can('replicate_external::vacancy');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_external::vacancy');
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\LibraryNews;
|
||||
use App\Models\Slide;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class LibraryNewsPolicy
|
||||
class SlidePolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
@@ -15,15 +15,15 @@ class LibraryNewsPolicy
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_library::news');
|
||||
return $user->can('view_any_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, LibraryNews $libraryNews): bool
|
||||
public function view(User $user, Slide $slide): bool
|
||||
{
|
||||
return $user->can('view_library::news');
|
||||
return $user->can('view_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,23 +31,23 @@ class LibraryNewsPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_library::news');
|
||||
return $user->can('create_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, LibraryNews $libraryNews): bool
|
||||
public function update(User $user, Slide $slide): bool
|
||||
{
|
||||
return $user->can('update_library::news');
|
||||
return $user->can('update_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, LibraryNews $libraryNews): bool
|
||||
public function delete(User $user, Slide $slide): bool
|
||||
{
|
||||
return $user->can('delete_library::news');
|
||||
return $user->can('delete_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,15 +55,15 @@ class LibraryNewsPolicy
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_library::news');
|
||||
return $user->can('delete_any_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, LibraryNews $libraryNews): bool
|
||||
public function forceDelete(User $user, Slide $slide): bool
|
||||
{
|
||||
return $user->can('force_delete_library::news');
|
||||
return $user->can('force_delete_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,15 +71,15 @@ class LibraryNewsPolicy
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_library::news');
|
||||
return $user->can('force_delete_any_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, LibraryNews $libraryNews): bool
|
||||
public function restore(User $user, Slide $slide): bool
|
||||
{
|
||||
return $user->can('restore_library::news');
|
||||
return $user->can('restore_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,15 +87,15 @@ class LibraryNewsPolicy
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_library::news');
|
||||
return $user->can('restore_any_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, LibraryNews $libraryNews): bool
|
||||
public function replicate(User $user, Slide $slide): bool
|
||||
{
|
||||
return $user->can('replicate_library::news');
|
||||
return $user->can('replicate_slide');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,6 +103,6 @@ class LibraryNewsPolicy
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_library::news');
|
||||
return $user->can('reorder_slide');
|
||||
}
|
||||
}
|
||||
@@ -3,10 +3,10 @@
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\VacantPosition;
|
||||
use App\Models\Slider;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class VacantPositionPolicy
|
||||
class SliderPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
@@ -15,15 +15,15 @@ class VacantPositionPolicy
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_vacant::position');
|
||||
return $user->can('view_any_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, VacantPosition $vacantPosition): bool
|
||||
public function view(User $user, Slider $slider): bool
|
||||
{
|
||||
return $user->can('view_vacant::position');
|
||||
return $user->can('view_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -31,23 +31,23 @@ class VacantPositionPolicy
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_vacant::position');
|
||||
return $user->can('create_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, VacantPosition $vacantPosition): bool
|
||||
public function update(User $user, Slider $slider): bool
|
||||
{
|
||||
return $user->can('update_vacant::position');
|
||||
return $user->can('update_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, VacantPosition $vacantPosition): bool
|
||||
public function delete(User $user, Slider $slider): bool
|
||||
{
|
||||
return $user->can('delete_vacant::position');
|
||||
return $user->can('delete_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -55,15 +55,15 @@ class VacantPositionPolicy
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_vacant::position');
|
||||
return $user->can('delete_any_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, VacantPosition $vacantPosition): bool
|
||||
public function forceDelete(User $user, Slider $slider): bool
|
||||
{
|
||||
return $user->can('force_delete_vacant::position');
|
||||
return $user->can('force_delete_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,15 +71,15 @@ class VacantPositionPolicy
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_vacant::position');
|
||||
return $user->can('force_delete_any_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, VacantPosition $vacantPosition): bool
|
||||
public function restore(User $user, Slider $slider): bool
|
||||
{
|
||||
return $user->can('restore_vacant::position');
|
||||
return $user->can('restore_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -87,15 +87,15 @@ class VacantPositionPolicy
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_vacant::position');
|
||||
return $user->can('restore_any_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, VacantPosition $vacantPosition): bool
|
||||
public function replicate(User $user, Slider $slider): bool
|
||||
{
|
||||
return $user->can('replicate_vacant::position');
|
||||
return $user->can('replicate_slider');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,6 +103,6 @@ class VacantPositionPolicy
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_vacant::position');
|
||||
return $user->can('reorder_slider');
|
||||
}
|
||||
}
|
||||
@@ -1,108 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\User;
|
||||
use App\Models\VirtualExhibition;
|
||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||
|
||||
class VirtualExhibitionPolicy
|
||||
{
|
||||
use HandlesAuthorization;
|
||||
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return $user->can('view_any_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, VirtualExhibition $virtualExhibition): bool
|
||||
{
|
||||
return $user->can('view_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return $user->can('create_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, VirtualExhibition $virtualExhibition): bool
|
||||
{
|
||||
return $user->can('update_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, VirtualExhibition $virtualExhibition): bool
|
||||
{
|
||||
return $user->can('delete_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk delete.
|
||||
*/
|
||||
public function deleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('delete_any_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete.
|
||||
*/
|
||||
public function forceDelete(User $user, VirtualExhibition $virtualExhibition): bool
|
||||
{
|
||||
return $user->can('force_delete_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently bulk delete.
|
||||
*/
|
||||
public function forceDeleteAny(User $user): bool
|
||||
{
|
||||
return $user->can('force_delete_any_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore.
|
||||
*/
|
||||
public function restore(User $user, VirtualExhibition $virtualExhibition): bool
|
||||
{
|
||||
return $user->can('restore_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can bulk restore.
|
||||
*/
|
||||
public function restoreAny(User $user): bool
|
||||
{
|
||||
return $user->can('restore_any_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can replicate.
|
||||
*/
|
||||
public function replicate(User $user, VirtualExhibition $virtualExhibition): bool
|
||||
{
|
||||
return $user->can('replicate_virtual::exhibition');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can reorder.
|
||||
*/
|
||||
public function reorder(User $user): bool
|
||||
{
|
||||
return $user->can('reorder_virtual::exhibition');
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,6 @@ use Filament\Pages;
|
||||
use Filament\Panel;
|
||||
use Filament\PanelProvider;
|
||||
use Filament\Support\Colors\Color;
|
||||
use Filament\Widgets;
|
||||
use Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse;
|
||||
use Illuminate\Cookie\Middleware\EncryptCookies;
|
||||
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
|
||||
@@ -20,7 +19,6 @@ use Illuminate\Session\Middleware\AuthenticateSession;
|
||||
use Illuminate\Session\Middleware\StartSession;
|
||||
use Illuminate\View\Middleware\ShareErrorsFromSession;
|
||||
use ShuvroRoy\FilamentSpatieLaravelBackup\FilamentSpatieLaravelBackupPlugin;
|
||||
use Vormkracht10\TwoFactorAuth\TwoFactorAuthPlugin;
|
||||
|
||||
class AdminPanelProvider extends PanelProvider
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\App\Breadcrumb;
|
||||
|
||||
use App\Http\Resources\ClientBreadcrumbPage;
|
||||
use App\Http\Resources\ClientBreadcrumbSection;
|
||||
use App\Http\Resources\ClientBreadcrumbSubSection;
|
||||
use App\Models\Page;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class BreadcrumbService
|
||||
{
|
||||
public function generateBreadcrumbs($routeName) : array|null
|
||||
{
|
||||
$path = $this->generatePath($routeName);
|
||||
|
||||
// Кешируем страницу
|
||||
$page = Cache::remember('page_' . $path, now()->addHours(1), function () use ($path) {
|
||||
return Page::where('path', '=', $path)->with('section.pages.section', 'section.mainSection')->first();
|
||||
});
|
||||
|
||||
if (isset($page->section)) {
|
||||
$breadcrumbs = [
|
||||
'mainSection' => new ClientBreadcrumbSection($page->section->mainSection),
|
||||
'subSection' => new ClientBreadcrumbSubSection($page->section),
|
||||
'page' => new ClientBreadcrumbPage($page),
|
||||
];
|
||||
} else {
|
||||
$breadcrumbs = null;
|
||||
}
|
||||
|
||||
return $breadcrumbs;
|
||||
}
|
||||
|
||||
private function generatePath($routeName) : string
|
||||
{
|
||||
$routeUrl = route($routeName);
|
||||
return ltrim(parse_url($routeUrl, PHP_URL_PATH), '/');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user