Добавлена возможность редактировать и создавать новости
This commit is contained in:
parent
ef147fbfdb
commit
77fcdfec0b
@ -22,4 +22,5 @@
|
|||||||
|
|
||||||
Работа с проектом:
|
Работа с проектом:
|
||||||
>git pull
|
>git pull
|
||||||
|
>php artisan vendor:publish --provider="Te7aHoudini\LaravelTrix\LaravelTrixServiceProvider"
|
||||||
>php artisan migrate
|
>php artisan migrate
|
||||||
@ -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
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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)
|
||||||
|
|||||||
36
app/Modules/Main/Http/Policies/ContentPolicy.php
Normal file
36
app/Modules/Main/Http/Policies/ContentPolicy.php
Normal 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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 {
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
app/Modules/Post/Http/Livewire/PostUpdate.php
Normal file
32
app/Modules/Post/Http/Livewire/PostUpdate.php
Normal 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()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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);
|
||||||
|
|
||||||
|
|||||||
@ -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
|
||||||
@ -40,4 +49,9 @@ public function cities(): HasManyThrough
|
|||||||
'city_id'
|
'city_id'
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function scopeVisibleForUser(Builder $query)
|
||||||
|
{
|
||||||
|
auth()->user()->can('view', $this) ? $query : $query->whereRaw('0 = 1');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -26,19 +26,25 @@ 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
|
||||||
{
|
{
|
||||||
if ($postCities = $post->cities->pluck('id')->toArray()) {
|
|
||||||
$availableCities = GetAvailableCities()->pluck('id')->toArray();
|
$availableCities = GetAvailableCities()->pluck('id')->toArray();
|
||||||
if (array_intersect($postCities, $availableCities)) {
|
if (!$availableCities) {
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($postCities = $post->cities->pluck('id')->toArray()) {
|
||||||
|
if (!array_intersect($postCities, $availableCities)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether the user can create models.
|
* Determine whether the user can create models.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@ -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()
|
||||||
|
|||||||
93
app/Modules/Post/Views/form/update.blade.php
Normal file
93
app/Modules/Post/Views/form/update.blade.php
Normal 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>
|
||||||
@ -28,14 +28,19 @@
|
|||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-none ms-auto py-2 hstack gap-2">
|
<div class="ms-auto py-2 hstack gap-2">
|
||||||
<select class="form-select form-select-lg bg-white" disabled aria-label="Large select example">
|
@can('create', \Modules\Post\Models\Post::class)
|
||||||
|
<div class="mb-3">
|
||||||
|
@livewire('post.form', ['post' => new \Modules\Post\Models\Post()])
|
||||||
|
</div>
|
||||||
|
@endcan
|
||||||
|
<select class="d-none form-select form-select-lg bg-white" disabled aria-label="Large select example">
|
||||||
<option selected>Город: любой</option>
|
<option selected>Город: любой</option>
|
||||||
<option value="1">Иркутск</option>
|
<option value="1">Иркутск</option>
|
||||||
<option value="2">Владивосток</option>
|
<option value="2">Владивосток</option>
|
||||||
<option value="3">Красноярск</option>
|
<option value="3">Красноярск</option>
|
||||||
</select>
|
</select>
|
||||||
<select class="form-select form-select-lg bg-white" disabled aria-label="Large select example">
|
<select class="d-none form-select form-select-lg bg-white" disabled aria-label="Large select example">
|
||||||
<option selected>Проект: все проекты</option>
|
<option selected>Проект: все проекты</option>
|
||||||
<option value="1">Проект 1</option>
|
<option value="1">Проект 1</option>
|
||||||
<option value="2">Проект 2</option>
|
<option value="2">Проект 2</option>
|
||||||
@ -59,5 +64,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@endsection
|
@endsection
|
||||||
@ -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>
|
||||||
|
|||||||
@ -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
59
composer.lock
generated
@ -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
9
config/laravel-trix.php
Normal 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',
|
||||||
|
];
|
||||||
@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -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>
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user