work in progress
This commit is contained in:
parent
d751cd4fdd
commit
1e33bfb50b
@ -11,10 +11,10 @@ class DashboardController extends Controller
|
|||||||
public function index(Request $request, ActivityService $activityService)
|
public function index(Request $request, ActivityService $activityService)
|
||||||
{
|
{
|
||||||
$user = $request->user();
|
$user = $request->user();
|
||||||
$unreadDynamics = $activityService->getUnreadDynamicsGrouped($user);
|
$unreadEntities = $activityService->getUnreadEntitiesGrouped($user);
|
||||||
|
|
||||||
return Inertia::render('Dashboard', [
|
return Inertia::render('Dashboard', [
|
||||||
'unreadDynamics' => $unreadDynamics,
|
'unreadEntities' => $unreadEntities,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -85,9 +85,7 @@ class LedgerController extends Controller
|
|||||||
return Inertia::render('Ledgers/Show', [
|
return Inertia::render('Ledgers/Show', [
|
||||||
'dynamic' => new DynamicResource($dynamic),
|
'dynamic' => new DynamicResource($dynamic),
|
||||||
'ledger' => new LedgerResource($ledger),
|
'ledger' => new LedgerResource($ledger),
|
||||||
'mutations' => MutationResource::collection($ledger->mutations),
|
'messages' => MessageResource::collection($dynamic->getOrCreateChat()->messages()->with(['user', 'media'])->latest()->paginate(\App\Models\Message::PAGINATION_COUNT)),
|
||||||
'participants' => UserResource::collection($dynamic->participants),
|
|
||||||
'messages' => MessageResource::collection($dynamic->chat->messages()->with(['user', 'media'])->latest()->paginate(\App\Models\Message::PAGINATION_COUNT)),
|
|
||||||
'can' => [
|
'can' => [
|
||||||
'update' => $request->user()->can('update', $ledger),
|
'update' => $request->user()->can('update', $ledger),
|
||||||
'close' => $request->user()->can('close', $ledger),
|
'close' => $request->user()->can('close', $ledger),
|
||||||
@ -99,7 +97,7 @@ class LedgerController extends Controller
|
|||||||
{
|
{
|
||||||
$this->authorize('view', $ledger);
|
$this->authorize('view', $ledger);
|
||||||
|
|
||||||
return MessageResource::collection($dynamic->chat->messages()->with(['user', 'media'])->latest()->paginate(\App\Models\Message::PAGINATION_COUNT));
|
return MessageResource::collection($dynamic->getOrCreateChat()->messages()->with(['user', 'media'])->latest()->paginate(\App\Models\Message::PAGINATION_COUNT));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -50,7 +50,7 @@ class HandleInertiaRequests extends Middleware
|
|||||||
|
|
||||||
$service = app(ActivityService::class);
|
$service = app(ActivityService::class);
|
||||||
|
|
||||||
return count($service->getUnreadDynamicsGrouped($request->user()));
|
return count($service->getUnreadEntitiesGrouped($request->user()));
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|||||||
24
app/Http/Resources/ChatResource.php
Normal file
24
app/Http/Resources/ChatResource.php
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Resources;
|
||||||
|
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class ChatResource extends BaseResource
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Transform the resource into an array.
|
||||||
|
*
|
||||||
|
* @return array<string, mixed>
|
||||||
|
*/
|
||||||
|
public function toArray(Request $request): array
|
||||||
|
{
|
||||||
|
$data = parent::toArray($request);
|
||||||
|
|
||||||
|
if ($this->whenLoaded('messages')) {
|
||||||
|
$data['messages'] = MessageResource::collection($this->messages);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $data;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -17,9 +17,12 @@ class DynamicResource extends BaseResource
|
|||||||
if ($this->ledgers) {
|
if ($this->ledgers) {
|
||||||
$result['ledgers'] = LedgerResource::collection($this->ledgers);
|
$result['ledgers'] = LedgerResource::collection($this->ledgers);
|
||||||
}
|
}
|
||||||
if ($this->participants) {
|
if ($this->whenLoaded('participants')) {
|
||||||
$result['participants'] = ParticipantResource::collection($this->participants);
|
$result['participants'] = ParticipantResource::collection($this->participants);
|
||||||
}
|
}
|
||||||
|
if ($this->whenLoaded('chat')) {
|
||||||
|
$result['chat'] = new ChatResource($this->chat);
|
||||||
|
}
|
||||||
return $result;
|
return $result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,6 +13,10 @@ class LedgerResource extends BaseResource
|
|||||||
*/
|
*/
|
||||||
public function toArray(Request $request): array
|
public function toArray(Request $request): array
|
||||||
{
|
{
|
||||||
return parent::toArray($request);
|
$data = parent::toArray($request);
|
||||||
|
|
||||||
|
$data['mutations'] = MutationResource::collection($this->whenLoaded('mutations'));
|
||||||
|
|
||||||
|
return $data;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
|||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
use Illuminate\Database\Eloquent\Relations\MorphOne;
|
||||||
use Illuminate\Support\Str;
|
use Illuminate\Support\Str;
|
||||||
|
use App\Models\Chat;
|
||||||
|
|
||||||
class Dynamic extends Model
|
class Dynamic extends Model
|
||||||
{
|
{
|
||||||
@ -64,4 +65,13 @@ class Dynamic extends Model
|
|||||||
public function getUrlAttribute(): string {
|
public function getUrlAttribute(): string {
|
||||||
return route('dynamics.show', $this);
|
return route('dynamics.show', $this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function getOrCreateChat(): Chat
|
||||||
|
{
|
||||||
|
if ($this->chat) {
|
||||||
|
return $this->chat;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->chat()->create([]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -45,8 +45,9 @@ class ActivityService
|
|||||||
return $cursor ? $cursor->read_at : Carbon::parse('1970-01-01');
|
return $cursor ? $cursor->read_at : Carbon::parse('1970-01-01');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createMessage($chat, $user, $content, $subject = null)
|
public function createMessage($dynamic, $user, $content, $subject = null)
|
||||||
{
|
{
|
||||||
|
$chat = $dynamic->getOrCreateChat();
|
||||||
$message = $chat->messages()->create([
|
$message = $chat->messages()->create([
|
||||||
'user_id' => $user ? $user->id : null,
|
'user_id' => $user ? $user->id : null,
|
||||||
'content' => $content,
|
'content' => $content,
|
||||||
@ -92,6 +93,11 @@ class ActivityService
|
|||||||
*/
|
*/
|
||||||
public function getActivitiesForDynamic(Dynamic $dynamic): array
|
public function getActivitiesForDynamic(Dynamic $dynamic): array
|
||||||
{
|
{
|
||||||
|
$chat = $dynamic->getOrCreateChat();
|
||||||
|
if (!$chat) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
$participants = $dynamic->participants()->withPivot('display_name')->get();
|
$participants = $dynamic->participants()->withPivot('display_name')->get();
|
||||||
$participantsMap = $participants->reduce(function ($acc, $p) {
|
$participantsMap = $participants->reduce(function ($acc, $p) {
|
||||||
$acc[$p->id] = $p->pivot->display_name ?? $p->name;
|
$acc[$p->id] = $p->pivot->display_name ?? $p->name;
|
||||||
@ -99,7 +105,7 @@ class ActivityService
|
|||||||
return $acc;
|
return $acc;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
$messages = Message::where('chat_id', $dynamic->chat->id)
|
$messages = Message::where('chat_id', $chat->id)
|
||||||
->with(['user', 'subject'])
|
->with(['user', 'subject'])
|
||||||
->latest()
|
->latest()
|
||||||
->get();
|
->get();
|
||||||
@ -122,10 +128,10 @@ class ActivityService
|
|||||||
/**
|
/**
|
||||||
* Get unread activities grouped by active entities (Dynamics, Ledgers) for the given user.
|
* Get unread activities grouped by active entities (Dynamics, Ledgers) for the given user.
|
||||||
*/
|
*/
|
||||||
public function getUnreadDynamicsGrouped(User $user): array
|
public function getUnreadEntitiesGrouped(User $user): array
|
||||||
{
|
{
|
||||||
$groupedDynamics = [];
|
$groupedDynamics = [];
|
||||||
$participatingDynamics = $user->dynamics()->with('ledgers')->get();
|
$participatingDynamics = $user->dynamics()->with(['chat', 'ledgers'])->get();
|
||||||
|
|
||||||
foreach ($participatingDynamics as $dynamic) {
|
foreach ($participatingDynamics as $dynamic) {
|
||||||
$readAt = $this->getCursorReadAt($user, $dynamic);
|
$readAt = $this->getCursorReadAt($user, $dynamic);
|
||||||
|
|||||||
@ -14,7 +14,7 @@ defineOptions({
|
|||||||
});
|
});
|
||||||
|
|
||||||
defineProps<{
|
defineProps<{
|
||||||
unreadDynamics: Array<{
|
unreadEntities: Array<{
|
||||||
id: number;
|
id: number;
|
||||||
name: string;
|
name: string;
|
||||||
url: string;
|
url: string;
|
||||||
@ -50,10 +50,10 @@ function formatTime(isoString: string): string {
|
|||||||
<div class="c-dashboard__container">
|
<div class="c-dashboard__container">
|
||||||
<h2 class="c-dashboard__title">Recent Activity</h2>
|
<h2 class="c-dashboard__title">Recent Activity</h2>
|
||||||
|
|
||||||
<div v-if="unreadDynamics.length > 0" class="c-dashboard__grid">
|
<div v-if="unreadEntities.length > 0" class="c-dashboard__grid">
|
||||||
<div
|
<div
|
||||||
v-for="dynamic in unreadDynamics"
|
v-for="entity in unreadEntities"
|
||||||
:key="dynamic.id"
|
:key="entity.id"
|
||||||
class="c-dashboard__card"
|
class="c-dashboard__card"
|
||||||
>
|
>
|
||||||
<div class="c-dashboard__card-header">
|
<div class="c-dashboard__card-header">
|
||||||
|
|||||||
@ -18,7 +18,7 @@ test('authenticated users can visit the dashboard', function () {
|
|||||||
|
|
||||||
$response = $this->get(route('dashboard'));
|
$response = $this->get(route('dashboard'));
|
||||||
$response->assertOk();
|
$response->assertOk();
|
||||||
$response->assertInertia(fn ($page) => $page->component('Dashboard')->has('unreadDynamics'));
|
$response->assertInertia(fn ($page) => $page->component('Dashboard')->has('unreadEntities'));
|
||||||
});
|
});
|
||||||
|
|
||||||
test('visiting dynamic updates the read cursor', function () {
|
test('visiting dynamic updates the read cursor', function () {
|
||||||
@ -100,12 +100,12 @@ test('dashboard groups and filters unread entities correctly based on cursor', f
|
|||||||
// Verify unread grouping structure
|
// Verify unread grouping structure
|
||||||
$response->assertInertia(fn ($page) => $page
|
$response->assertInertia(fn ($page) => $page
|
||||||
->component('Dashboard')
|
->component('Dashboard')
|
||||||
->where('unreadDynamics.0.name', 'Testing Dynamic')
|
->where('unreadEntities.0.name', 'Testing Dynamic')
|
||||||
->where('unreadDynamics.0.unread_count', 1)
|
->where('unreadEntities.0.unread_count', 1)
|
||||||
->has('unreadDynamics.0.context_activities', 1) // Should have old message as context
|
->has('unreadEntities.0.context_activities', 1) // Should have old message as context
|
||||||
->where('unreadDynamics.0.context_activities.0.content', 'Old message context')
|
->where('unreadEntities.0.context_activities.0.content', 'Old message context')
|
||||||
->has('unreadDynamics.0.new_activities', 1) // Should have unread message
|
->has('unreadEntities.0.new_activities', 1) // Should have unread message
|
||||||
->where('unreadDynamics.0.new_activities.0.content', 'New unread message alert')
|
->where('unreadEntities.0.new_activities.0.content', 'New unread message alert')
|
||||||
);
|
);
|
||||||
|
|
||||||
// Now visit the Dynamic, which clears the unread count
|
// Now visit the Dynamic, which clears the unread count
|
||||||
@ -116,7 +116,7 @@ test('dashboard groups and filters unread entities correctly based on cursor', f
|
|||||||
$response2->assertOk();
|
$response2->assertOk();
|
||||||
$response2->assertInertia(fn ($page) => $page
|
$response2->assertInertia(fn ($page) => $page
|
||||||
->component('Dashboard')
|
->component('Dashboard')
|
||||||
->has('unreadDynamics', 0)
|
->has('unreadEntities', 0)
|
||||||
);
|
);
|
||||||
|
|
||||||
Carbon::setTestNow(); // Reset test time
|
Carbon::setTestNow(); // Reset test time
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user