mirror of
https://github.com/HDInnovations/UNIT3D-Community-Edition.git
synced 2026-04-22 18:20:31 -05:00
Merge pull request #3519 from Roardom/add-forum-categories
(Update) Separate forum categories into their own model
This commit is contained in:
@@ -13,7 +13,8 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Forum;
|
||||
use App\Models\ForumCategory;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @see \Tests\Feature\Http\Controllers\ForumCategoryControllerTest
|
||||
@@ -23,24 +24,15 @@ class ForumCategoryController extends Controller
|
||||
/**
|
||||
* Show The Forum Category.
|
||||
*/
|
||||
public function show(int $id): \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
|
||||
public function show(Request $request, int $id): \Illuminate\Contracts\Foundation\Application|\Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Http\RedirectResponse
|
||||
{
|
||||
// Find the topic
|
||||
$forum = Forum::findOrFail($id);
|
||||
|
||||
// Check if this is a category or forum
|
||||
if ($forum->parent_id !== null) {
|
||||
return to_route('forums.show', ['id' => $forum->id]);
|
||||
}
|
||||
|
||||
// Check if the user has permission to view the forum
|
||||
if (!$forum->getPermission()?->read_topic) {
|
||||
return to_route('forums.index')
|
||||
->withErrors('You Do Not Have Access To This Category!');
|
||||
}
|
||||
|
||||
return view('forum.category_topic.index', [
|
||||
'forum' => $forum,
|
||||
'category' => ForumCategory::query()
|
||||
->whereHas('forums', fn ($query) => $query->whereRelation('permissions', [
|
||||
['read_topic', '=', 1],
|
||||
['group_id', '=', $request->user()->group_id],
|
||||
]))
|
||||
->findOrFail($id),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Forum;
|
||||
use App\Models\ForumCategory;
|
||||
use App\Models\Post;
|
||||
use App\Models\Topic;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -29,17 +30,17 @@ class ForumController extends Controller
|
||||
public function index(Request $request): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('forum.index', [
|
||||
'categories' => Forum::query()
|
||||
'categories' => ForumCategory::query()
|
||||
->with([
|
||||
'forums' => fn ($query) => $query
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', $request->user()->group_id]]),
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', $request->user()->group_id]])
|
||||
->orderBy('position'),
|
||||
'forums.latestPoster' => fn ($query) => $query->withTrashed(),
|
||||
'forums.lastRepliedTopic',
|
||||
])
|
||||
->whereNull('parent_id')
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', $request->user()->group_id]])
|
||||
->orderBy('position')
|
||||
->get(),
|
||||
->get()
|
||||
->filter(fn ($category) => $category->forums->isNotEmpty()),
|
||||
'num_posts' => Post::count(),
|
||||
'num_forums' => Forum::count(),
|
||||
'num_topics' => Topic::count(),
|
||||
@@ -49,24 +50,13 @@ class ForumController extends Controller
|
||||
/**
|
||||
* Show Forums And Topics Inside.
|
||||
*/
|
||||
public function show(int $id): \Illuminate\Contracts\View\Factory|\Illuminate\View\View|\Illuminate\Http\RedirectResponse
|
||||
public function show(Request $request, int $id): \Illuminate\Contracts\View\Factory|\Illuminate\View\View|\Illuminate\Http\RedirectResponse
|
||||
{
|
||||
// Find the topic
|
||||
$forum = Forum::findOrFail($id);
|
||||
|
||||
// Check if this is a category or forum
|
||||
if ($forum->parent_id === null) {
|
||||
return to_route('forums.categories.show', ['id' => $forum->id]);
|
||||
}
|
||||
|
||||
// Check if the user has permission to view the forum
|
||||
if (!$forum->getPermission()?->read_topic) {
|
||||
return to_route('forums.index')
|
||||
->withErrors('You Do Not Have Access To This Forum!');
|
||||
}
|
||||
|
||||
return view('forum.forum_topic.index', [
|
||||
'forum' => $forum,
|
||||
'forum' => Forum::query()
|
||||
->with('category')
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', $request->user()->group_id]])
|
||||
->findOrFail($id),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,7 @@ class PostController extends Controller
|
||||
$realUrl = sprintf('/forums/topics/%s/posts/%s', $topic->id, $post->id);
|
||||
$profileUrl = sprintf('%s/users/%s', $appUrl, $user->username);
|
||||
|
||||
if (config('other.staff-forum-notify') && ($forum->id == config('other.staff-forum-id') || $forum->parent_id == config('other.staff-forum-id'))) {
|
||||
if (config('other.staff-forum-notify') && ($forum->id == config('other.staff-forum-id') || $forum->forum_category_id == config('other.staff-forum-id'))) {
|
||||
$topic->notifyStaffers($user, $topic, $post);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(sprintf('[url=%s]%s[/url] has left a reply on topic [url=%s]%s[/url]', $profileUrl, $user->username, $postUrl, $topic->name));
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author Roardom <roardom@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Controllers\Staff;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Staff\StoreForumCategoryRequest;
|
||||
use App\Http\Requests\Staff\UpdateForumCategoryRequest;
|
||||
use App\Models\ForumCategory;
|
||||
|
||||
class ForumCategoryController extends Controller
|
||||
{
|
||||
public function index(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('Staff.forum-category.index', [
|
||||
'categories' => ForumCategory::query()
|
||||
->with(['forums' => fn ($query) => $query->orderBy('position')])
|
||||
->orderBy('position')
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('Staff.forum-category.create');
|
||||
}
|
||||
|
||||
public function store(StoreForumCategoryRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
ForumCategory::create($request->validated());
|
||||
|
||||
return to_route('staff.forum_categories.index')
|
||||
->withSuccess('Forum has been created successfully');
|
||||
}
|
||||
|
||||
public function edit(ForumCategory $forumCategory): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('Staff.forum-category.edit', [
|
||||
'forumCategory' => $forumCategory,
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpdateForumCategoryRequest $request, ForumCategory $forumCategory): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$forumCategory->update($request->validated());
|
||||
|
||||
return to_route('staff.forum_categories.index')
|
||||
->withSuccess('Forum has been edited successfully');
|
||||
}
|
||||
|
||||
public function destroy(ForumCategory $forumCategory): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$forumCategory->delete();
|
||||
|
||||
return to_route('staff.forum_categories.index')
|
||||
->withSuccess('Forum has been deleted successfully');
|
||||
}
|
||||
}
|
||||
@@ -17,37 +17,26 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Staff\StoreForumRequest;
|
||||
use App\Http\Requests\Staff\UpdateForumRequest;
|
||||
use App\Models\Forum;
|
||||
use App\Models\ForumCategory;
|
||||
use App\Models\Group;
|
||||
use App\Models\Permission;
|
||||
use Illuminate\Support\Str;
|
||||
use Exception;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* @see \Tests\Todo\Feature\Http\Controllers\Staff\ForumControllerTest
|
||||
*/
|
||||
class ForumController extends Controller
|
||||
{
|
||||
/**
|
||||
* Display All Forums.
|
||||
*/
|
||||
public function index(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('Staff.forum.index', [
|
||||
'categories' => Forum::orderBy('position')
|
||||
->whereNull('parent_id')
|
||||
->with(['forums' => fn ($query) => $query->orderBy('position')])
|
||||
->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Show Forum Create Form.
|
||||
*/
|
||||
public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
public function create(Request $request): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('Staff.forum.create', [
|
||||
'categories' => Forum::whereNull('parent_id')->get(),
|
||||
'groups' => Group::orderBy('position')->get(),
|
||||
'forumCategoryId' => $request->integer('forumCategoryId'),
|
||||
'categories' => ForumCategory::orderBy('position')->get(),
|
||||
'groups' => Group::orderBy('position')->get(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -56,45 +45,14 @@ class ForumController extends Controller
|
||||
*/
|
||||
public function store(StoreForumRequest $request): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$groups = Group::all();
|
||||
$forum = Forum::create($request->safe(['name', 'position', 'description', 'slug', 'forum_category_id']));
|
||||
|
||||
$forum = Forum::create(
|
||||
['slug' => Str::slug($request->title)]
|
||||
+ $request->safe()->only(
|
||||
[
|
||||
'name',
|
||||
'position',
|
||||
'description',
|
||||
'parent_id'
|
||||
]
|
||||
)
|
||||
Permission::upsert(
|
||||
array_map(fn ($item) => ['forum_id' => $forum->id] + $item, $request->validated('permissions')),
|
||||
['forum_id', 'group_id']
|
||||
);
|
||||
|
||||
// Permissions
|
||||
foreach ($groups as $group) {
|
||||
$perm = Permission::where('forum_id', '=', $forum->id)->where('group_id', '=', $group->id)->first();
|
||||
|
||||
if ($perm == null) {
|
||||
$perm = new Permission();
|
||||
}
|
||||
|
||||
$perm->forum_id = $forum->id;
|
||||
$perm->group_id = $group->id;
|
||||
|
||||
if (\array_key_exists($group->id, $request->input('permissions'))) {
|
||||
$perm->read_topic = isset($request->input('permissions')[$group->id]['read_topic']);
|
||||
$perm->reply_topic = isset($request->input('permissions')[$group->id]['reply_topic']);
|
||||
$perm->start_topic = isset($request->input('permissions')[$group->id]['start_topic']);
|
||||
} else {
|
||||
$perm->read_topic = false;
|
||||
$perm->reply_topic = false;
|
||||
$perm->start_topic = false;
|
||||
}
|
||||
|
||||
$perm->save();
|
||||
}
|
||||
|
||||
return to_route('staff.forums.index')
|
||||
return to_route('staff.forum_categories.index')
|
||||
->withSuccess('Forum has been created successfully');
|
||||
}
|
||||
|
||||
@@ -104,9 +62,9 @@ class ForumController extends Controller
|
||||
public function edit(Forum $forum): \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
{
|
||||
return view('Staff.forum.edit', [
|
||||
'categories' => Forum::whereNull('parent_id')->get(),
|
||||
'categories' => ForumCategory::orderBy('position')->get(),
|
||||
'groups' => Group::orderBy('position')->get(),
|
||||
'forum' => $forum->load('permissions'),
|
||||
'forum' => $forum->load(['permissions', 'category']),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -115,37 +73,14 @@ class ForumController extends Controller
|
||||
*/
|
||||
public function update(UpdateForumRequest $request, Forum $forum): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$groups = Group::all();
|
||||
$forum->update($request->safe(['name', 'position', 'description', 'slug', 'forum_category_id']));
|
||||
|
||||
$forum->update(
|
||||
[
|
||||
'slug' => Str::slug($request->title),
|
||||
'parent_id' => $request->forum_type === 'category' ? null : $request->parent_id,
|
||||
]
|
||||
+ $request->safe()->only(['name', 'position', 'description'])
|
||||
Permission::upsert(
|
||||
array_map(fn ($item) => ['forum_id' => $forum->id] + $item, $request->validated('permissions')),
|
||||
['forum_id', 'group_id']
|
||||
);
|
||||
|
||||
// Permissions
|
||||
foreach ($groups as $group) {
|
||||
$permission = Permission::whereBelongsTo($forum)->whereBelongsTo($group)->firstOrNew([
|
||||
'forum_id' => $forum->id,
|
||||
'group_id' => $group->id,
|
||||
]);
|
||||
|
||||
if (\array_key_exists($group->id, $request->input('permissions'))) {
|
||||
$permission->read_topic = isset($request->input('permissions')[$group->id]['read_topic']);
|
||||
$permission->reply_topic = isset($request->input('permissions')[$group->id]['reply_topic']);
|
||||
$permission->start_topic = isset($request->input('permissions')[$group->id]['start_topic']);
|
||||
} else {
|
||||
$permission->read_topic = false;
|
||||
$permission->reply_topic = false;
|
||||
$permission->start_topic = false;
|
||||
}
|
||||
|
||||
$permission->save();
|
||||
}
|
||||
|
||||
return to_route('staff.forums.index')
|
||||
return to_route('staff.forum_categories.index')
|
||||
->withSuccess('Forum has been edited successfully');
|
||||
}
|
||||
|
||||
@@ -156,26 +91,9 @@ class ForumController extends Controller
|
||||
*/
|
||||
public function destroy(Forum $forum): \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
$forum->permissions()->delete();
|
||||
$forum->delete();
|
||||
|
||||
if ($forum->parent_id === null) {
|
||||
$category = $forum;
|
||||
|
||||
foreach ($category->forums as $forum) {
|
||||
$forum->permissions()->delete();
|
||||
$forum->posts()->delete();
|
||||
$forum->topics()->delete();
|
||||
$forum->delete();
|
||||
}
|
||||
|
||||
$category->delete();
|
||||
} else {
|
||||
$forum->posts()->delete();
|
||||
$forum->topics()->delete();
|
||||
$forum->delete();
|
||||
}
|
||||
|
||||
return to_route('staff.forums.index')
|
||||
return to_route('staff.forum_categories.index')
|
||||
->withSuccess('Forum has been deleted successfully');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,15 +60,13 @@ class TopicController extends Controller
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$topic = Topic::with('user')
|
||||
$topic = Topic::with('user', 'forum.category')
|
||||
->whereRelation('forumPermissions', [
|
||||
['read_topic', '=', 1],
|
||||
['group_id', '=', $user->group_id],
|
||||
])
|
||||
->findOrFail($id);
|
||||
|
||||
$forum = $topic->forum->load('category');
|
||||
|
||||
$subscription = Subscription::where('user_id', '=', $user->id)->where('topic_id', '=', $id)->first();
|
||||
|
||||
$topic->views++;
|
||||
@@ -76,7 +74,6 @@ class TopicController extends Controller
|
||||
|
||||
return view('forum.topic.show', [
|
||||
'topic' => $topic,
|
||||
'forum' => $forum,
|
||||
'subscription' => $subscription,
|
||||
]);
|
||||
}
|
||||
@@ -153,7 +150,7 @@ class TopicController extends Controller
|
||||
$topicUrl = sprintf('%s/forums/topics/%s', $appUrl, $topic->id);
|
||||
$profileUrl = sprintf('%s/users/%s', $appUrl, $user->username);
|
||||
|
||||
if (config('other.staff-forum-notify') && ($forum->id == config('other.staff-forum-id') || $forum->parent_id == config('other.staff-forum-id'))) {
|
||||
if (config('other.staff-forum-notify') && ($forum->id == config('other.staff-forum-id') || $forum->forum_category_id == config('other.staff-forum-id'))) {
|
||||
$forum->notifyStaffers($user, $topic);
|
||||
} else {
|
||||
$this->chatRepository->systemMessage(sprintf('[url=%s]%s[/url] has created a new topic [url=%s]%s[/url]', $profileUrl, $user->username, $topicUrl, $topic->name));
|
||||
@@ -195,16 +192,14 @@ class TopicController extends Controller
|
||||
|
||||
abort_unless($user->group->is_modo || $user->id === $topic->first_post_user_id, 403);
|
||||
|
||||
$categories = Forum::whereRelation('permissions', [
|
||||
['start_topic', '=', 1],
|
||||
])
|
||||
->whereNull('parent_id')
|
||||
->with([
|
||||
'forums' => fn ($query) => $query->whereRelation('permissions', [
|
||||
['start_topic', '=', 1],
|
||||
])
|
||||
$categories = Forum::with('category:id,name')
|
||||
->whereRelation('permissions', [
|
||||
['read_topic', '=', 1],
|
||||
['start_topic', '=', 1],
|
||||
['group_id', '=', $request->user()->group_id],
|
||||
])
|
||||
->get();
|
||||
->get()
|
||||
->groupBy('category.name');
|
||||
|
||||
return view('forum.topic.edit', [
|
||||
'topic' => $topic,
|
||||
@@ -225,6 +220,10 @@ class TopicController extends Controller
|
||||
]);
|
||||
|
||||
$topic = Topic::query()
|
||||
->whereRelation('forumPermissions', [
|
||||
['read_topic', '=', 1],
|
||||
['group_id', '=', $user->group_id],
|
||||
])
|
||||
->when(!$user->group->is_modo, fn ($query) => $query->where('state', '=', 'open'))
|
||||
->findOrFail($id);
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Forum;
|
||||
use App\Models\ForumCategory;
|
||||
use App\Models\Topic;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
@@ -28,7 +29,7 @@ class ForumCategoryTopicSearch extends Component
|
||||
public string $label = '';
|
||||
public string $state = '';
|
||||
public string $subscribed = '';
|
||||
public Forum $category;
|
||||
public ForumCategory $category;
|
||||
|
||||
/**
|
||||
* @var array<mixed>
|
||||
@@ -42,7 +43,7 @@ class ForumCategoryTopicSearch extends Component
|
||||
'subscribed' => ['except' => ''],
|
||||
];
|
||||
|
||||
final public function mount(Forum $category): void
|
||||
final public function mount(ForumCategory $category): void
|
||||
{
|
||||
$this->category = $category;
|
||||
}
|
||||
@@ -64,8 +65,8 @@ class ForumCategoryTopicSearch extends Component
|
||||
{
|
||||
return Topic::query()
|
||||
->select('topics.*')
|
||||
->with('user', 'user.group', 'latestPoster')
|
||||
->whereIn('forum_id', Forum::where('parent_id', '=', $this->category->id)->select('id'))
|
||||
->with('user', 'user.group', 'latestPoster', 'forum')
|
||||
->whereIn('forum_id', Forum::where('forum_category_id', '=', $this->category->id)->select('id'))
|
||||
->whereRelation('forumPermissions', [['read_topic', '=', 1], ['group_id', '=', auth()->user()->group_id]])
|
||||
->when($this->search !== '', fn ($query) => $query->where('name', 'LIKE', '%'.$this->search.'%'))
|
||||
->when($this->label !== '', fn ($query) => $query->where($this->label, '=', 1))
|
||||
|
||||
@@ -28,7 +28,6 @@ class SubscribedForum extends Component
|
||||
{
|
||||
return Forum::query()
|
||||
->with('latestPoster', 'lastRepliedTopic')
|
||||
->whereNotNull('parent_id')
|
||||
->whereRelation('subscribedUsers', 'users.id', '=', auth()->id())
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', auth()->user()->group_id]])
|
||||
->orderBy('position')
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Forum;
|
||||
use App\Models\ForumCategory;
|
||||
use App\Models\Topic;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
@@ -28,7 +28,7 @@ class TopicSearch extends Component
|
||||
public string $label = '';
|
||||
public string $state = '';
|
||||
public string $subscribed = '';
|
||||
public String $forumId = '';
|
||||
public string $forumId = '';
|
||||
|
||||
/**
|
||||
* @var array<mixed>
|
||||
@@ -54,18 +54,17 @@ class TopicSearch extends Component
|
||||
}
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Support\Collection<int, Forum>
|
||||
* @return \Illuminate\Database\Eloquent\Collection<int, ForumCategory>
|
||||
*/
|
||||
final public function getForumCategoriesProperty(): \Illuminate\Support\Collection
|
||||
final public function getForumCategoriesProperty(): \Illuminate\Database\Eloquent\Collection
|
||||
{
|
||||
return Forum::query()
|
||||
return ForumCategory::query()
|
||||
->with(['forums' => fn ($query) => $query
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', auth()->user()->group_id]])
|
||||
])
|
||||
->whereNull('parent_id')
|
||||
->whereRelation('permissions', [['read_topic', '=', 1], ['group_id', '=', auth()->user()->group_id]])
|
||||
->orderBy('position')
|
||||
->get();
|
||||
->get()
|
||||
->filter(fn ($category) => $category->forums->isNotEmpty());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,11 +89,7 @@ class TopicSearch extends Component
|
||||
fn ($query) => $query
|
||||
->whereDoesntHave('subscribedUsers', fn ($query) => $query->where('users.id', '=', auth()->id()))
|
||||
)
|
||||
->when($this->forumId !== '', fn ($query) => $query->where(
|
||||
fn ($query) => $query
|
||||
->where('forum_id', '=', $this->forumId)
|
||||
->orWhereIn('forum_id', Forum::where('parent_id', '=', $this->forumId)->select('id'))
|
||||
))
|
||||
->when($this->forumId !== '', fn ($query) => $query->where('forum_id', '=', $this->forumId))
|
||||
->orderBy($this->sortField, $this->sortDirection)
|
||||
->paginate(25);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author Roardom <roardom@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Staff;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StoreForumCategoryRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\Rule|array<\Illuminate\Contracts\Validation\Rule|string>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => [
|
||||
'required',
|
||||
],
|
||||
'slug' => [
|
||||
'required',
|
||||
],
|
||||
'position' => [
|
||||
'required',
|
||||
],
|
||||
'description' => [
|
||||
'required',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'slug' => Str::slug($this->name),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,8 @@
|
||||
namespace App\Http\Requests\Staff;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class StoreForumRequest extends FormRequest
|
||||
{
|
||||
@@ -39,34 +41,50 @@ class StoreForumRequest extends FormRequest
|
||||
'position' => [
|
||||
'required',
|
||||
],
|
||||
'slug' => [
|
||||
'required',
|
||||
],
|
||||
'description' => [
|
||||
'required',
|
||||
],
|
||||
'parent_id' => [
|
||||
'sometimes',
|
||||
'nullable',
|
||||
'integer',
|
||||
'forum_category_id' => [
|
||||
'required',
|
||||
'exists:forum_categories,id',
|
||||
],
|
||||
'permissions' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'array',
|
||||
],
|
||||
'permissions.*' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'array:group_id,read_topic,reply_topic,start_topic',
|
||||
],
|
||||
'permissions.*.group_id' => [
|
||||
'required',
|
||||
'exists:groups,id',
|
||||
],
|
||||
'permissions.*.read_topic' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.reply_topic' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.start_topic' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'slug' => Str::slug($this->name),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author Roardom <roardom@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Http\Requests\Staff;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UpdateForumCategoryRequest extends FormRequest
|
||||
{
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\Rule|array<\Illuminate\Contracts\Validation\Rule|string>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => [
|
||||
'required',
|
||||
],
|
||||
'slug' => [
|
||||
'required',
|
||||
],
|
||||
'position' => [
|
||||
'required',
|
||||
],
|
||||
'description' => [
|
||||
'required',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'slug' => Str::slug($this->name),
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@
|
||||
namespace App\Http\Requests\Staff;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class UpdateForumRequest extends FormRequest
|
||||
{
|
||||
@@ -39,32 +40,50 @@ class UpdateForumRequest extends FormRequest
|
||||
'position' => [
|
||||
'required',
|
||||
],
|
||||
'slug' => [
|
||||
'required',
|
||||
],
|
||||
'description' => [
|
||||
'required',
|
||||
],
|
||||
'parent_id' => [
|
||||
'sometimes',
|
||||
'nullable',
|
||||
'integer',
|
||||
'forum_category_id' => [
|
||||
'required',
|
||||
'exists:forum_categories,id',
|
||||
],
|
||||
'permissions' => [
|
||||
'required',
|
||||
'array',
|
||||
],
|
||||
'permissions.*' => [
|
||||
'required',
|
||||
'array:group_id,read_topic,reply_topic,start_topic',
|
||||
],
|
||||
'permissions.*.group_id' => [
|
||||
'required',
|
||||
'exists:groups,id',
|
||||
],
|
||||
'permissions.*.read_topic' => [
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.reply_topic' => [
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.start_topic' => [
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'forum_type' => [
|
||||
'in:category,forum',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare the data for validation.
|
||||
*/
|
||||
protected function prepareForValidation(): void
|
||||
{
|
||||
$this->merge([
|
||||
'slug' => Str::slug($this->name),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
+9
-30
@@ -32,7 +32,7 @@ use Illuminate\Database\Eloquent\Model;
|
||||
* @property string|null $name
|
||||
* @property string|null $slug
|
||||
* @property string|null $description
|
||||
* @property int|null $parent_id
|
||||
* @property int $forum_category_id
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
*/
|
||||
@@ -58,36 +58,14 @@ class Forum extends Model
|
||||
return $this->hasMany(Topic::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Sub Topics.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany<Topic>
|
||||
*/
|
||||
public function sub_topics(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
$children = $this->forums->pluck('id')->toArray();
|
||||
|
||||
return $this->hasMany(Topic::class)->orWhereIn('topics.forum_id', $children);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Sub Forums.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany<self>
|
||||
*/
|
||||
public function forums(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_id', 'id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns The Category In Which The Forum Is Located.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasOne<self>
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo<ForumCategory, self>
|
||||
*/
|
||||
public function category(): \Illuminate\Database\Eloquent\Relations\HasOne
|
||||
public function category(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->hasOne(self::class, 'id', 'parent_id');
|
||||
return $this->belongsTo(ForumCategory::class, 'forum_category_id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,7 +95,7 @@ class Forum extends Model
|
||||
*/
|
||||
public function lastRepliedTopic(): \Illuminate\Database\Eloquent\Relations\BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Topic::class, 'last_post_topic_id');
|
||||
return $this->belongsTo(Topic::class, 'last_topic_id');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -200,8 +178,9 @@ class Forum extends Model
|
||||
*/
|
||||
public function getPermission(): ?Permission
|
||||
{
|
||||
$group = auth()->check() ? auth()->user()->group : Group::where('slug', 'guest')->first();
|
||||
|
||||
return $group->permissions->where('forum_id', $this->id)->first();
|
||||
return Permission::query()
|
||||
->where('group_id', '=', auth()->user()->group_id)
|
||||
->where('forum_id', '=', $this->id)
|
||||
->first();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author Roardom <roardom@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Traits\Auditable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* App\Models\Forum.
|
||||
*
|
||||
* @property int $id
|
||||
* @property int|null $position
|
||||
* @property string $name
|
||||
* @property string $slug
|
||||
* @property string $description
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property \Illuminate\Support\Carbon|null $updated_at
|
||||
*/
|
||||
class ForumCategory extends Model
|
||||
{
|
||||
use Auditable;
|
||||
use HasFactory;
|
||||
|
||||
/**
|
||||
* The attributes that aren't mass assignable.
|
||||
*
|
||||
* @var string[]
|
||||
*/
|
||||
protected $guarded = ['id', 'created_at'];
|
||||
|
||||
/**
|
||||
* Has Many Sub Topics.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough<Topic>
|
||||
*/
|
||||
public function topics(): \Illuminate\Database\Eloquent\Relations\HasManyThrough
|
||||
{
|
||||
return $this->hasManyThrough(Topic::class, Forum::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Has Many Sub Forums.
|
||||
*
|
||||
* @return \Illuminate\Database\Eloquent\Relations\HasMany<Forum>
|
||||
*/
|
||||
public function forums(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Forum::class);
|
||||
}
|
||||
}
|
||||
+20
-3
@@ -22,9 +22,26 @@ return [
|
||||
*/
|
||||
|
||||
'global_discards' => [
|
||||
'password', 'passkey', 'rsskey', 'ip', 'remember_token',
|
||||
'views', 'num_post', 'read', 'nfo',
|
||||
'last_post_created_at', 'last_action', 'created_at', 'updated_at', 'deleted_at',
|
||||
'password',
|
||||
'passkey',
|
||||
'rsskey',
|
||||
'ip',
|
||||
'remember_token',
|
||||
'views',
|
||||
'num_post',
|
||||
'num_topic',
|
||||
'read',
|
||||
'nfo',
|
||||
'last_post_id',
|
||||
'last_topic_id',
|
||||
'first_post_user_id',
|
||||
'last_post_id',
|
||||
'last_post_user_id',
|
||||
'last_post_created_at',
|
||||
'last_action',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at',
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php
|
||||
/**
|
||||
* NOTICE OF LICENSE.
|
||||
*
|
||||
* UNIT3D Community Edition is open-sourced software licensed under the GNU Affero General Public License v3.0
|
||||
* The details is bundled with this project in the file LICENSE.txt.
|
||||
*
|
||||
* @project UNIT3D Community Edition
|
||||
*
|
||||
* @author Roardom <roardom@protonmail.com>
|
||||
* @license https://www.gnu.org/licenses/agpl-3.0.en.html/ GNU Affero General Public License v3.0
|
||||
*/
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\ForumCategory;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
|
||||
/** @extends Factory<ForumCategory> */
|
||||
class ForumCategoryFactory extends Factory
|
||||
{
|
||||
/**
|
||||
* The name of the factory's corresponding model.
|
||||
*/
|
||||
protected $model = ForumCategory::class;
|
||||
|
||||
/**
|
||||
* Define the model's default state.
|
||||
*/
|
||||
public function definition(): array
|
||||
{
|
||||
return [
|
||||
'position' => $this->faker->numberBetween(0, 65535),
|
||||
'name' => $this->faker->name(),
|
||||
'slug' => $this->faker->slug(),
|
||||
'description' => $this->faker->text(),
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
namespace Database\Factories;
|
||||
|
||||
use App\Models\ForumCategory;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\Forum;
|
||||
|
||||
@@ -40,7 +41,7 @@ class ForumFactory extends Factory
|
||||
'name' => $this->faker->name(),
|
||||
'slug' => $this->faker->slug(),
|
||||
'description' => $this->faker->text(),
|
||||
'parent_id' => $this->faker->randomDigitNotNull(),
|
||||
'forum_category_id' => ForumCategory::factory(),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class () extends Migration {
|
||||
public function up(): void
|
||||
{
|
||||
Schema::create('forum_categories', function (Blueprint $table): void {
|
||||
$table->smallIncrements('id');
|
||||
$table->unsignedSmallInteger('position');
|
||||
$table->string('slug');
|
||||
$table->string('name');
|
||||
$table->string('description');
|
||||
|
||||
$table->timestamps();
|
||||
});
|
||||
|
||||
DB::table('forum_categories')->insertUsing(
|
||||
[
|
||||
'id',
|
||||
'position',
|
||||
'slug',
|
||||
'name',
|
||||
'description',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
],
|
||||
DB::table('forums')->select([
|
||||
'id',
|
||||
DB::raw("COALESCE(position, 0) as position"),
|
||||
DB::raw("COALESCE(slug, '') as slug"),
|
||||
DB::raw("COALESCE(name, '') as name"),
|
||||
DB::raw("COALESCE(description, '') as description"),
|
||||
'created_at',
|
||||
'updated_at',
|
||||
])
|
||||
->whereNull('parent_id')
|
||||
);
|
||||
|
||||
Schema::table('forums', function (Blueprint $table): void {
|
||||
$table->dropForeign(['parent_id']);
|
||||
$table->renameColumn('parent_id', 'forum_category_id');
|
||||
});
|
||||
|
||||
DB::table('forums')
|
||||
->whereNull('forum_category_id')
|
||||
->delete();
|
||||
|
||||
Schema::table('forums', function (Blueprint $table): void {
|
||||
$table->unsignedSmallInteger('forum_category_id')->nullable(false)->change();
|
||||
|
||||
$table->foreign('forum_category_id')->references('id')->on('forum_categories')->cascadeOnUpdate()->cascadeOnDelete();
|
||||
});
|
||||
|
||||
// Remove existing duplicates
|
||||
DB::table('permissions as p1')
|
||||
->join('permissions as p2', function ($join): void {
|
||||
$join->on('p1.id', '<', 'p2.id')
|
||||
->whereColumn('p1.group_id', '=', 'p2.group_id')
|
||||
->whereColumn('p1.forum_id', '=', 'p2.forum_id');
|
||||
})
|
||||
->delete();
|
||||
|
||||
Schema::table('permissions', function (Blueprint $table): void {
|
||||
$table->unique(['group_id', 'forum_id']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -14,29 +14,26 @@
|
||||
namespace Database\Seeders;
|
||||
|
||||
use App\Models\Forum;
|
||||
use App\Models\ForumCategory;
|
||||
use Illuminate\Database\Seeder;
|
||||
|
||||
class ForumsTableSeeder extends Seeder
|
||||
{
|
||||
public function run(): void
|
||||
{
|
||||
Forum::upsert([
|
||||
ForumCategory::upsert([
|
||||
[
|
||||
'id' => 1,
|
||||
'position' => 1,
|
||||
'num_topic' => null,
|
||||
'num_post' => null,
|
||||
'last_topic_id' => null,
|
||||
'last_post_id' => null,
|
||||
'last_post_user_id' => null,
|
||||
'last_post_created_at' => null,
|
||||
'name' => 'UNIT3D Forums',
|
||||
'slug' => 'unit3d-forums',
|
||||
'description' => 'UNIT3D Forums',
|
||||
'parent_id' => null,
|
||||
'created_at' => '2017-01-03 18:29:21',
|
||||
'updated_at' => '2017-01-03 18:29:21',
|
||||
'id' => 1,
|
||||
'position' => 1,
|
||||
'name' => 'UNIT3D Forums',
|
||||
'slug' => 'unit3d-forums',
|
||||
'description' => 'UNIT3D Forums',
|
||||
'created_at' => '2017-01-03 18:29:21',
|
||||
'updated_at' => '2017-01-03 18:29:21',
|
||||
],
|
||||
], ['id']);
|
||||
|
||||
Forum::upsert([
|
||||
[
|
||||
'id' => 2,
|
||||
'position' => 2,
|
||||
@@ -49,7 +46,7 @@ class ForumsTableSeeder extends Seeder
|
||||
'name' => 'Welcome',
|
||||
'slug' => 'welcome',
|
||||
'description' => 'Introduce Yourself Here!',
|
||||
'parent_id' => 1,
|
||||
'forum_category_id' => 1,
|
||||
'created_at' => '2017-04-01 20:16:06',
|
||||
'updated_at' => '2017-12-27 18:19:07',
|
||||
],
|
||||
|
||||
@@ -800,36 +800,6 @@ parameters:
|
||||
count: 1
|
||||
path: app/Http/Controllers/Staff/FlushController.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Permission\\:\\:\\$read_topic \\(int\\) does not accept bool\\.$#"
|
||||
count: 2
|
||||
path: app/Http/Controllers/Staff/ForumController.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Permission\\:\\:\\$read_topic \\(int\\) does not accept false\\.$#"
|
||||
count: 2
|
||||
path: app/Http/Controllers/Staff/ForumController.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Permission\\:\\:\\$reply_topic \\(int\\) does not accept bool\\.$#"
|
||||
count: 2
|
||||
path: app/Http/Controllers/Staff/ForumController.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Permission\\:\\:\\$reply_topic \\(int\\) does not accept false\\.$#"
|
||||
count: 2
|
||||
path: app/Http/Controllers/Staff/ForumController.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Permission\\:\\:\\$start_topic \\(int\\) does not accept bool\\.$#"
|
||||
count: 2
|
||||
path: app/Http/Controllers/Staff/ForumController.php
|
||||
|
||||
-
|
||||
message: "#^Property App\\\\Models\\\\Permission\\:\\:\\$start_topic \\(int\\) does not accept false\\.$#"
|
||||
count: 2
|
||||
path: app/Http/Controllers/Staff/ForumController.php
|
||||
|
||||
-
|
||||
message: "#^Parameter \\#1 \\$boolean of function abort_if expects bool, int given\\.$#"
|
||||
count: 3
|
||||
|
||||
@@ -151,7 +151,7 @@
|
||||
<p class="form__group form__group--horizontal">
|
||||
<a
|
||||
class="form__button form__button--text"
|
||||
href="{{ route('staff.forums.index') }}"
|
||||
href="{{ route('staff.forum_categories.index') }}"
|
||||
>
|
||||
<i class="fab fa-wpforms"></i>
|
||||
{{ __('staff.forums') }}
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('title')
|
||||
<title>Add Forums - {{ __('staff.staff-dashboard') }} - {{ config('other.title') }}</title>
|
||||
@endsection
|
||||
|
||||
@section('meta')
|
||||
<meta name="description" content="Add Forums - {{ __('staff.staff-dashboard') }}" />
|
||||
@endsection
|
||||
|
||||
@section('breadcrumbs')
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.dashboard.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.staff-dashboard') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.forum_categories.index') }}" class="breadcrumb__link">
|
||||
Forum Categories
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
{{ __('common.new-adj') }}
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@section('page', 'page__forum-category-admin--create')
|
||||
|
||||
@section('main')
|
||||
<section class="panelV2">
|
||||
<h2 class="panel__heading">Add a new Forum Category</h2>
|
||||
<div class="panel__body">
|
||||
<form class="form" method="POST" action="{{ route('staff.forum_categories.store') }}">
|
||||
@csrf
|
||||
<p class="form__group">
|
||||
<input id="name" class="form__text" type="text" name="name" required />
|
||||
<label class="form__label form__label--floating" for="name">Title</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<input
|
||||
id="position"
|
||||
class="form__text"
|
||||
inputmode="numeric"
|
||||
name="position"
|
||||
pattern="[0-9]*"
|
||||
required
|
||||
type="text"
|
||||
/>
|
||||
<label class="form__label form__label--floating" for="position">
|
||||
{{ __('common.position') }}
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<textarea
|
||||
id="description"
|
||||
class="form__textarea"
|
||||
name="description"
|
||||
required
|
||||
></textarea>
|
||||
<label class="form__label form__label--floating" for="description">
|
||||
Description
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<button class="form__button form__button--filled">Save Forum</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
@@ -0,0 +1,90 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('title')
|
||||
<title>
|
||||
{{ __('common.edit') }} Forums - {{ __('staff.staff-dashboard') }} -
|
||||
{{ config('other.title') }}
|
||||
</title>
|
||||
@endsection
|
||||
|
||||
@section('meta')
|
||||
<meta
|
||||
name="description"
|
||||
content="{{ __('common.edit') }} Forums - {{ __('staff.staff-dashboard') }}"
|
||||
/>
|
||||
@endsection
|
||||
|
||||
@section('breadcrumbs')
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.dashboard.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.staff-dashboard') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.forum_categories.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.forums') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
{{ $forumCategory->name }}
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
{{ __('common.edit') }}
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@section('page', 'page__forums-admin--edit')
|
||||
|
||||
@section('main')
|
||||
<section class="panelV2">
|
||||
<h2 class="panel__heading">{{ __('common.edit') }} {{ __('forum.forum') }}</h2>
|
||||
<div class="panel__body">
|
||||
<form
|
||||
class="form"
|
||||
method="POST"
|
||||
action="{{ route('staff.forum_categories.update', ['forumCategory' => $forumCategory]) }}"
|
||||
>
|
||||
@csrf
|
||||
@method('PATCH')
|
||||
<p class="form__group">
|
||||
<input
|
||||
id="name"
|
||||
class="form__text"
|
||||
type="text"
|
||||
name="name"
|
||||
required
|
||||
value="{{ $forumCategory->name }}"
|
||||
/>
|
||||
<label class="form__label form__label--floating" for="name">Title</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<input
|
||||
id="position"
|
||||
class="form__text"
|
||||
inputmode="numeric"
|
||||
name="position"
|
||||
pattern="[0-9]*"
|
||||
placeholder=" "
|
||||
type="text"
|
||||
value="{{ $forumCategory->position }}"
|
||||
required
|
||||
/>
|
||||
<label class="form__label form__label--floating" for="position">
|
||||
{{ __('common.position') }}
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<textarea id="description" name="description" class="form__textarea" required>
|
||||
{{ $forumCategory->description }}</textarea
|
||||
>
|
||||
<label class="form__label form__label--floating" for="description">
|
||||
Description
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<button class="form__button form__button--filled">Save Forum</button>
|
||||
</p>
|
||||
</form>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
@@ -0,0 +1,144 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('title')
|
||||
<title>Forums - {{ __('staff.staff-dashboard') }} - {{ config('other.title') }}</title>
|
||||
@endsection
|
||||
|
||||
@section('meta')
|
||||
<meta name="description" content="Forums - {{ __('staff.staff-dashboard') }}" />
|
||||
@endsection
|
||||
|
||||
@section('breadcrumbs')
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.dashboard.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.staff-dashboard') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
{{ __('staff.forums') }}
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@section('page', 'page__forums-admin--index')
|
||||
|
||||
@section('main')
|
||||
@foreach ($categories as $category)
|
||||
<section class="panelV2">
|
||||
<header class="panel__header">
|
||||
<h2 class="panel__heading">{{ $category->name }}</h2>
|
||||
<div class="panel__actions">
|
||||
<div class="panel__action">
|
||||
<a
|
||||
href="{{ route('staff.forums.create', ['forumCategoryId' => $category->id]) }}"
|
||||
class="form__button form__button--text"
|
||||
>
|
||||
{{ __('common.add') }}
|
||||
</a>
|
||||
</div>
|
||||
<div class="panel__action">
|
||||
<a
|
||||
href="{{ route('staff.forum_categories.edit', ['forumCategory' => $category]) }}"
|
||||
class="form__button form__button--text"
|
||||
>
|
||||
{{ __('common.edit') }}
|
||||
</a>
|
||||
</div>
|
||||
<form
|
||||
action="{{ route('staff.forum_categories.destroy', ['forumCategory' => $category]) }}"
|
||||
method="POST"
|
||||
style="display: contents"
|
||||
x-data="confirmation"
|
||||
>
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button
|
||||
class="form__button form__button--text"
|
||||
x-on:click.prevent="confirmAction"
|
||||
data-b64-deletion-message="{{ base64_encode('Are you sure you want to delete this forum category (' . $category->name . ') and all forums, topics, and posts within?') }}"
|
||||
>
|
||||
{{ __('common.delete') }}
|
||||
</button>
|
||||
</form>
|
||||
</div>
|
||||
</header>
|
||||
<div class="data-table-wrapper">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('common.position') }}</th>
|
||||
<th>{{ __('common.name') }}</th>
|
||||
<th>{{ __('common.action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($category->forums as $forum)
|
||||
<tr>
|
||||
<td>{{ $forum->position }}</td>
|
||||
<td>
|
||||
<a
|
||||
href="{{ route('staff.forums.edit', ['forum' => $forum]) }}"
|
||||
>
|
||||
{{ $forum->name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<menu class="data-table__actions">
|
||||
<li class="data-table__action">
|
||||
<a
|
||||
class="form__button form__button--text"
|
||||
href="{{ route('staff.forums.edit', ['forum' => $forum]) }}"
|
||||
>
|
||||
{{ __('common.edit') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="data-table__action">
|
||||
<form
|
||||
method="POST"
|
||||
action="{{ route('staff.forums.destroy', ['forum' => $forum]) }}"
|
||||
x-data="confirmation"
|
||||
>
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button
|
||||
x-on:click.prevent="confirmAction"
|
||||
data-b64-deletion-message="{{ base64_encode('Are you sure you want to delete this forum (' . $forum->name . ') including all topics and posts within?') }}"
|
||||
class="form__button form__button--text"
|
||||
>
|
||||
{{ __('common.delete') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</menu>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
@endforeach
|
||||
@endsection
|
||||
|
||||
@section('sidebar')
|
||||
<section class="panelV2">
|
||||
<h2 class="panel__heading">{{ __('common.actions') }}</h2>
|
||||
<div class="panel__body">
|
||||
<p class="form__group form__group--horizontal">
|
||||
<a
|
||||
href="{{ route('staff.forum_categories.create') }}"
|
||||
class="form__button form__button--filled form__button--centered"
|
||||
>
|
||||
Create new category
|
||||
</a>
|
||||
</p>
|
||||
<p class="form__group form__group--horizontal">
|
||||
<a
|
||||
href="{{ route('staff.forums.create') }}"
|
||||
class="form__button form__button--filled form__button--centered"
|
||||
>
|
||||
Create new forum
|
||||
</a>
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
@@ -15,13 +15,11 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.forums.index') }}" class="breadcrumb__link">
|
||||
<a href="{{ route('staff.forum_categories.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.forums') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
{{ __('common.new-adj') }}
|
||||
</li>
|
||||
<li class="breadcrumb--active">{{ __('common.new-adj') }}</li>
|
||||
@endsection
|
||||
|
||||
@section('page', 'page__forums-admin--create')
|
||||
@@ -32,43 +30,10 @@
|
||||
<div class="panel__body">
|
||||
<form class="form" method="POST" action="{{ route('staff.forums.store') }}">
|
||||
@csrf
|
||||
<p class="form__group">
|
||||
<select id="forum_type" class="form__select" name="forum_type" required>
|
||||
<option class="form__option" value="category">Category</option>
|
||||
<option class="form__option" value="forum">Forum</option>
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="forum_type">
|
||||
Forum Type
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<input id="name" class="form__text" type="text" name="name" required />
|
||||
<label class="form__label form__label--floating" for="name">Title</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<textarea
|
||||
id="description"
|
||||
class="form__textarea"
|
||||
name="description"
|
||||
placeholder=" "
|
||||
></textarea>
|
||||
<label class="form__label form__label--floating" for="description">
|
||||
Description
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<select id="parent_id" class="form__select" name="parent_id">
|
||||
<option value="">New Category</option>
|
||||
@foreach ($categories as $category)
|
||||
<option class="form__option" value="{{ $category->id }}">
|
||||
New Forum In {{ $category->name }} Category
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="parent_id">
|
||||
Parent forum
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<input
|
||||
id="position"
|
||||
@@ -76,13 +41,48 @@
|
||||
inputmode="numeric"
|
||||
name="position"
|
||||
pattern="[0-9]*"
|
||||
placeholder=" "
|
||||
required
|
||||
type="text"
|
||||
/>
|
||||
<label class="form__label form__label--floating" for="position">
|
||||
{{ __('common.position') }}
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<textarea
|
||||
id="description"
|
||||
class="form__textarea"
|
||||
name="description"
|
||||
required
|
||||
></textarea>
|
||||
<label class="form__label form__label--floating" for="description">
|
||||
Description
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<select
|
||||
id="forum_category_id"
|
||||
name="forum_category_id"
|
||||
class="form__select"
|
||||
x-data="{ selected: {{ $forumCategoryId }} || '' }"
|
||||
x-model="selected"
|
||||
x-bind:class="selected === '' ? 'form__selected--default' : ''"
|
||||
required
|
||||
>
|
||||
<option disabled hidden></option>
|
||||
@foreach ($categories as $category)
|
||||
<option
|
||||
value="{{ $category->id }}"
|
||||
@selected($category->id === $forumCategoryId)
|
||||
>
|
||||
{{ $category->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="forum_category_id">
|
||||
Forum Category
|
||||
</label>
|
||||
</p>
|
||||
<div class="form__group">
|
||||
<h3>Permissions</h3>
|
||||
<div class="data-table-wrapper" x-data="checkboxGrid">
|
||||
@@ -98,36 +98,52 @@
|
||||
<tbody>
|
||||
@foreach ($groups as $group)
|
||||
<tr>
|
||||
<th x-bind="rowHeader">{{ $group->name }}</th>
|
||||
<th x-bind="rowHeader">
|
||||
{{ $group->name }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][group_id]"
|
||||
value="{{ $group->id }}"
|
||||
/>
|
||||
</th>
|
||||
<td>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $group->id }}][read_topic]"
|
||||
value="1"
|
||||
checked
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][read_topic]"
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $loop->index }}][read_topic]"
|
||||
value="1"
|
||||
checked
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $group->id }}][start_topic]"
|
||||
value="1"
|
||||
checked
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][start_topic]"
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $loop->index }}][start_topic]"
|
||||
value="1"
|
||||
checked
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<label>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $group->id }}][reply_topic]"
|
||||
value="1"
|
||||
checked
|
||||
/>
|
||||
</label>
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][reply_topic]"
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $loop->index }}][reply_topic]"
|
||||
value="1"
|
||||
checked
|
||||
/>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
|
||||
@@ -21,7 +21,15 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.forums.index') }}" class="breadcrumb__link">
|
||||
<a href="{{ route('staff.forum_categories.index') }}" class="breadcrumb__link">
|
||||
Forum Categories
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
{{ $forum->category->name }}
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.forum_categories.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.forums') }}
|
||||
</a>
|
||||
</li>
|
||||
@@ -53,47 +61,10 @@
|
||||
type="text"
|
||||
name="name"
|
||||
value="{{ $forum->name }}"
|
||||
required
|
||||
/>
|
||||
<label class="form__label form__label--floating" for="name">Title</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<textarea id="description" name="description" class="form__textarea">
|
||||
{{ $forum->description }}</textarea
|
||||
>
|
||||
<label class="form__label form__label--floating" for="description">
|
||||
Description
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<select id="forum_type" name="forum_type" class="form__select">
|
||||
@if ($forum->category == null)
|
||||
<option value="category" selected>Category (Current)</option>
|
||||
<option value="forum">Forum</option>
|
||||
@else
|
||||
<option value="category">Category</option>
|
||||
<option value="forum" selected>Forum (Current)</option>
|
||||
@endif
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="forum_type">
|
||||
Forum Type
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<select id="parent_id" name="parent_id" class="form__select">
|
||||
@if ($forum->category != null)
|
||||
<option value="{{ $forum->parent_id }}" selected>
|
||||
{{ $forum->category->name }} (Current)
|
||||
</option>
|
||||
@endif
|
||||
|
||||
@foreach ($categories as $category)
|
||||
<option value="{{ $category->id }}">{{ $category->name }}</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="parent_id">
|
||||
Parent forum
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<input
|
||||
id="position"
|
||||
@@ -110,6 +81,29 @@
|
||||
{{ __('common.position') }}
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<textarea id="description" name="description" class="form__textarea" required>
|
||||
{{ $forum->description }}</textarea
|
||||
>
|
||||
<label class="form__label form__label--floating" for="description">
|
||||
Description
|
||||
</label>
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<select id="forum_category_id" name="forum_category_id" class="form__select">
|
||||
@foreach ($categories as $category)
|
||||
<option
|
||||
value="{{ $category->id }}"
|
||||
@selected($category->id === $forum->category->id)
|
||||
>
|
||||
{{ $category->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="forum_category_id">
|
||||
Forum Category
|
||||
</label>
|
||||
</p>
|
||||
<div class="form__group">
|
||||
<label class="form__label">Permissions</label>
|
||||
<div class="data-table-wrapper">
|
||||
@@ -125,27 +119,49 @@
|
||||
<tbody x-ref="tbody">
|
||||
@foreach ($groups as $group)
|
||||
<tr>
|
||||
<th x-bind="rowHeader">{{ $group->name }}</th>
|
||||
<th x-bind="rowHeader">
|
||||
{{ $group->name }}
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][group_id]"
|
||||
value="{{ $group->id }}"
|
||||
/>
|
||||
</th>
|
||||
<td>
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][read_topic]"
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $group->id }}][read_topic]"
|
||||
name="permissions[{{ $loop->index }}][read_topic]"
|
||||
value="1"
|
||||
@checked($forum->permissions->where('group_id', '=', $group->id)->first()?->read_topic)
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][start_topic]"
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $group->id }}][start_topic]"
|
||||
name="permissions[{{ $loop->index }}][start_topic]"
|
||||
value="1"
|
||||
@checked($forum->permissions->where('group_id', '=', $group->id)->first()?->start_topic)
|
||||
/>
|
||||
</td>
|
||||
<td>
|
||||
<input
|
||||
type="hidden"
|
||||
name="permissions[{{ $loop->index }}][reply_topic]"
|
||||
value="0"
|
||||
/>
|
||||
<input
|
||||
type="checkbox"
|
||||
name="permissions[{{ $group->id }}][reply_topic]"
|
||||
name="permissions[{{ $loop->index }}][reply_topic]"
|
||||
value="1"
|
||||
@checked($forum->permissions->where('group_id', '=', $group->id)->first()?->reply_topic)
|
||||
/>
|
||||
|
||||
@@ -1,129 +0,0 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('title')
|
||||
<title>Forums - {{ __('staff.staff-dashboard') }} - {{ config('other.title') }}</title>
|
||||
@endsection
|
||||
|
||||
@section('meta')
|
||||
<meta name="description" content="Forums - {{ __('staff.staff-dashboard') }}" />
|
||||
@endsection
|
||||
|
||||
@section('breadcrumbs')
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('staff.dashboard.index') }}" class="breadcrumb__link">
|
||||
{{ __('staff.staff-dashboard') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
{{ __('staff.forums') }}
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@section('page', 'page__forums-admin--index')
|
||||
|
||||
@section('main')
|
||||
<section class="panelV2">
|
||||
<header class="panel__header">
|
||||
<h2 class="panel__heading">Forums</h2>
|
||||
<a href="{{ route('staff.forums.create') }}" class="form__button form__button--text">
|
||||
{{ __('common.add') }}
|
||||
</a>
|
||||
</header>
|
||||
<div class="data-table-wrapper">
|
||||
<table class="data-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>{{ __('common.name') }}</th>
|
||||
<th>Type</th>
|
||||
<th>{{ __('common.position') }}</th>
|
||||
<th>{{ __('common.action') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($categories as $category)
|
||||
<tr>
|
||||
<td>
|
||||
<a href="{{ route('staff.forums.edit', ['forum' => $category]) }}">
|
||||
{{ $category->name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>Category</td>
|
||||
<td>{{ $category->position }}</td>
|
||||
<td>
|
||||
<menu class="data-table__actions">
|
||||
<li class="data-table__action">
|
||||
<a
|
||||
class="form__button form__button--text"
|
||||
href="{{ route('staff.forums.edit', ['forum' => $category]) }}"
|
||||
>
|
||||
{{ __('common.edit') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="data-table__action">
|
||||
<form
|
||||
method="POST"
|
||||
action="{{ route('staff.forums.destroy', ['forum' => $category]) }}"
|
||||
x-data="confirmation"
|
||||
>
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button
|
||||
x-on:click.prevent="confirmAction"
|
||||
data-b64-deletion-message="{{ base64_encode('Are you sure you want to delete this forum category: ' . $category->name . '?') }}"
|
||||
class="form__button form__button--text"
|
||||
>
|
||||
{{ __('common.delete') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</menu>
|
||||
</td>
|
||||
</tr>
|
||||
@foreach ($category->forums as $forum)
|
||||
<tr>
|
||||
<td style="padding-left: 50px">
|
||||
<a
|
||||
href="{{ route('staff.forums.edit', ['forum' => $forum]) }}"
|
||||
>
|
||||
{{ $forum->name }}
|
||||
</a>
|
||||
</td>
|
||||
<td>Forum</td>
|
||||
<td>{{ $forum->position }}</td>
|
||||
<td>
|
||||
<menu class="data-table__actions">
|
||||
<li class="data-table__action">
|
||||
<a
|
||||
class="form__button form__button--text"
|
||||
href="{{ route('staff.forums.edit', ['forum' => $forum]) }}"
|
||||
>
|
||||
{{ __('common.edit') }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="data-table__action">
|
||||
<form
|
||||
method="POST"
|
||||
action="{{ route('staff.forums.destroy', ['forum' => $forum]) }}"
|
||||
x-data="confirmation"
|
||||
>
|
||||
@csrf
|
||||
@method('DELETE')
|
||||
<button
|
||||
x-on:click.prevent="confirmAction"
|
||||
data-b64-deletion-message="{{ base64_encode('Are you sure you want to delete this forum: ' . $forum->name . '?') }}"
|
||||
class="form__button form__button--text"
|
||||
>
|
||||
{{ __('common.delete') }}
|
||||
</button>
|
||||
</form>
|
||||
</li>
|
||||
</menu>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
@endsection
|
||||
@@ -1,7 +1,7 @@
|
||||
@extends('layout.default')
|
||||
|
||||
@section('title')
|
||||
<title>{{ $forum->name }} - {{ __('forum.forums') }} - {{ config('other.title') }}</title>
|
||||
<title>{{ $category->name }} - {{ __('forum.forums') }} - {{ config('other.title') }}</title>
|
||||
@endsection
|
||||
|
||||
@section('meta')
|
||||
@@ -15,7 +15,7 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
{{ $forum->name }}
|
||||
{{ $category->name }}
|
||||
</li>
|
||||
@endsection
|
||||
|
||||
@@ -26,5 +26,5 @@
|
||||
@section('page', 'page__forum--category')
|
||||
|
||||
@section('main')
|
||||
@livewire('forum-category-topic-search', ['category' => $forum])
|
||||
@livewire('forum-category-topic-search', ['category' => $category])
|
||||
@endsection
|
||||
|
||||
@@ -31,9 +31,9 @@
|
||||
{{ $category->name }}
|
||||
</a>
|
||||
</h2>
|
||||
@if ($category->forums->count() > 0)
|
||||
@if ($category->forums->isNotEmpty())
|
||||
<ul class="subforum-listings">
|
||||
@foreach ($category->forums->sortBy('position') as $forum)
|
||||
@foreach ($category->forums as $forum)
|
||||
<li class="subforum-listings__item">
|
||||
<x-forum.subforum-listing :subforum="$forum" />
|
||||
</li>
|
||||
|
||||
@@ -64,9 +64,9 @@
|
||||
</p>
|
||||
<p class="form__group">
|
||||
<select id="forum_id" name="forum_id" class="form__select">
|
||||
@foreach ($categories as $category)
|
||||
<optgroup label="{{ $category->name }}">
|
||||
@foreach ($category->forums as $forum)
|
||||
@foreach ($categories as $name => $forums)
|
||||
<optgroup label="{{ $name }}">
|
||||
@foreach ($forums as $forum)
|
||||
<option
|
||||
value="{{ $forum->id }}"
|
||||
@selected($topic->forum_id === $forum->id)
|
||||
|
||||
@@ -12,15 +12,15 @@
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a
|
||||
href="{{ route('forums.categories.show', ['id' => $forum->category->id]) }}"
|
||||
href="{{ route('forums.categories.show', ['id' => $topic->forum->category->id]) }}"
|
||||
class="breadcrumb__link"
|
||||
>
|
||||
{{ $forum->category->name }}
|
||||
{{ $topic->forum->category->name }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumbV2">
|
||||
<a href="{{ route('forums.show', ['id' => $forum->id]) }}" class="breadcrumb__link">
|
||||
{{ $forum->name }}
|
||||
<a href="{{ route('forums.show', ['id' => $topic->forum->id]) }}" class="breadcrumb__link">
|
||||
{{ $topic->forum->name }}
|
||||
</a>
|
||||
</li>
|
||||
<li class="breadcrumb--active">
|
||||
@@ -43,7 +43,7 @@
|
||||
</p>
|
||||
@endif
|
||||
|
||||
@if (($topic->state === 'open' && $forum->getPermission()?->reply_topic) || auth()->user()->group->is_modo)
|
||||
@if (($topic->state === 'open' && $topic->forum->getPermission()?->reply_topic) || auth()->user()->group->is_modo)
|
||||
<form id="forum_reply_form" method="POST" action="{{ route('posts.store') }}">
|
||||
@csrf
|
||||
<input type="hidden" name="topic_id" value="{{ $topic->id }}" />
|
||||
|
||||
@@ -42,15 +42,15 @@
|
||||
wire:model="forumId"
|
||||
>
|
||||
<option value="">Any</option>
|
||||
@foreach ($forumCategories->sortBy('position') as $category)
|
||||
<option value="{{ $category->id }}">
|
||||
{{ $category->name }}
|
||||
</option>
|
||||
@foreach ($category->forums->sortBy('position') as $forum)
|
||||
<option value="{{ $forum->id }}">
|
||||
» {{ $forum->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
|
||||
@foreach ($forumCategories as $category)
|
||||
<optgroup label="{{ $category->name }}">
|
||||
@foreach ($category->forums as $forum)
|
||||
<option value="{{ $forum->id }}">
|
||||
{{ $forum->name }}
|
||||
</option>
|
||||
@endforeach
|
||||
</optgroup>
|
||||
@endforeach
|
||||
</select>
|
||||
<label class="form__label form__label--floating" for="category">
|
||||
|
||||
+11
-1
@@ -844,9 +844,19 @@ Route::middleware('language')->group(function (): void {
|
||||
});
|
||||
|
||||
// Forums System
|
||||
Route::prefix('forum-categories')->middleware('admin')->group(function (): void {
|
||||
Route::name('forum_categories.')->group(function (): void {
|
||||
Route::get('/', [App\Http\Controllers\Staff\ForumCategoryController::class, 'index'])->name('index');
|
||||
Route::get('/create', [App\Http\Controllers\Staff\ForumCategoryController::class, 'create'])->name('create');
|
||||
Route::post('/', [App\Http\Controllers\Staff\ForumCategoryController::class, 'store'])->name('store');
|
||||
Route::get('/{forumCategory}/edit', [App\Http\Controllers\Staff\ForumCategoryController::class, 'edit'])->name('edit');
|
||||
Route::patch('/{forumCategory}', [App\Http\Controllers\Staff\ForumCategoryController::class, 'update'])->name('update');
|
||||
Route::delete('/{forumCategory}', [App\Http\Controllers\Staff\ForumCategoryController::class, 'destroy'])->name('destroy');
|
||||
});
|
||||
});
|
||||
|
||||
Route::prefix('forums')->middleware('admin')->group(function (): void {
|
||||
Route::name('forums.')->group(function (): void {
|
||||
Route::get('/', [App\Http\Controllers\Staff\ForumController::class, 'index'])->name('index');
|
||||
Route::get('/create', [App\Http\Controllers\Staff\ForumController::class, 'create'])->name('create');
|
||||
Route::post('/', [App\Http\Controllers\Staff\ForumController::class, 'store'])->name('store');
|
||||
Route::get('/{forum}/edit', [App\Http\Controllers\Staff\ForumController::class, 'edit'])->name('edit');
|
||||
|
||||
@@ -18,21 +18,12 @@ use App\Models\User;
|
||||
test('show returns an ok response', function (): void {
|
||||
$user = User::factory()->create();
|
||||
|
||||
// This forum does not have a parent_id, which makes it a "Forum Category".
|
||||
$parentForum = Forum::factory()->create([
|
||||
'parent_id' => null,
|
||||
'last_topic_id' => null,
|
||||
]);
|
||||
$forum = Forum::factory()->create();
|
||||
|
||||
Permission::factory()->create([
|
||||
'forum_id' => $parentForum->id,
|
||||
'group_id' => $user->group_id,
|
||||
'forum_id' => $forum->id,
|
||||
]);
|
||||
|
||||
// This forum has a parent_id, which makes it a "Forum".
|
||||
$forum = Forum::factory()->create([
|
||||
'parent_id' => $parentForum->id,
|
||||
'last_topic_id' => null,
|
||||
]);
|
||||
|
||||
$this->actingAs($user)->get(route('forums.categories.show', ['id' => $forum->id]));
|
||||
$this->actingAs($user)->get(route('forums.categories.show', ['id' => $forum->forum_category_id]));
|
||||
});
|
||||
|
||||
@@ -36,16 +36,16 @@ test('show returns an ok response', function (): void {
|
||||
$user = User::factory()->create();
|
||||
|
||||
$forum = Forum::factory()->create([
|
||||
'parent_id' => null, // This Forum does not have a parent, which makes it a "Forum Category".
|
||||
'last_post_user_id' => $user->id,
|
||||
'last_topic_id' => null,
|
||||
]);
|
||||
|
||||
Permission::factory()->create([
|
||||
'group_id' => $user->group_id,
|
||||
'forum_id' => $forum->id,
|
||||
'read_topic' => true,
|
||||
]);
|
||||
|
||||
$response = $this->actingAs($user)->get(route('forums.show', ['id' => $forum->id]));
|
||||
$response->assertRedirect(route('forums.categories.show', ['id' => $forum->id]));
|
||||
$response->assertViewIs('forum.forum_topic.index');
|
||||
});
|
||||
|
||||
@@ -69,21 +69,6 @@ test('edit returns an ok response', function (): void {
|
||||
// TODO: perform additional assertions
|
||||
});
|
||||
|
||||
test('index returns an ok response', function (): void {
|
||||
$this->markTestIncomplete('This test case was generated by Shift. When you are ready, remove this line and complete this test case.');
|
||||
|
||||
$forums = Forum::factory()->times(3)->create();
|
||||
$user = User::factory()->create();
|
||||
|
||||
$response = $this->actingAs($user)->get(route('staff.forums.index'));
|
||||
|
||||
$response->assertOk();
|
||||
$response->assertViewIs('Staff.forum.index');
|
||||
$response->assertViewHas('categories');
|
||||
|
||||
// TODO: perform additional assertions
|
||||
});
|
||||
|
||||
test('store validates with a form request', function (): void {
|
||||
$this->assertActionUsesFormRequest(
|
||||
ForumController::class,
|
||||
|
||||
@@ -71,16 +71,11 @@ final class ForumControllerTest extends TestCase
|
||||
|
||||
$user = User::factory()->create();
|
||||
|
||||
// This Forum does not have a parent, which makes it a proper Forum
|
||||
// (and not a "Forum Category").
|
||||
|
||||
$forum = Forum::factory()->create([
|
||||
'parent_id' => 0,
|
||||
'last_post_user_id' => $user->id,
|
||||
]);
|
||||
$forum = Forum::factory()->create();
|
||||
|
||||
$permissions = Permission::factory()->create([
|
||||
'forum_id' => $forum->id,
|
||||
'group_id' => $user->group_id,
|
||||
'read_topic' => true,
|
||||
]);
|
||||
|
||||
|
||||
@@ -33,32 +33,38 @@ test('rules', function (): void {
|
||||
'position' => [
|
||||
'required',
|
||||
],
|
||||
'slug' => [
|
||||
'required',
|
||||
],
|
||||
'description' => [
|
||||
'required',
|
||||
],
|
||||
'parent_id' => [
|
||||
'sometimes',
|
||||
'nullable',
|
||||
'integer',
|
||||
'forum_category_id' => [
|
||||
'required',
|
||||
'exists:forum_categories,id',
|
||||
],
|
||||
'permissions' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'array',
|
||||
],
|
||||
'permissions.*' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'array:group_id,read_topic,reply_topic,start_topic',
|
||||
],
|
||||
'permissions.*.group_id' => [
|
||||
'required',
|
||||
'exists:groups,id',
|
||||
],
|
||||
'permissions.*.read_topic' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.reply_topic' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.start_topic' => [
|
||||
'sometimes',
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
], $actual);
|
||||
|
||||
@@ -33,31 +33,39 @@ test('rules', function (): void {
|
||||
'position' => [
|
||||
'required',
|
||||
],
|
||||
'slug' => [
|
||||
'required',
|
||||
],
|
||||
'description' => [
|
||||
'required',
|
||||
],
|
||||
'parent_id' => [
|
||||
'sometimes',
|
||||
'nullable',
|
||||
'integer',
|
||||
'forum_category_id' => [
|
||||
'required',
|
||||
'exists:forum_categories,id',
|
||||
],
|
||||
'permissions' => [
|
||||
'required',
|
||||
'array',
|
||||
],
|
||||
'permissions.*' => [
|
||||
'required',
|
||||
'array:group_id,read_topic,reply_topic,start_topic',
|
||||
],
|
||||
'permissions.*.group_id' => [
|
||||
'required',
|
||||
'exists:groups,id',
|
||||
],
|
||||
'permissions.*.read_topic' => [
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.reply_topic' => [
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'permissions.*.start_topic' => [
|
||||
'required',
|
||||
'boolean',
|
||||
],
|
||||
'forum_type' => [
|
||||
'in:category,forum',
|
||||
],
|
||||
], $actual);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user