creates
This commit is contained in:
parent
55215be5d9
commit
7b77a131ac
9 changed files with 99 additions and 75 deletions
|
@ -45,6 +45,7 @@ public function update(UpdateJoinedRequest $request, Joined $joined)
|
||||||
public function destroy(Joined $joined)
|
public function destroy(Joined $joined)
|
||||||
{
|
{
|
||||||
$joined->remove();
|
$joined->remove();
|
||||||
|
|
||||||
return redirect()->route('admin.joined.index')->with('success', 'Fanlisting removed.');
|
return redirect()->route('admin.joined.index')->with('success', 'Fanlisting removed.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,6 +35,9 @@ public function create()
|
||||||
*/
|
*/
|
||||||
public function store(StoreOwnedRequest $request)
|
public function store(StoreOwnedRequest $request)
|
||||||
{
|
{
|
||||||
|
Owned::store($request->validated());
|
||||||
|
|
||||||
|
return redirect()->route('admin.owned.index')->with('success', 'Fanlisting added!');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -32,7 +32,7 @@ public function rules()
|
||||||
'slug' => ['required', 'alpha_dash'],
|
'slug' => ['required', 'alpha_dash'],
|
||||||
'title' => ['nullable', 'string'],
|
'title' => ['nullable', 'string'],
|
||||||
'image' => ['nullable', 'image'],
|
'image' => ['nullable', 'image'],
|
||||||
'date_opened' => ['nullable', 'date'],
|
'opened' => ['nullable', 'date'],
|
||||||
'hold_member_updates' => ['nullable', 'boolean'],
|
'hold_member_updates' => ['nullable', 'boolean'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
use App\Traits\Categorizable;
|
use App\Traits\Categorizable;
|
||||||
use App\Traits\Imageable;
|
use App\Traits\Imageable;
|
||||||
use App\Traits\Ownable;
|
use App\Traits\Ownable;
|
||||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
@ -35,15 +34,6 @@ class Joined extends Model
|
||||||
|
|
||||||
// injected by trait: categories (morph many-to-many)
|
// injected by trait: categories (morph many-to-many)
|
||||||
|
|
||||||
/* -------------------------------------------------------------------------- attributes ---- */
|
|
||||||
|
|
||||||
protected function approved() : Attribute
|
|
||||||
{
|
|
||||||
return Attribute::make(
|
|
||||||
set: fn ($value) => isset($value) ? $value = $value : $value = false,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------------ joined ---- */
|
/* ------------------------------------------------------------------------------ joined ---- */
|
||||||
|
|
||||||
public static function store(array $validated) : Joined
|
public static function store(array $validated) : Joined
|
||||||
|
|
|
@ -17,5 +17,35 @@ class Owned extends Model
|
||||||
|
|
||||||
protected $table = 'owned';
|
protected $table = 'owned';
|
||||||
|
|
||||||
|
protected $casts = [
|
||||||
|
'opened' => 'datetime',
|
||||||
|
'hold_member_updates' => 'boolean',
|
||||||
|
];
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- relationships ---- */
|
/* ----------------------------------------------------------------------- relationships ---- */
|
||||||
|
|
||||||
|
// injected by trait: collective (belongsTo)
|
||||||
|
|
||||||
|
// injected by trait: categories (many-to-many polymorphic)
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------------- store ---- */
|
||||||
|
|
||||||
|
public static function store(array $validated) : static
|
||||||
|
{
|
||||||
|
$validated['image'] = $validated['image'] ?? null;
|
||||||
|
|
||||||
|
$owned = new static();
|
||||||
|
$owned->subject = $validated['subject'];
|
||||||
|
$owned->status = $validated['status'];
|
||||||
|
$owned->slug = $validated['slug'];
|
||||||
|
$owned->title = $validated['title'] ?? null;
|
||||||
|
$owned->image = self::imagePath($validated['image']);
|
||||||
|
$owned->opened = $validated['opened'] ?? null;
|
||||||
|
$owned->hold_member_updates = $validated['hold_member_updates'] ?? false;
|
||||||
|
|
||||||
|
auth_collective()->owned()->save($owned);
|
||||||
|
$owned->categories()->sync($validated['categories']);
|
||||||
|
|
||||||
|
return $owned;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,10 +8,10 @@ trait Imageable
|
||||||
{
|
{
|
||||||
public static function imagePath($image) : ?string
|
public static function imagePath($image) : ?string
|
||||||
{
|
{
|
||||||
$path = strtolower(static::class);
|
$path = strtolower(substr(strrchr(__CLASS__, '\\'), 1));
|
||||||
|
|
||||||
if (isset($image)) {
|
if (isset($image)) {
|
||||||
return Storage::putFile($path, $image);
|
return $image->storePublicly($path, 'public');
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,8 @@
|
||||||
|
|
||||||
@section('content')
|
@section('content')
|
||||||
|
|
||||||
<form action="{{ route('admin.owned.store') }}" method="POST" autocomplete="off">
|
<form action="{{ route('admin.owned.store') }}" method="POST" autocomplete="off"
|
||||||
|
enctype="multipart/form-data">
|
||||||
@csrf
|
@csrf
|
||||||
|
|
||||||
<fieldset class="form__fieldset">
|
<fieldset class="form__fieldset">
|
||||||
|
@ -18,7 +19,7 @@
|
||||||
<x-form.text name="slug" :label="'Slug:'" required />
|
<x-form.text name="slug" :label="'Slug:'" required />
|
||||||
<x-form.text name="title" :label="'Title:'" />
|
<x-form.text name="title" :label="'Title:'" />
|
||||||
<x-form.file name="image" />
|
<x-form.file name="image" />
|
||||||
<x-form.date name="date_opened" :label="'Date opened:'" />
|
<x-form.date name="opened" :label="'Date opened:'" />
|
||||||
<x-form.checkbox name="hold_member_updates" :label="'Hold member updates?'" />
|
<x-form.checkbox name="hold_member_updates" :label="'Hold member updates?'" />
|
||||||
|
|
||||||
<x-form.buttons />
|
<x-form.buttons />
|
||||||
|
|
|
@ -1,51 +1,50 @@
|
||||||
<div>
|
<div>
|
||||||
<input type="text" name="search" placeholder="Search fanlistings..." class="form__input--search"
|
<input type="text" name="search" placeholder="Search fanlistings..." class="form__input--search"
|
||||||
wire:model="searchTerm" />
|
wire:model="searchTerm" />
|
||||||
<table class="table">
|
<table class="table">
|
||||||
<thead class="table__thead">
|
<thead class="table__thead">
|
||||||
<tr>
|
<tr>
|
||||||
<th>{{-- approved --}}</th>
|
<th>{{-- approved --}}</th>
|
||||||
<th>Subject</th> {{-- link --}}
|
<th>Subject</th> {{-- link --}}
|
||||||
<th>Categories</th>
|
<th>Categories</th>
|
||||||
<th>Image</th>
|
<th>Image</th>
|
||||||
<th colspan="3">Actions</th>
|
<th colspan="3">Actions</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
|
|
||||||
<tbody class="table__tbody">
|
<tbody class="table__tbody">
|
||||||
@foreach ($fanlistings as $fl)
|
@foreach ($fanlistings as $fl)
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
@if (!$fl->approved)
|
@if (!$fl->approved)
|
||||||
<span class="text--error">×</span>
|
<span class="text--error">×</span>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
<td><a href="{{ $fl->url }}" target="_blank">{{ $fl->subject }}</a></td>
|
<td><a href="{{ $fl->url }}" target="_blank">{{ $fl->subject }}</a></td>
|
||||||
<td>{{ $fl->listCategories() }}</td>
|
<td>{{ $fl->listCategories() }}</td>
|
||||||
<td><img src="{{ $fl->image }}"></td>
|
<td><img src="/storage/{{ $fl->image }}"></td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
@if ($class == 'joined' && $fl->approved == false)
|
@if ($class == 'joined' && $fl->approved == false)
|
||||||
<button wire:click="approve({{ $fl }})" class="btn--table">
|
<button wire:click="approve({{ $fl }})" class="btn--table">
|
||||||
Approve
|
Approve
|
||||||
</button>
|
</button>
|
||||||
@elseif ($class == 'owned')
|
@elseif ($class == 'owned')
|
||||||
<a href="{{ route('admin.owned.show', $fl) }}" class="btn--table">View</a>
|
<a href="{{ route('admin.owned.show', $fl) }}" class="btn--table">View</a>
|
||||||
@endif
|
@endif
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<a href="{{ route("admin.$class.edit", $fl) }}" class="btn--table">Edit</a>
|
<a href="{{ route("admin.$class.edit", $fl) }}" class="btn--table">Edit</a>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
<td>
|
<td>
|
||||||
<x-admin.form.destroy :object="$fl" :route="'admin.'.$class.'.destroy'"
|
<x-admin.form.destroy :object="$fl" :route="'admin.'.$class.'.destroy'" :btnClass="'btn--table'" />
|
||||||
:btnClass="'btn--table'"/>
|
</td>
|
||||||
</td>
|
</tr>
|
||||||
</tr>
|
@endforeach
|
||||||
@endforeach
|
</tbody>
|
||||||
</tbody>
|
</table>
|
||||||
</table>
|
|
||||||
|
|
||||||
{{ $fanlistings->links() }}
|
{{ $fanlistings->links() }}
|
||||||
</div>
|
</div>
|
|
@ -8,14 +8,14 @@
|
||||||
uses()->group('owned', 'admin');
|
uses()->group('owned', 'admin');
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
$this->user = Collective::first();
|
$this->user = Collective::first();
|
||||||
$this->request = [
|
$this->request = [
|
||||||
'categories' => [rand(1, 57), rand(1, 57), rand(1, 57)],
|
'categories' => [rand(1, 57), rand(1, 57), rand(1, 57)],
|
||||||
'subject' => faker()->word,
|
'subject' => faker()->word,
|
||||||
'status' => 'current',
|
'status' => 'current',
|
||||||
'slug' => faker()->slug(2),
|
'slug' => faker()->slug(2),
|
||||||
'title' => faker()->sentence(),
|
'title' => faker()->sentence(),
|
||||||
'date_opened' => faker()->dateTimeThisMonth(),
|
'opened' => faker()->dateTimeThisMonth(),
|
||||||
'hold_member_updates' => faker()->boolean(),
|
'hold_member_updates' => faker()->boolean(),
|
||||||
'notify_pending' => faker()->boolean(),
|
'notify_pending' => faker()->boolean(),
|
||||||
];
|
];
|
||||||
|
@ -48,29 +48,29 @@
|
||||||
|
|
||||||
it('fails non-array categories', function () {
|
it('fails non-array categories', function () {
|
||||||
$this->request['categories'] = 'This is not an array.';
|
$this->request['categories'] = 'This is not an array.';
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails empty categories array', function () {
|
it('fails empty categories array', function () {
|
||||||
$this->request['categories'] = [];
|
$this->request['categories'] = [];
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails non-numeric category item', function () {
|
it('fails non-numeric category item', function () {
|
||||||
$this->request['categories'][] = 'a';
|
$this->request['categories'][] = 'a';
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails non-existant category', function () {
|
it('fails non-existant category', function () {
|
||||||
$invalidCat = (Category::all()->count()) + 10;
|
$invalidCat = (Category::all()->count()) + 10;
|
||||||
$this->request['categories'][] = $invalidCat;
|
$this->request['categories'][] = $invalidCat;
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
@ -84,7 +84,7 @@
|
||||||
|
|
||||||
it('fails non-string subject', function () {
|
it('fails non-string subject', function () {
|
||||||
$this->request['subject'] = 39502;
|
$this->request['subject'] = 39502;
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
@ -98,7 +98,7 @@
|
||||||
|
|
||||||
it('fails non-valid status', function () {
|
it('fails non-valid status', function () {
|
||||||
$this->request['status'] = 'This is not a correct status.';
|
$this->request['status'] = 'This is not a correct status.';
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
@ -112,7 +112,7 @@
|
||||||
|
|
||||||
it('fails non-valid slug format', function () {
|
it('fails non-valid slug format', function () {
|
||||||
$this->request['slug'] = 'This is not a valid slug.';
|
$this->request['slug'] = 'This is not a valid slug.';
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
@ -126,21 +126,21 @@
|
||||||
|
|
||||||
it('fails non-string title', function () {
|
it('fails non-string title', function () {
|
||||||
$this->request['title'] = 494920;
|
$this->request['title'] = 494920;
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('allows null date_opened', function () {
|
it('allows null opened', function () {
|
||||||
unset($this->request['date_opened']);
|
unset($this->request['opened']);
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertValid();
|
$response->assertValid();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('fails non-date date_opened', function () {
|
it('fails non-date opened', function () {
|
||||||
$this->request['date_opened'] = 'This is not a date.';
|
$this->request['opened'] = 'This is not a date.';
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
@ -154,7 +154,7 @@
|
||||||
|
|
||||||
it('fails non-bool hold_member_updates', function () {
|
it('fails non-bool hold_member_updates', function () {
|
||||||
$this->request['holds_member_updates'] = 'This is not a boolean.';
|
$this->request['holds_member_updates'] = 'This is not a boolean.';
|
||||||
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
$response = $this->actingAs($this->user)->post('/fanatic/owned', $this->request);
|
||||||
|
|
||||||
$response->assertInvalid();
|
$response->assertInvalid();
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue