Commit workspace changes
This commit is contained in:
235
app/Http/Controllers/Studio/GroupStudioController.php
Normal file
235
app/Http/Controllers/Studio/GroupStudioController.php
Normal file
@@ -0,0 +1,235 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Http\Controllers\Studio;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\Groups\StoreGroupRequest;
|
||||
use App\Http\Requests\Groups\UpdateGroupRequest;
|
||||
use App\Models\Group;
|
||||
use App\Services\GroupMembershipService;
|
||||
use App\Services\GroupService;
|
||||
use App\Services\GroupArtworkReviewService;
|
||||
use App\Services\GroupJoinRequestService;
|
||||
use App\Services\GroupReputationService;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Inertia\Inertia;
|
||||
use Inertia\Response;
|
||||
|
||||
class GroupStudioController extends Controller
|
||||
{
|
||||
public function __construct(
|
||||
private readonly GroupService $groups,
|
||||
private readonly GroupMembershipService $memberships,
|
||||
private readonly GroupJoinRequestService $joinRequests,
|
||||
private readonly GroupArtworkReviewService $artworkReviews,
|
||||
private readonly GroupReputationService $reputation,
|
||||
) {
|
||||
}
|
||||
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
$user = $request->user();
|
||||
|
||||
$groups = Group::query()
|
||||
->with(['owner.profile', 'members'])
|
||||
->where(function ($query) use ($user): void {
|
||||
$query->where('owner_user_id', $user->id)
|
||||
->orWhereHas('members', function ($memberQuery) use ($user): void {
|
||||
$memberQuery->where('user_id', $user->id)
|
||||
->where('status', Group::STATUS_ACTIVE);
|
||||
});
|
||||
})
|
||||
->orderBy('name')
|
||||
->get()
|
||||
->map(fn (Group $group): array => $this->groups->mapGroupCard($group, $user))
|
||||
->values()
|
||||
->all();
|
||||
|
||||
return Inertia::render('Studio/StudioGroupsIndex', [
|
||||
'title' => 'Groups',
|
||||
'description' => 'Create collective publishing identities, manage memberships, and switch into shared artwork and collection workflows.',
|
||||
'groups' => $groups,
|
||||
'pendingInvites' => $this->memberships->pendingInvitationsForUser($user),
|
||||
'endpoints' => [
|
||||
'create' => route('studio.groups.create'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): Response
|
||||
{
|
||||
$this->authorize('create', Group::class);
|
||||
|
||||
return Inertia::render('Studio/StudioGroupCreate', [
|
||||
'title' => 'Create Group',
|
||||
'description' => 'Set up a shared publishing identity for collaborative uploads and collections.',
|
||||
'visibilityOptions' => [
|
||||
['value' => Group::VISIBILITY_PUBLIC, 'label' => 'Public'],
|
||||
['value' => Group::VISIBILITY_UNLISTED, 'label' => 'Unlisted'],
|
||||
['value' => Group::VISIBILITY_PRIVATE, 'label' => 'Private'],
|
||||
],
|
||||
'membershipPolicyOptions' => [
|
||||
['value' => Group::MEMBERSHIP_INVITE_ONLY, 'label' => 'Invite only'],
|
||||
],
|
||||
'endpoints' => [
|
||||
'store' => route('studio.groups.store'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(StoreGroupRequest $request): RedirectResponse
|
||||
{
|
||||
$this->authorize('create', Group::class);
|
||||
|
||||
$group = $this->groups->createGroup($request->user(), $request->validated());
|
||||
|
||||
return redirect()->route('studio.groups.show', ['group' => $group]);
|
||||
}
|
||||
|
||||
public function show(Request $request, Group $group): Response
|
||||
{
|
||||
$this->authorize('viewStudio', $group);
|
||||
|
||||
$viewer = $request->user();
|
||||
|
||||
return Inertia::render('Studio/StudioGroupDashboard', [
|
||||
'title' => $group->name,
|
||||
'description' => $group->headline ?: 'Shared publishing overview for this group.',
|
||||
'studioGroup' => $this->groups->mapGroupDetail($group, $viewer),
|
||||
'dashboard' => $this->groups->studioDashboardSummary($group),
|
||||
'draftsPendingAction' => $this->groups->studioArtworkPreviewItems($group, 'drafts', 4),
|
||||
'recentArtworks' => $this->groups->studioArtworkPreviewItems($group, 'published', 6),
|
||||
'recentCollections' => $this->groups->studioCollectionPreviewItems($group, 4),
|
||||
'members' => $this->memberships->mapMembers($group, $viewer),
|
||||
'recentPosts' => $this->groups->recentPostCards($group, 3),
|
||||
'recentProjects' => $this->groups->recentProjectCards($group, $viewer, 3),
|
||||
'recentReleases' => $this->groups->recentReleaseCards($group, $viewer, 3),
|
||||
'recentChallenges' => $this->groups->recentChallengeCards($group, $viewer, 3),
|
||||
'recentEvents' => $this->groups->recentEventCards($group, $viewer, 3),
|
||||
'recentActivity' => $this->groups->studioActivityFeed($group, $viewer, 8),
|
||||
'recruitment' => $this->groups->recruitmentPayload($group),
|
||||
'reputationSummary' => $this->reputation->summary($group),
|
||||
'trustSignals' => $this->reputation->trustSignals($group),
|
||||
'pendingJoinRequests' => $group->canReviewJoinRequests($viewer)
|
||||
? $this->joinRequests->mapRequests($group, $viewer, ['bucket' => 'pending', 'per_page' => 4])['items']
|
||||
: [],
|
||||
'reviewQueuePreview' => $this->artworkReviews->listing($group, $viewer, ['bucket' => 'submitted', 'per_page' => 4])['items'],
|
||||
'recentHistory' => $this->groups->recentHistory($group, 6),
|
||||
]);
|
||||
}
|
||||
|
||||
public function artworks(Request $request, Group $group): Response
|
||||
{
|
||||
$this->authorize('viewStudio', $group);
|
||||
|
||||
return Inertia::render('Studio/StudioGroupArtworks', [
|
||||
'title' => $group->name . ' Artworks',
|
||||
'description' => 'Browse every artwork published through this shared identity.',
|
||||
'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
|
||||
'listing' => $this->groups->studioArtworkListing($group, $request->only(['bucket', 'q', 'page', 'per_page'])),
|
||||
'uploadUrl' => route('upload', ['group' => $group->slug]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function collections(Request $request, Group $group): Response
|
||||
{
|
||||
$this->authorize('viewStudio', $group);
|
||||
|
||||
return Inertia::render('Studio/StudioGroupCollections', [
|
||||
'title' => $group->name . ' Collections',
|
||||
'description' => 'Manage collections published under this group identity.',
|
||||
'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
|
||||
'listing' => $this->groups->studioCollectionListing($group, $request->only(['bucket', 'q', 'page', 'per_page'])),
|
||||
'createUrl' => route('settings.collections.create', ['group' => $group->slug]),
|
||||
]);
|
||||
}
|
||||
|
||||
public function members(Request $request, Group $group): Response
|
||||
{
|
||||
$this->authorize('viewStudio', $group);
|
||||
$viewer = $request->user();
|
||||
$canManageMembers = $group->canManageMembers($viewer);
|
||||
|
||||
return Inertia::render('Studio/StudioGroupMembers', [
|
||||
'title' => $group->name . ' Members',
|
||||
'description' => 'Invite, remove, and promote the people who can publish and curate under this group.',
|
||||
'studioGroup' => $this->groups->mapGroupDetail($group, $viewer),
|
||||
'members' => $this->memberships->mapMembers($group, $viewer),
|
||||
'canManageMembers' => $canManageMembers,
|
||||
'permissionOverrideOptions' => array_map(static fn (string $permission): array => [
|
||||
'value' => $permission,
|
||||
'label' => str_replace('_', ' ', $permission),
|
||||
], Group::allowedPermissionOverrides()),
|
||||
'endpoints' => $canManageMembers ? [
|
||||
'invite' => route('studio.groups.members.store', ['group' => $group]),
|
||||
'invitations' => route('studio.groups.invitations', ['group' => $group]),
|
||||
'updatePattern' => route('studio.groups.members.update', ['group' => $group, 'member' => '__MEMBER__']),
|
||||
'permissionsPattern' => route('studio.groups.members.permissions.update', ['group' => $group, 'member' => '__MEMBER__']),
|
||||
'transferPattern' => route('studio.groups.members.transfer', ['group' => $group, 'member' => '__MEMBER__']),
|
||||
'deletePattern' => route('studio.groups.members.destroy', ['group' => $group, 'member' => '__MEMBER__']),
|
||||
] : null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function invitations(Request $request, Group $group): Response
|
||||
{
|
||||
$this->authorize('manageMembers', $group);
|
||||
|
||||
return Inertia::render('Studio/StudioGroupInvitations', [
|
||||
'title' => $group->name . ' Invitations',
|
||||
'description' => 'Manage outstanding invites, resend collaboration roles, and review recent invite history for this group.',
|
||||
'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
|
||||
'members' => $this->memberships->mapMembers($group, $request->user()),
|
||||
'invitations' => $this->memberships->mapInvitations($group, $request->user()),
|
||||
'endpoints' => [
|
||||
'invite' => route('studio.groups.members.store', ['group' => $group]),
|
||||
'deletePattern' => route('studio.groups.invitations.destroy', ['group' => $group, 'invitation' => '__INVITATION__']),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function settings(Request $request, Group $group): Response
|
||||
{
|
||||
$this->authorize('update', $group);
|
||||
|
||||
return Inertia::render('Studio/StudioGroupSettings', [
|
||||
'title' => $group->name . ' Settings',
|
||||
'description' => 'Update the public presentation and collaboration defaults for this group.',
|
||||
'studioGroup' => $this->groups->mapGroupDetail($group, $request->user()),
|
||||
'featuredArtworkOptions' => $this->groups->studioFeaturedArtworkOptions($group),
|
||||
'visibilityOptions' => [
|
||||
['value' => Group::VISIBILITY_PUBLIC, 'label' => 'Public'],
|
||||
['value' => Group::VISIBILITY_UNLISTED, 'label' => 'Unlisted'],
|
||||
['value' => Group::VISIBILITY_PRIVATE, 'label' => 'Private'],
|
||||
],
|
||||
'membershipPolicyOptions' => [
|
||||
['value' => Group::MEMBERSHIP_INVITE_ONLY, 'label' => 'Invite only'],
|
||||
],
|
||||
'endpoints' => [
|
||||
'update' => route('studio.groups.update', ['group' => $group]),
|
||||
'archive' => route('studio.groups.archive', ['group' => $group]),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(UpdateGroupRequest $request, Group $group): RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $group);
|
||||
|
||||
$group = $this->groups->updateGroup($group, $request->validated(), $request->user());
|
||||
|
||||
return redirect()->route('studio.groups.settings', ['group' => $group]);
|
||||
}
|
||||
|
||||
public function archive(Request $request, Group $group): RedirectResponse
|
||||
{
|
||||
$this->authorize('archive', $group);
|
||||
|
||||
$group = $this->groups->archiveGroup($group, $request->user());
|
||||
|
||||
return redirect()->route('studio.groups.settings', ['group' => $group]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user