Update viewer page to include moderator actions, links to Twitch viewer cards
This commit is contained in:
parent
e45fb69b6a
commit
70fa331f46
@ -12,7 +12,7 @@ class ViewerController extends Controller
|
|||||||
{
|
{
|
||||||
public function index(ViewerRequest $request, string $viewer)
|
public function index(ViewerRequest $request, string $viewer)
|
||||||
{
|
{
|
||||||
$viewer = strtolower($viewer);
|
$viewer = strtolower(trim($viewer));
|
||||||
$message = Message::orderBy('timestamp', 'desc')
|
$message = Message::orderBy('timestamp', 'desc')
|
||||||
->where('author_id', $viewer)
|
->where('author_id', $viewer)
|
||||||
->orWhere('author_login', $viewer)
|
->orWhere('author_login', $viewer)
|
||||||
@ -45,11 +45,26 @@ public function index(ViewerRequest $request, string $viewer)
|
|||||||
return $b->timestamp <=> $a->timestamp;
|
return $b->timestamp <=> $a->timestamp;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$user = $request->user();
|
||||||
|
$moderatorActions = [];
|
||||||
|
$channelPerms = $user->channelPermissions();
|
||||||
|
$channels = $user->getTraceChannels();
|
||||||
|
|
||||||
|
$channelPermsIds = $channelPerms->pluck('channel_provider_id')->toArray();
|
||||||
|
|
||||||
|
$moderatorActions = ModeratorAction::where('target_id', $viewerId)
|
||||||
|
->orWhere('initiator_id', $viewerId)
|
||||||
|
->whereIn('channel_id', $channelPermsIds)
|
||||||
|
->orderBy('timestamp', 'desc')
|
||||||
|
->paginate(50);
|
||||||
|
|
||||||
return view('viewer.index', [
|
return view('viewer.index', [
|
||||||
'id' => $viewerId,
|
'id' => $viewerId,
|
||||||
'username' => $initialMessage->author_login,
|
'username' => $initialMessage->author_login,
|
||||||
'usernames' => $usernames,
|
'usernames' => $usernames,
|
||||||
'messages' => $messages,
|
'messages' => $messages,
|
||||||
|
'actions' => $moderatorActions,
|
||||||
|
'channels' => $channels,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ public function formatted($asHtml = false) : string
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the target of the action, if any
|
* Get the target name of the action, if any
|
||||||
*
|
*
|
||||||
* @param bool $linkToViewerPage Returns an HTML link to the viewer page
|
* @param bool $linkToViewerPage Returns an HTML link to the viewer page
|
||||||
* @return string
|
* @return string
|
||||||
@ -106,6 +106,30 @@ public function targetName($linkToViewerPage = false) : ?string
|
|||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the target ID of the action, if any
|
||||||
|
*
|
||||||
|
* @return string|null
|
||||||
|
*/
|
||||||
|
public function targetId() : ?string
|
||||||
|
{
|
||||||
|
if (!empty($this->target_id)) {
|
||||||
|
return $this->target_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the channel that the action was executed in
|
||||||
|
*
|
||||||
|
* @return Channel
|
||||||
|
*/
|
||||||
|
public function channel()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(Channel::class, 'channel_id', 'channel_id');
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the user that executed the action
|
* Get the user that executed the action
|
||||||
*
|
*
|
||||||
|
82
resources/views/components/moderator-actions.blade.php
Normal file
82
resources/views/components/moderator-actions.blade.php
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
@php
|
||||||
|
$showChannel = $showChannel ?? false;
|
||||||
|
@endphp
|
||||||
|
<table class="w-full table-auto">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th class="px-4 py-2">Time & date</th>
|
||||||
|
<th class="px-4 py-2">Command</th>
|
||||||
|
<th class="px-4 py-2">Moderator</th>
|
||||||
|
@if ($showChannel)
|
||||||
|
<th class="px-4 py-2">Channel</th>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@foreach ($actions as $action)
|
||||||
|
<tr>
|
||||||
|
<td class="px-4 py-2 border" title="{{ $action->timestamp }} UTC" data-timestamp="{{ $action->timestamp->toIso8601String() }}"></td>
|
||||||
|
@if (empty($action->targetName()))
|
||||||
|
<td class="px-4 py-2 break-all border">
|
||||||
|
<code>{{ $action->formatted() }}</code>
|
||||||
|
</td>
|
||||||
|
@else
|
||||||
|
<td class="px-4 py-2 break-all border">
|
||||||
|
<code>
|
||||||
|
{!! $action->formatted(true) !!}
|
||||||
|
</code>
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
|
<td class="px-4 py-2 border">{{ $action->user->login }}</td>
|
||||||
|
@if ($showChannel)
|
||||||
|
@php
|
||||||
|
$channel = $action->channel->username();
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
<td class="px-4 py-2 border">
|
||||||
|
<a class="text-rose-400" href="{{ route('dashboard.channel', ['channel' => $channel]) }}">
|
||||||
|
{{ $channel }}
|
||||||
|
</a>
|
||||||
|
</td>
|
||||||
|
@endif
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
</tbody>
|
||||||
|
@if ($actions->hasPages())
|
||||||
|
<tfoot>
|
||||||
|
<tr>
|
||||||
|
<td colspan="{{ $showChannel ? 4 : 3 }}" class="px-4 py-2 border">
|
||||||
|
{{ $actions->links() }}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tfoot>
|
||||||
|
@endif
|
||||||
|
</table>
|
||||||
|
|
||||||
|
|
||||||
|
@section('scripts')
|
||||||
|
<script>
|
||||||
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
|
const timestamps = document.querySelectorAll('[data-timestamp]');
|
||||||
|
|
||||||
|
// Get locale from browser for Intl.DateTimeFormat
|
||||||
|
const locale = navigator.language;
|
||||||
|
|
||||||
|
const formatterOpts = {
|
||||||
|
hour: 'numeric',
|
||||||
|
minute: 'numeric',
|
||||||
|
second: 'numeric',
|
||||||
|
year: 'numeric',
|
||||||
|
month: 'long',
|
||||||
|
day: 'numeric',
|
||||||
|
};
|
||||||
|
|
||||||
|
const formatter = new Intl.DateTimeFormat(locale, formatterOpts);
|
||||||
|
|
||||||
|
for (const timestamp of timestamps) {
|
||||||
|
const date = new Date(timestamp.dataset.timestamp);
|
||||||
|
timestamp.innerText = formatter.format(date);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endsection
|
@ -1,55 +1,18 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||||
{{ __('Dashboard') }}
|
{{ __('Dashboard') }}
|
||||||
</h2>
|
</h2>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
<div class="mx-auto sm:px-6 lg:px-8">
|
<div class="mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
<div class="overflow-hidden bg-gray-800 shadow-sm sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-100">
|
<div class="p-6 text-gray-100">
|
||||||
<h2 class="font-semibold text-xl text-gray-200 leading-tight">
|
<h2 class="text-xl font-semibold leading-tight text-gray-200">
|
||||||
{{ $channel->username() }}
|
{{ $channel->username() }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<table class="table-auto w-full">
|
@include('components.moderator-actions', ['actions' => $actions])
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th class="px-4 py-2">Time & date</th>
|
|
||||||
<th class="px-4 py-2">Command</th>
|
|
||||||
<th class="px-4 py-2">Moderator</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
@foreach ($actions as $action)
|
|
||||||
<tr>
|
|
||||||
<td class="border px-4 py-2" title="{{ $action->timestamp }}">{{ $action->timestamp }}
|
|
||||||
</td>
|
|
||||||
@if (empty($action->targetName()))
|
|
||||||
<td class="border px-4 py-2 break-all">
|
|
||||||
<code>{{ $action->formatted() }}</code>
|
|
||||||
</td>
|
|
||||||
@else
|
|
||||||
<td class="border px-4 py-2 break-all">
|
|
||||||
<code>
|
|
||||||
{!! $action->formatted(true) !!}
|
|
||||||
</code>
|
|
||||||
</td>
|
|
||||||
@endif
|
|
||||||
<td class="border px-4 py-2">{{ $action->user->login }}</td>
|
|
||||||
</tr>
|
|
||||||
@endforeach
|
|
||||||
</tbody>
|
|
||||||
@if ($actions->hasPages())
|
|
||||||
<tfoot>
|
|
||||||
<tr>
|
|
||||||
<td colspan="3" class="border px-4 py-2">
|
|
||||||
{{ $actions->links() }}
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
</tfoot>
|
|
||||||
@endif
|
|
||||||
</table>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||||
{{ __('Dashboard') }}
|
{{ __('Dashboard') }}
|
||||||
</h2>
|
</h2>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
<div class="mx-auto sm:px-6 lg:px-8">
|
<div class="mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
<div class="overflow-hidden bg-gray-800 shadow-sm sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-100">
|
<div class="p-6 text-gray-100">
|
||||||
{{ __("Hi :user!", ['user' => Auth::user()->display_name]) }}
|
{{ __("Hi :user!", ['user' => Auth::user()->display_name]) }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="bg-gray-800 p-6 -mt-6 text-gray-100">
|
<div class="p-6 -mt-6 text-gray-100 bg-gray-800">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight mb-2">
|
<h2 class="mb-2 text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||||
{{ __('Channels') }}
|
{{ __('Channels') }}
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
<!-- Fonts -->
|
<!-- Fonts -->
|
||||||
<link rel="preconnect" href="https://fonts.bunny.net">
|
<link rel="preconnect" href="https://fonts.bunny.net">
|
||||||
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
|
<link href="https://fonts.bunny.net/css?family=figtree:400,500,600&display=swap" rel="stylesheet" />
|
||||||
|
<link rel="stylesheet" href="https://decicus-cdn.b-cdn.net/fontawesome/v6.4.2/css/all.min.css" integrity="sha512-WgpJvPsU5RMfJeB5QbEbVfyuEGX+emeIHhNIFdc2SdyXVA11IyRLkdHZZHcnbxs/tCEAQFr2YEWrqqHFRL88eQ==" crossorigin="anonymous">
|
||||||
|
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||||
@ -17,13 +18,13 @@
|
|||||||
@yield('head')
|
@yield('head')
|
||||||
</head>
|
</head>
|
||||||
<body class="font-sans antialiased bg-gray-900">
|
<body class="font-sans antialiased bg-gray-900">
|
||||||
<div class="flex flex-col h-screen justify-between">
|
<div class="flex flex-col justify-between h-screen">
|
||||||
<livewire:layout.navigation />
|
<livewire:layout.navigation />
|
||||||
|
|
||||||
<!-- Page Heading -->
|
<!-- Page Heading -->
|
||||||
@if (isset($header))
|
@if (isset($header))
|
||||||
<header class="bg-gray-800 shadow">
|
<header class="bg-gray-800 shadow">
|
||||||
<div class="max-w-full mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
<div class="max-w-full px-4 py-6 mx-auto sm:px-6 lg:px-8">
|
||||||
{{ $header }}
|
{{ $header }}
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
@ -31,24 +32,28 @@
|
|||||||
|
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<div class="max-w-full mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-full mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
<div class="overflow-hidden bg-gray-800 shadow-sm sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-100">
|
<div class="p-6 text-gray-100">
|
||||||
<p>This is the initial implementation of this project. A few different things that are planned:</p>
|
<p><i class="fas fa-list fa-1x"></i> This is the initial implementation of this project. A few different things that are planned:</p>
|
||||||
|
<ul class="mt-2 list-disc list-inside">
|
||||||
<ul class="list-disc list-inside mt-2">
|
|
||||||
<li>Channels that are tracked where you have moderator access will be <a href="https://twitch.uservoice.com/forums/310213-developers/suggestions/38203849-add-endpoint-to-return-channels-where-the-user-is" class="underline text-amber-400">automatically retrieved from Twitch's API upon login</a>. At the moment I have to manually give permissions via the database, since this API is currently only "planned" by Twitch.</li>
|
<li>Channels that are tracked where you have moderator access will be <a href="https://twitch.uservoice.com/forums/310213-developers/suggestions/38203849-add-endpoint-to-return-channels-where-the-user-is" class="underline text-amber-400">automatically retrieved from Twitch's API upon login</a>. At the moment I have to manually give permissions via the database, since this API is currently only "planned" by Twitch.</li>
|
||||||
<li>Different filtering options: Type of action (timeout, raid etc.), moderator (whodunit), user/viewer (next point).</li>
|
<li>Different filtering options: Type of action (timeout, raid etc.), moderator (whodunit), user/viewer (next point).</li>
|
||||||
<li>See related moderation actions, for example if a specific viewer has been timed out or banned multiple times.</li>
|
|
||||||
<li>Searching by text.</li>
|
<li>Searching by text.</li>
|
||||||
<li>Linking any affected viewer's to their Twitch viewer card.</li>
|
|
||||||
<li>Automatic conversion to local time. Currently time & date is displayed in UTC.</li>
|
|
||||||
<li>Ability to see a viewer's chat messages at the time of action, alongside messages before/after to see context.</li>
|
<li>Ability to see a viewer's chat messages at the time of action, alongside messages before/after to see context.</li>
|
||||||
<li>... and probably more I'll figure out as I go along.</li>
|
<li>... and probably more I'll figure out as I go along.</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
<p class="mt-6">List of things that were planned and has been implemented in some form:</p>
|
<p class="mt-6"><i class="fas fa-check fa-1x"></i> List of things that were planned and has been implemented in some form:</p>
|
||||||
<ul class="list-disc list-inside mt-2">
|
<ul class="mt-2 list-disc list-inside">
|
||||||
<li>Username history of a user - For any user that has been timed out, raided, etc. you can now click on their name (highlighted in orange/amber) and access their basic "viewer profile".</li>
|
<li><s>Username history of a user</s> - For any user that has been timed out, raided, etc. you can now click on their name (highlighted in orange/amber) and access their basic "viewer profile".</li>
|
||||||
|
<li><s>See related moderation actions, for example if a specific viewer has been timed out or banned multiple times.</s> - Implemented on the viewer profile. Will display moderation actions for any channels you have access to.</li>
|
||||||
|
<li><s>Automatic conversion to local time. Currently time & date is displayed in UTC.</s> - Original UTC timestamp is still available if you hover over the converted timestamp in the table.</li>
|
||||||
|
<li><s>Linking any affected viewer's to their Twitch viewer card.</s> - Viewer card will be linked for any channel you have access to.</li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p class="mt-6"><i class="fas fa-bug fa-1x"></i> Known bugs:</p>
|
||||||
|
<ul class="mt-2 list-disc list-inside">
|
||||||
|
<li>Attempting to access a viewer page of someone who has no tracked chat messages will give you a 404. Trying to decide how I want to tackle those scenarios.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -56,25 +61,27 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Page Content -->
|
<!-- Page Content -->
|
||||||
<main class="mb-auto mt-4">
|
<main class="mt-4 mb-auto">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<footer class="bg-gray-800 shadow bottom-0 mt-4">
|
<footer class="bottom-0 mt-4 bg-gray-800 shadow">
|
||||||
<div class="max-w-full mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
<div class="max-w-full px-4 py-6 mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="flex justify-between items-center">
|
<div class="flex items-center justify-between">
|
||||||
<div class="text-sm text-gray-500 dark:text-gray-400">
|
<div class="text-sm text-gray-500 dark:text-gray-400">
|
||||||
<p>TraceDash — v0.0.3 [Pre-Alpha Early Access™]</p>
|
<p>TraceDash — v0.0.4 [Pre-Alpha Early Access™]</p>
|
||||||
<p>Powered by an unhealthy amount of caffeine</p>
|
<p>Powered by an unhealthy amount of caffeine</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="text-sm text-gray-500 dark:text-gray-400 text-right">
|
<div class="text-sm text-right text-gray-500 dark:text-gray-400">
|
||||||
<p>Please send any feedback or bug reports to @Decicus on Discord</p>
|
<p>Please send any feedback or bug reports to @Decicus on Discord</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@yield('scripts')
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -14,15 +14,15 @@
|
|||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
@vite(['resources/css/app.css', 'resources/js/app.js'])
|
||||||
</head>
|
</head>
|
||||||
<body class="font-sans text-gray-900 antialiased">
|
<body class="font-sans antialiased text-gray-900">
|
||||||
<div class="min-h-screen flex flex-col sm:justify-center items-center pt-6 sm:pt-0 bg-gray-100 dark:bg-gray-900">
|
<div class="flex flex-col items-center min-h-screen pt-6 bg-gray-100 sm:justify-center sm:pt-0 dark:bg-gray-900">
|
||||||
<div>
|
<div>
|
||||||
<a href="/" wire:navigate>
|
<a href="/" wire:navigate>
|
||||||
<x-application-logo class="w-20 h-20 fill-current text-gray-500" />
|
<x-application-logo class="w-20 h-20 text-gray-500 fill-current" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white dark:bg-gray-800 shadow-md overflow-hidden sm:rounded-lg">
|
<div class="w-full px-6 py-4 mt-6 overflow-hidden bg-white shadow-md sm:max-w-md dark:bg-gray-800 sm:rounded-lg">
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
<nav x-data="{ open: false }" class="bg-white dark:bg-gray-800 border-b border-gray-100 dark:border-gray-700">
|
<nav x-data="{ open: false }" class="bg-white border-b border-gray-100 dark:bg-gray-800 dark:border-gray-700">
|
||||||
<!-- Primary Navigation Menu -->
|
<!-- Primary Navigation Menu -->
|
||||||
<div class="max-w-full mx-auto px-4 sm:px-6 lg:px-8">
|
<div class="max-w-full px-4 mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="flex justify-between h-16">
|
<div class="flex justify-between h-16">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
<!-- Logo -->
|
<!-- Logo -->
|
||||||
<div class="shrink-0 flex items-center">
|
<div class="flex items-center shrink-0">
|
||||||
<a href="{{ route('dashboard') }}">
|
<a href="{{ route('dashboard') }}">
|
||||||
<x-application-logo class="block h-9 w-auto fill-current text-gray-800 dark:text-gray-200" />
|
<x-application-logo class="block w-auto text-gray-800 fill-current h-9 dark:text-gray-200" />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -23,12 +23,12 @@
|
|||||||
<div class="hidden sm:flex sm:items-center sm:ms-6">
|
<div class="hidden sm:flex sm:items-center sm:ms-6">
|
||||||
<x-dropdown align="right" width="48">
|
<x-dropdown align="right" width="48">
|
||||||
<x-slot name="trigger">
|
<x-slot name="trigger">
|
||||||
<button class="inline-flex items-center px-3 py-2 border border-transparent text-sm leading-4 font-medium rounded-md text-gray-500 dark:text-gray-400 bg-white dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none transition ease-in-out duration-150">
|
<button class="inline-flex items-center px-3 py-2 text-sm font-medium leading-4 text-gray-500 transition duration-150 ease-in-out bg-white border border-transparent rounded-md dark:text-gray-400 dark:bg-gray-800 hover:text-gray-700 dark:hover:text-gray-300 focus:outline-none">
|
||||||
<img src="{{ Auth::user()->avatar }}" class="h-6 w-6 rounded-full" alt="{{ Auth::user()->display_name }}" />
|
<img src="{{ Auth::user()->avatar }}" class="w-6 h-6 rounded-full" alt="{{ Auth::user()->display_name }}" />
|
||||||
<div class="ml-2">{{ Auth::user()->display_name }}</div>
|
<div class="ml-2">{{ Auth::user()->display_name }}</div>
|
||||||
|
|
||||||
<div class="ms-1">
|
<div class="ms-1">
|
||||||
<svg class="fill-current h-4 w-4" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
<svg class="w-4 h-4 fill-current" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 20 20">
|
||||||
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
<path fill-rule="evenodd" d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z" clip-rule="evenodd" />
|
||||||
</svg>
|
</svg>
|
||||||
</div>
|
</div>
|
||||||
@ -52,9 +52,9 @@
|
|||||||
@endif
|
@endif
|
||||||
|
|
||||||
<!-- Hamburger -->
|
<!-- Hamburger -->
|
||||||
<div class="-me-2 flex items-center sm:hidden">
|
<div class="flex items-center -me-2 sm:hidden">
|
||||||
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400 transition duration-150 ease-in-out">
|
<button @click="open = ! open" class="inline-flex items-center justify-center p-2 text-gray-400 transition duration-150 ease-in-out rounded-md dark:text-gray-500 hover:text-gray-500 dark:hover:text-gray-400 hover:bg-gray-100 dark:hover:bg-gray-900 focus:outline-none focus:bg-gray-100 dark:focus:bg-gray-900 focus:text-gray-500 dark:focus:text-gray-400">
|
||||||
<svg class="h-6 w-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
<svg class="w-6 h-6" stroke="currentColor" fill="none" viewBox="0 0 24 24">
|
||||||
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
<path :class="{'hidden': open, 'inline-flex': ! open }" class="inline-flex" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
|
||||||
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
<path :class="{'hidden': ! open, 'inline-flex': open }" class="hidden" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
|
||||||
</svg>
|
</svg>
|
||||||
@ -75,7 +75,7 @@
|
|||||||
<!-- Responsive Settings Options -->
|
<!-- Responsive Settings Options -->
|
||||||
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
<div class="pt-4 pb-1 border-t border-gray-200 dark:border-gray-600">
|
||||||
<div class="px-4">
|
<div class="px-4">
|
||||||
<div class="font-medium text-base text-gray-800 dark:text-gray-200">{{ Auth::user()->display_name }}</div>
|
<div class="text-base font-medium text-gray-800 dark:text-gray-200">{{ Auth::user()->display_name }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-3 space-y-1">
|
<div class="mt-3 space-y-1">
|
||||||
|
@ -1,27 +1,43 @@
|
|||||||
<x-app-layout>
|
<x-app-layout>
|
||||||
<x-slot name="header">
|
<x-slot name="header">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||||
{{ __('Viewer Details') }}
|
{{ __('Viewer Details') }}
|
||||||
</h2>
|
</h2>
|
||||||
</x-slot>
|
</x-slot>
|
||||||
|
|
||||||
<div class="max-w-full mx-auto sm:px-6 lg:px-8">
|
<div class="max-w-full mx-auto sm:px-6 lg:px-8">
|
||||||
<div class="bg-white dark:bg-gray-800 overflow-hidden shadow-sm sm:rounded-lg">
|
<div class="overflow-hidden bg-white shadow-sm dark:bg-gray-800 sm:rounded-lg">
|
||||||
<div class="p-6 text-gray-900 dark:text-gray-100">
|
<div class="p-6 text-gray-900 dark:text-gray-100">
|
||||||
<h2 class="font-semibold text-xl text-gray-800 dark:text-gray-200 leading-tight">
|
<h2 class="text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">
|
||||||
Viewer details for: {{ $username }} [{{ $id }}]
|
Viewer details for: {{ $username }} [{{ $id }}]
|
||||||
</h2>
|
</h2>
|
||||||
|
|
||||||
<p class="mt-4">Seen under the following usernames:</p>
|
@if (!empty($messages))
|
||||||
|
<p class="mt-6">Seen under the following usernames:</p>
|
||||||
|
<ul class="mt-2 list-disc list-inside">
|
||||||
|
@foreach ($messages as $username => $message)
|
||||||
|
<li class="mt-1">
|
||||||
|
{{ $username }} <span class="text-gray-400">— Last seen with this username: {{ date('Y-m-d', strtotime($message->timestamp)) }}</span>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@endif
|
||||||
|
|
||||||
<!-- List style dots -->
|
@if ($actions->isNotEmpty())
|
||||||
<ul class="mt-2 list-disc list-inside">
|
<h2 class="mt-6 text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200">Moderator actions</h2>
|
||||||
@foreach ($messages as $username => $message)
|
@include('components.moderator-actions', ['actions' => $actions, 'showChannel' => true])
|
||||||
<li class="mt-1">
|
@endif
|
||||||
{{ $username }} <span class="text-gray-400">— Last seen with this username: {{ date('Y-m-d', strtotime($message->timestamp)) }}</span>
|
|
||||||
</li>
|
@if ($channels->isNotEmpty())
|
||||||
@endforeach
|
<h2 class="mt-6 text-xl font-semibold leading-tight text-gray-800 dark:text-gray-200"><i class="fab fa-twitch fa-1x"></i> Twitch viewer cards in these channels:</h2>
|
||||||
</ul>
|
<ul class="mt-2 list-disc list-inside">
|
||||||
|
@foreach ($channels as $channel)
|
||||||
|
<li class="mt-1">
|
||||||
|
<a href="https://www.twitch.tv/popout/{{ $channel->username() }}/viewercard/{{ $username }}" target="_blank" class="text-amber-400">{{ $channel->username() }}</a>
|
||||||
|
</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user