Добавлена возможность редактировать и создавать новости

This commit is contained in:
developer 2026-05-08 13:39:17 +08:00
parent ef147fbfdb
commit 77fcdfec0b
20 changed files with 388 additions and 183 deletions

View File

@ -22,4 +22,5 @@
Работа с проектом: Работа с проектом:
>git pull >git pull
>php artisan vendor:publish --provider="Te7aHoudini\LaravelTrix\LaravelTrixServiceProvider"
>php artisan migrate >php artisan migrate

View File

@ -75,7 +75,7 @@ private function createPolicy()
$policy = Str::singular(class_basename($this->option('create_policy'))); $policy = Str::singular(class_basename($this->option('create_policy')));
$model = Str::singular(class_basename($this->option('model'))); $model = Str::singular(class_basename($this->option('model')));
$this->call('make:policy', [ $this->call('make:policy', [
'name' => 'App\\Modules\\' . $path . '\\Policies\\' . $policy, 'name' => 'App\\Modules\\' . $path . '\\Http\\Policies\\' . $policy,
'--model' => $model '--model' => $model
]); ]);
} }

View File

@ -38,6 +38,7 @@ public function create()
public function store(Request $request) public function store(Request $request)
{ {
$request['text'] = 'none';
$validated = $request->validate([ $validated = $request->validate([
'name' => 'required', 'name' => 'required',
'category' => 'required', 'category' => 'required',
@ -64,7 +65,7 @@ public function store(Request $request)
$path = $request->file('imageFile')->store('posts', ['disk' => 'public']); $path = $request->file('imageFile')->store('posts', ['disk' => 'public']);
$request['image'] = $path; $request['image'] = $path;
$post = Post::create( $post = Post::create(
$request->only(['name', 'short_text', 'text', 'category', 'image']) $request->only(['name', 'short_text', 'text', 'category', 'image', 'post-trixFields'])
); );
if (array_key_exists('cities', $request->all()) && is_array($request['cities'])) { if (array_key_exists('cities', $request->all()) && is_array($request['cities'])) {
foreach ($request->cities as $cityId) { foreach ($request->cities as $cityId) {
@ -87,11 +88,14 @@ public function edit(Post $post)
public function update(Request $request, Post $post) public function update(Request $request, Post $post)
{ {
$request['text'] = 'none';
$validated = $request->validate([ $validated = $request->validate([
'name' => 'required', 'name' => 'required',
'category' => 'required', 'category' => 'required',
'short_text' => 'max:500', 'short_text' => 'max:500',
'text' => 'required', 'text' => 'required',
'imageFile' => 'mimes:jpg,bmp,png'
]); ]);
if ($request->file('imageFile')) { if ($request->file('imageFile')) {
@ -100,10 +104,11 @@ public function update(Request $request, Post $post)
} else { } else {
$reuqest['image'] = $post->image; $reuqest['image'] = $post->image;
} }
$post = $post->update( $post = $post->update(
$request->only(['name', 'short_text', 'text', 'category', 'image']) $request->only(['name', 'short_text', 'text', 'category', 'image', 'post-trixFields'])
); );
return to_route('admin.posts'); return back()->withSuccess('Новость обновлена успешно');
} }
public function delete(Post $post) public function delete(Post $post)

View File

@ -0,0 +1,36 @@
<?php
namespace Modules\Main\Http\Policies;
use Illuminate\Auth\Access\Response;
use Modules\Main\Models\City;
use Modules\User\Models\User;
use Modules\CityManager\Models\CityManager;
class ContentPolicy
{
public function before(User $user, string $ability): bool|null
{
if ($user->isAdmin()) {
return true;
}
return null;
}
/**
* Determine whether the user can CRUD content (posts, agents, documents)
*/
public function manageContent(User $user, City $city): bool
{
if (!$cityManagersOfUser = CityManager::where('user_id', $user->id)->get()) {
return false;
}
foreach ($cityManagersOfUser as $cityManager) {
if ($cityManager->city_id == $city->id) {
return true;
}
}
return false;
}
}

View File

@ -14,10 +14,7 @@ public function apply(Builder $builder, Model $model): void
{ {
//dd(GetAvailableCities()); //dd(GetAvailableCities());
if ($cities = GetAvailableCities()) { //получаю доступные пользователю города if ($cities = GetAvailableCities()) { //получаю доступные пользователю города
$citiesIds = []; $citiesIds = $cities->pluck('id')->toArray();
foreach ($cities as $city) {
$citiesIds[] = $city->id;
}
$builder->whereHas('cities', fn($q) => $q->whereIn('cities.id', $citiesIds)); $builder->whereHas('cities', fn($q) => $q->whereIn('cities.id', $citiesIds));
$builder->OrDoesntHave('cities'); $builder->OrDoesntHave('cities');
} else { } else {

View File

@ -93,6 +93,7 @@ protected function registerComponent()
protected function registerPolicies() protected function registerPolicies()
{ {
Gate::policy(\Modules\Main\Models\Company\Company::class, \Modules\Main\Http\Policies\CompanyPolicy::class); Gate::policy(\Modules\Main\Models\Company\Company::class, \Modules\Main\Http\Policies\CompanyPolicy::class);
Gate::policy(\Modules\Main\Models\City::class, \Modules\Main\Http\Policies\ContentPolicy::class);
} }
protected function registerHelpers() protected function registerHelpers()

View File

@ -1,106 +0,0 @@
<?php
namespace Modules\Post\Http\Livewire;
use Livewire\Component;
use Livewire\Attributes\Validate;
use Livewire\Attributes\On;
class PostCreator extends Component
{
public $categories = [];
protected function rules()
{
return [
];
}
protected function messages()
{
return [
];
}
public function mount()
{
}
public function updated($propertyName)
{
}
public function render()
{
return view(
'post::form.index'
);
}
public function rendered()
{
$this->dispatch('phoneInputAdded');
}
public function resetData()
{
$this->mount();
}
public function back()
{
$this->status = FormStatus::IN_PROCESS;
}
public function save()
{
$hasErrors = false;
foreach ($this->selectedObjects as $complexId=>$room) {
if ($this->createDeal($complexId, $room)) {
unset($this->selectedObjects[$complexId]);
} else {
$hasErrors = true;
}
}
if ($hasErrors) {
return $this->status = FormStatus::ERROR;
}
$this->status = FormStatus::SUCCESS;
}
private function createDeal($complexId, $room)
{
if (
!$deal = Deal::create([
'agent_id' => $this->agentId,
'complex_id' => $complexId,
'plan7_data' => (is_array($room) && array_key_exists('id', $room)) ? json_encode($room) : null
])
) {
return false;
}
foreach ($this->contacts as $contact) {
if (
!$newUser = Client::updateOrCreate(
['phone' => $contact['phones'][0]],
[
'name' => trim($contact['firstName'] . ' ' . $contact['secondName']),
'phone' => $contact['phones'][0]
]
)
) {
return false;
}
if (
!$dealClient = DealClients::firstOrCreate([
'deal_id' => $deal->id,
'client_id' => $newUser->id
])
) {
return false;
}
}
$this->dispatch('clientCreated');
return true;
}
}

View File

@ -0,0 +1,32 @@
<?php
namespace Modules\Post\Http\Livewire;
use Livewire\Component;
use Livewire\Attributes\Validate;
use Livewire\Attributes\On;
use Modules\Post\Models\Post;
class PostUpdate extends Component
{
public $categories = [];
public $availableCities = [];
public Post $post;
public $isActive = false;
public function mount(Post $post)
{
$this->categories = \Modules\Post\Models\PostCategory::cases();
$this->post = $post;
$this->availableCities = GetAvailableCities();
}
public function render()
{
return view(
'post::form.update'
);
}
public function rendered()
{
}
}

View File

@ -22,7 +22,7 @@ public function open($id)
} }
public function render() public function render()
{ {
$posts = Post::orderBy('id', 'desc'); $posts = Post::orderBy('id', 'desc')->visibleForUser();
if ($this->category && $this->category != 'all') if ($this->category && $this->category != 'all')
$posts = $posts->where('category', $this->category); $posts = $posts->where('category', $this->category);

View File

@ -6,27 +6,36 @@
use Modules\Post\Models\PostCity; use Modules\Post\Models\PostCity;
use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasManyThrough; use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasMany;
use Te7aHoudini\LaravelTrix\Traits\HasTrixRichText;
use Modules\Main\Models\Scopes\CityScope; use Modules\Main\Models\Scopes\CityScope;
class Post extends Model class Post extends Model
{ {
use HasFactory; use HasFactory;
use HasTrixRichText;
protected $guarded = [];
protected $fillable = [ protected $fillable = [
'name', 'name',
'short_text', 'short_text',
'text', 'text',
'category', 'category',
'image' 'image',
'post-trixFields'
]; ];
protected static function booted(): void protected static function booted(): void
{ {
static::addGlobalScope(new CityScope); static::addGlobalScope(new CityScope);
static::deleted(function ($post) {
$post->trixRichText->each->delete();
$post->trixAttachments->each->purge();
});
} }
public function cities(): HasManyThrough public function cities(): HasManyThrough
@ -38,6 +47,11 @@ public function cities(): HasManyThrough
'id', 'id',
'id', 'id',
'city_id' 'city_id'
); );
}
public function scopeVisibleForUser(Builder $query)
{
auth()->user()->can('view', $this) ? $query : $query->whereRaw('0 = 1');
} }
} }

View File

@ -26,17 +26,23 @@ public function viewAny(User $user): bool
} }
/** /**
* Determine whether the user can view the model. * Проврка возможности просмотра новости.
* Если пользователь не состоит ни в одной из ролей ни в одном из городов, то false
* Далее проверка, если новость привязана к городам и у пользователя нет пересечений по этим городам, то false
*/ */
public function view(User $user, Post $post): bool public function view(User $user, Post $post): bool
{ {
$availableCities = GetAvailableCities()->pluck('id')->toArray();
if (!$availableCities) {
return false;
}
if ($postCities = $post->cities->pluck('id')->toArray()) { if ($postCities = $post->cities->pluck('id')->toArray()) {
$availableCities = GetAvailableCities()->pluck('id')->toArray(); if (!array_intersect($postCities, $availableCities)) {
if (array_intersect($postCities, $availableCities)) { return false;
return true;
} }
} }
return false; return true;
} }
/** /**

View File

@ -69,7 +69,7 @@ protected function registerLivewire()
{ {
Livewire::component('posts.list', \Modules\Post\Http\Livewire\PostsList::class); Livewire::component('posts.list', \Modules\Post\Http\Livewire\PostsList::class);
Livewire::component('post.card', \Modules\Post\Http\Livewire\PostCard::class); Livewire::component('post.card', \Modules\Post\Http\Livewire\PostCard::class);
Livewire::component('post.form', \Modules\Post\Http\Livewire\PostCreator::class); Livewire::component('post.form', \Modules\Post\Http\Livewire\PostUpdate::class);
} }
protected function registerComponent() protected function registerComponent()

View File

@ -0,0 +1,93 @@
<div>
<a href="#" wire:click="$toggle('isActive')" class="btn btn-primary">@if($post->id) Редактировать @else Новая публикация @endif</a>
@if($isActive == 'active')
<div class="modal fade show d-block bg-dark" style="--bs-bg-opacity: .5;z-index:3000" id="postCardModal" data-bs-backdrop="static"
data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
<form
class="modal-dialog modal-dialog-scrollable modal-lg modal-fullscreen-lg-down"
action="{{ ($post->id) ? route('admin.posts.update', ['post' => $post]) : route('admin.posts.store') }}" method="post" enctype="multipart/form-data">
<div class="modal-content">
<div class="modal-header border-0">
<h1 class="modal-title fs-5" id="exampleModalToggleLabel2">Редактирование новости</h1>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"
wire:click="$toggle('isActive')"></button>
</div>
<div class="modal-body">
<div>
@csrf
<div class="mb-3">
<label for="titleFormControlTextarea" class="form-label">Заголовок</label>
<textarea class="form-control" id="titleFormControlTextarea1" name="name" rows="2">{{ $post->name }}</textarea>
@error('name')
<div class="text-danger">{{ $message }}</div>
@enderror
</div>
<div class="text-dark mb-2">
<label class="form-label mb-1">Города для публикации</label>
<div class="mb-2 p-2 border rounded">
@if($availableCities = GetAvailableCities())
<div>
@foreach($availableCities as $key=>$city)
<div class="form-check form-check-inline">
<input name="cities[{{ $key }}]" class="form-check-input" type="checkbox" value="{{ $city->id }}" id="city_{{ $city->id }}">
<label class="form-check-label" for="city_{{ $city->id }}">
{{ $city->name }}
</label>
</div>
@endforeach
</div>
@endif
</div>
</div>
<div class="row">
<div class="col mb-3">
<label for="categoryFormControlSelect" class="form-label">Категория</label>
<select class="form-select" id="categoryFormControlSelect" name="category" aria-label="">
@foreach ($categories as $category)
<option value="{{ $category->value }}" {{ $post->category == $category->value ? 'selected' : '' }}>
{{ __($category->name) }}
</option>
@endforeach
</select>
@error('category')
<div class="text-danger">{{ $message }}</div>
@enderror
</div>
<div class="col mb-3">
<label for="formFile" class="form-label">Заставка новости</label>
<input class="form-control" type="file" id="formFile" name="imageFile">
@error('imageFile')
<div class="text-danger">{{ $message }}</div>
@enderror
</div>
</div>
<div class="mb-3">
<label for="shortTextFormControlTextarea" class="form-label">Анонс</label>
<textarea class="form-control" id="shortTextFormControlTextarea1" name="short_text"
rows="3">{{ $post->short_text }}</textarea>
@error('short_text')
<div class="text-danger">{{ $message }}</div>
@enderror
</div>
<div class="mb-3">
<label for="shortTextFormControlTextarea" class="form-label">Основной текст</label>
@trix($post, 'content', ['inputAttributes' => ['height' => '500px']])
@error('text')
<div class="text-danger">{{ $message }}</div>
@enderror
</div>
<button type="submit" class="btn btn-primary">Сохранить</button>
</div>
</div>
</div>
</form>
</div>
<style>
.trix-content {
height: 500px;
overflow-y: auto;
}
</style>
@endif
</div>

View File

@ -1,63 +1,70 @@
@extends('layouts.app') @extends('layouts.app')
@section('content') @section('content')
<style> <style>
.btn-check:checked+.btn { .btn-check:checked+.btn {
background-color: rgb(231, 117, 11); background-color: rgb(231, 117, 11);
color: white; color: white;
} }
td, td,
h4 { h4 {
color: #333c4e !important color: #333c4e !important
} }
</style> </style>
<div class="container"> <div class="container">
<div> <div>
<form class="d-lg-flex mb-3" method="GET" action="{{ route('posts') }}"> <form class="d-lg-flex mb-3" method="GET" action="{{ route('posts') }}">
<div class="p-2 border rounded-3 border-1 p-1 bg-white"> <div class="p-2 border rounded-3 border-1 p-1 bg-white">
<input type="radio" class="btn-check" onclick="this.form.submit()" name="filter[category]" value="all" <input type="radio" class="btn-check" onclick="this.form.submit()" name="filter[category]" value="all"
id="option_all" autocomplete="off" checked> id="option_all" autocomplete="off" checked>
<label class="btn p-2 fs-5" for="option_all">Все</label> <label class="btn p-2 fs-5" for="option_all">Все</label>
@foreach ($categories as $category) @foreach ($categories as $category)
<input type="radio" class="btn-check" onclick="this.form.submit()" name="filter[category]" <input type="radio" class="btn-check" onclick="this.form.submit()" name="filter[category]"
value="{{ $category->value }}" id="cat_{{ $category->name }}" autocomplete="off" value="{{ $category->value }}" id="cat_{{ $category->name }}" autocomplete="off"
{{ isset($filter) && isset($filter['category']) && $filter['category'] == $category->value ? 'checked' : '' }}> {{ isset($filter) && isset($filter['category']) && $filter['category'] == $category->value ? 'checked' : '' }}>
<label class="btn p-2 fs-5" for="cat_{{ $category->name }}">{{ __($category->name) }}</label> <label class="btn p-2 fs-5" for="cat_{{ $category->name }}">{{ __($category->name) }}</label>
@endforeach @endforeach
</div>
<div class="ms-auto py-2 hstack gap-2">
@can('create', \Modules\Post\Models\Post::class)
<div class="mb-3">
@livewire('post.form', ['post' => new \Modules\Post\Models\Post()])
</div> </div>
@endcan
<select class="d-none form-select form-select-lg bg-white" disabled aria-label="Large select example">
<option selected>Город: любой</option>
<option value="1">Иркутск</option>
<option value="2">Владивосток</option>
<option value="3">Красноярск</option>
</select>
<select class="d-none form-select form-select-lg bg-white" disabled aria-label="Large select example">
<option selected>Проект: все проекты</option>
<option value="1">Проект 1</option>
<option value="2">Проект 2</option>
<option value="3">Проект 3</option>
</select>
</div>
<div class="d-none ms-auto py-2 hstack gap-2"> </form>
<select class="form-select form-select-lg bg-white" disabled aria-label="Large select example">
<option selected>Город: любой</option>
<option value="1">Иркутск</option>
<option value="2">Владивосток</option>
<option value="3">Красноярск</option>
</select>
<select class="form-select form-select-lg bg-white" disabled aria-label="Large select example">
<option selected>Проект: все проекты</option>
<option value="1">Проект 1</option>
<option value="2">Проект 2</option>
<option value="3">Проект 3</option>
</select>
</div>
</form>
</div>
<div>
@livewire('posts.list', $filter)
</div>
<div class="position-fixed bottom-0 end-0 me-0 me-md-5" style="z-index:2000">
<a class="m-2 me-md-5 btn btn-primary rounded-circle d-flex justify-content-center align-items-center"
style="width:4rem;height:4rem" href="{{ route('post.create') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-plus-lg"
viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2" />
</svg>
</a>
</div>
</div> </div>
<div>
@livewire('posts.list', $filter)
</div>
<div class="position-fixed bottom-0 end-0 me-0 me-md-5" style="z-index:2000">
<a class="m-2 me-md-5 btn btn-primary rounded-circle d-flex justify-content-center align-items-center"
style="width:4rem;height:4rem" href="{{ route('post.create') }}">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" class="bi bi-plus-lg"
viewBox="0 0 16 16">
<path fill-rule="evenodd"
d="M8 2a.5.5 0 0 1 .5.5v5h5a.5.5 0 0 1 0 1h-5v5a.5.5 0 0 1-1 0v-5h-5a.5.5 0 0 1 0-1h5v-5A.5.5 0 0 1 8 2" />
</svg>
</a>
</div>
</div>
@endsection @endsection

View File

@ -20,8 +20,13 @@
</div> </div>
@endif @endif
<h1 class="mt-3">{{ $post->name }}</h1> <h1 class="mt-3">{{ $post->name }}</h1>
@can('update', $post)
<div class="mb-3">
@livewire('post.form', ['post' => $post])
</div>
@endcan
<p> <p>
{!! $post->text !!} {!! $post->trixRender('content') !!}
</p> </p>
</div> </div>
</div> </div>

View File

@ -16,7 +16,8 @@
"laravel/scout": "^11.1", "laravel/scout": "^11.1",
"laravel/tinker": "^2.8", "laravel/tinker": "^2.8",
"laravel/ui": "^4.5", "laravel/ui": "^4.5",
"livewire/livewire": "^3.5" "livewire/livewire": "^3.5",
"te7a-houdini/laravel-trix": "^3.1"
}, },
"require-dev": { "require-dev": {
"fakerphp/faker": "^1.9.1", "fakerphp/faker": "^1.9.1",

59
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "ea5a7c49862ceb1f5b573b695143a176", "content-hash": "71bff85f2be8492b6394f7265f7c4ccf",
"packages": [ "packages": [
{ {
"name": "bacon/bacon-qr-code", "name": "bacon/bacon-qr-code",
@ -5927,6 +5927,63 @@
], ],
"time": "2025-09-25T15:37:27+00:00" "time": "2025-09-25T15:37:27+00:00"
}, },
{
"name": "te7a-houdini/laravel-trix",
"version": "3.1.0",
"source": {
"type": "git",
"url": "https://github.com/amaelftah/laravel-trix.git",
"reference": "e8ff1c09420113b1bc40d02f95fc4b475349ca5d"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/amaelftah/laravel-trix/zipball/e8ff1c09420113b1bc40d02f95fc4b475349ca5d",
"reference": "e8ff1c09420113b1bc40d02f95fc4b475349ca5d",
"shasum": ""
},
"require": {
"laravel/framework": "~5.8.0|~6.0|~7.0|~8.0|~9.0|^10.0|^11.0|^12.0",
"php": "^7.1|^8.0"
},
"require-dev": {
"orchestra/testbench": "^3.5|~4.0|~5.0|~6.0|^8.0|^9.0|^10.0"
},
"type": "library",
"extra": {
"laravel": {
"providers": [
"Te7aHoudini\\LaravelTrix\\LaravelTrixServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Te7aHoudini\\LaravelTrix\\": "src"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Ahmed Abd El Ftah",
"email": "ahmedabdelftah95165@gmail.com",
"role": "Developer"
}
],
"description": "trix editor for laravel inspired by ActionText for rails",
"homepage": "https://github.com/te7ahoudini/laravel-trix",
"keywords": [
"laravel-trix",
"te7a-houdini"
],
"support": {
"issues": "https://github.com/amaelftah/laravel-trix/issues",
"source": "https://github.com/amaelftah/laravel-trix/tree/3.1.0"
},
"time": "2025-02-18T17:13:43+00:00"
},
{ {
"name": "tijsverkoyen/css-to-inline-styles", "name": "tijsverkoyen/css-to-inline-styles",
"version": "v2.3.0", "version": "v2.3.0",

9
config/laravel-trix.php Normal file
View File

@ -0,0 +1,9 @@
<?php
return [
'storage_disk' => env('LARAVEL_TRIX_STORAGE_DISK', 'public'),
'store_attachment_action' => Te7aHoudini\LaravelTrix\Http\Controllers\TrixAttachmentController::class.'@store',
'destroy_attachment_action' => Te7aHoudini\LaravelTrix\Http\Controllers\TrixAttachmentController::class.'@destroy',
];

View File

@ -0,0 +1,46 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateTrixRichTextsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('trix_rich_texts', function (Blueprint $table) {
$table->unsignedBigInteger('id')->autoIncrement();
$table->string('field');
$table->morphs('model');
$table->text('content')->nullable();
$table->timestamps();
});
Schema::create('trix_attachments', function (Blueprint $table) {
$table->unsignedBigInteger('id')->autoIncrement();
$table->string('field');
$table->unsignedInteger('attachable_id')->nullable();
$table->string('attachable_type');
$table->string('attachment');
$table->string('disk');
$table->boolean('is_pending')->default(1);
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::drop('trix_attachments');
Schema::drop('trix_rich_texts');
}
}

View File

@ -15,6 +15,7 @@
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css"> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
@vite(['resources/sass/app.scss', 'resources/js/app.js', 'resources/js/multiselect.js', 'resources/js/zoomable.js', 'resources/css/app.css', 'resources/css/form.css', 'resources/css/docs.css', 'resources/css/plan7.css', 'resources/css/zoomable.css', 'resources/css/multiselect.css']) @vite(['resources/sass/app.scss', 'resources/js/app.js', 'resources/js/multiselect.js', 'resources/js/zoomable.js', 'resources/css/app.css', 'resources/css/form.css', 'resources/css/docs.css', 'resources/css/plan7.css', 'resources/css/zoomable.css', 'resources/css/multiselect.css'])
@include('layouts.design') @include('layouts.design')
@trixassets
<script src="https://plan7.ru/catalog/exp/cat.js"></script> <script src="https://plan7.ru/catalog/exp/cat.js"></script>
</head> </head>