added role viewer and command to create user viewer updated application to hide components for viewer

This commit is contained in:
Martin Folkerts 2025-06-30 14:49:21 +02:00
parent d4648bdd54
commit e1e359503d
14 changed files with 222 additions and 24 deletions

View file

@ -0,0 +1,19 @@
<?php
namespace App\Casts;
use App\Enums\UserRole;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class RoleCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes)
{
return UserRole::from($value);
}
public function set($model, string $key, $value, array $attributes)
{
return $value instanceof UserRole ? $value->value : $value;
}
}

View file

@ -0,0 +1,60 @@
<?php
namespace App\Console\Commands;
use App\Enums\UserRole;
use App\Models\User;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Hash;
class CreateUser extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'user:create';
/**
* The console command description.
*
* @var string
*/
protected $description = 'maak een nieuwe gebruiker';
/**
* Execute the console command.
*/
public function handle(): int
{
$name = $this->ask('Naam van de gebruiker');
$email = $this->ask('E-mailadres');
$password = $this->secret('Wachtwoord');
$choices = collect(UserRole::cases())->map(fn($role) => $role->label())->toArray();
$names = collect(UserRole::cases())->map(fn($role) => $role->name)->toArray();
$index = $this->choice('Welke rol?', $choices); // string zoals 'Beheerder'
$name = $names[array_search($index, $choices)];
$role = UserRole::tryFromName($name);
if (!$role) {
$this->error("Ongeldige rol opgegeven.");
return Command::FAILURE;
}
$user = User::create([
'name' => $name,
'email' => $email,
'password' => Hash::make($password),
'role' => $role,
]);
$this->info("Gebruiker {$user->email} aangemaakt met rol {$role->name}");
return Command::SUCCESS;
}
}

View file

@ -0,0 +1,29 @@
<?php
namespace App\Enums;
enum UserRole: int {
case Viewer = 100;
case Manager = 200;
public static function tryFromName(string $name): ?self
{
return match (strtolower($name)) {
'manager' => self::Manager,
'viewer' => self::Viewer,
default => null,
};
}
public function label(): string
{
return $this->name;
}
public static function labels(): array
{
return collect(self::cases())->mapWithKeys(function ($role) {
return [$role->value => $role->label()];
})->toArray();
}
}

View file

@ -13,9 +13,12 @@ class DownloadNotification extends Component
// TODO Change session bool to timestamp so i can check if i show it in 5 min. // TODO Change session bool to timestamp so i can check if i show it in 5 min.
public function mount(Project $project) public function mount(Project $project)
{ {
$this->show_download_notification = session()->get('show-download.'.$project->id,$project->hasMissingDownloadsDateInHarvestFile()); if (auth()->user()->hasRole('manager')) {
$this->show_download_notification = session()->get('show-download.'.$project->id,
$project->hasMissingDownloadsDateInHarvestFile());
$this->project = $project; $this->project = $project;
} }
}
public function getSessionKey() public function getSessionKey()
{ {
@ -25,9 +28,11 @@ public function getSessionKey()
#[On('download_notify')] #[On('download_notify')]
public function open() public function open()
{ {
if (auth()->user()->hasRole('manager')) {
$this->show_download_notification = true; $this->show_download_notification = true;
session([$this->getSessionKey() => true]); session([$this->getSessionKey() => true]);
} }
}
public function close(): void public function close(): void
{ {
$this->show_download_notification = false; $this->show_download_notification = false;

View file

@ -3,6 +3,7 @@
namespace App\Models; namespace App\Models;
// use Illuminate\Contracts\Auth\MustVerifyEmail; // use Illuminate\Contracts\Auth\MustVerifyEmail;
use App\Enums\UserRole;
use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable; use Illuminate\Notifications\Notifiable;
@ -28,6 +29,7 @@ class User extends Authenticatable
'name', 'name',
'email', 'email',
'password', 'password',
'role',
]; ];
/** /**
@ -49,6 +51,7 @@ class User extends Authenticatable
*/ */
protected $casts = [ protected $casts = [
'email_verified_at' => 'datetime', 'email_verified_at' => 'datetime',
'role' => UserRole::class,
]; ];
/** /**
@ -59,4 +62,15 @@ class User extends Authenticatable
protected $appends = [ protected $appends = [
'profile_photo_url', 'profile_photo_url',
]; ];
public function hasRole(string|UserRole $role): bool
{
if (is_string($role)) {
$role = UserRole::tryFromName($role); // custom helper zie onder
}
return $this->role === $role;
}
} }

View file

@ -2,6 +2,7 @@
namespace App\Providers; namespace App\Providers;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
@ -19,6 +20,12 @@ public function register(): void
*/ */
public function boot(): void public function boot(): void
{ {
// Blade::if('manager', function () {
return auth()->check() && auth()->user()->hasRole('manager');
});
Blade::if('viewer', function () {
return auth()->check() && auth()->user()->hasRole('viewer');
});
} }
} }

View file

@ -0,0 +1,28 @@
<?php
use App\Enums\UserRole;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('users', function (Blueprint $table) {
$table->integer('role')->default(UserRole::Manager);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('users', function (Blueprint $table) {
$table->dropColumn('role');
});
}
};

View file

@ -1,5 +1,13 @@
<svg viewBox="0 0 317 48" fill="none" xmlns="http://www.w3.org/2000/svg" {{ $attributes }}> <h1 class="mt-8 text-2xl font-medium text-gray-900">
<path d="M74.09 30.04V13h-4.14v21H82.1v-3.96h-8.01zM95.379 19v1.77c-1.08-1.35-2.7-2.19-4.89-2.19-3.99 0-7.29 3.45-7.29 7.92s3.3 7.92 7.29 7.92c2.19 0 3.81-.84 4.89-2.19V34h3.87V19h-3.87zm-4.17 11.73c-2.37 0-4.14-1.71-4.14-4.23 0-2.52 1.77-4.23 4.14-4.23 2.4 0 4.17 1.71 4.17 4.23 0 2.52-1.77 4.23-4.17 4.23zM106.628 21.58V19h-3.87v15h3.87v-7.17c0-3.15 2.55-4.05 4.56-3.81V18.7c-1.89 0-3.78.84-4.56 2.88zM124.295 19v1.77c-1.08-1.35-2.7-2.19-4.89-2.19-3.99 0-7.29 3.45-7.29 7.92s3.3 7.92 7.29 7.92c2.19 0 3.81-.84 4.89-2.19V34h3.87V19h-3.87zm-4.17 11.73c-2.37 0-4.14-1.71-4.14-4.23 0-2.52 1.77-4.23 4.14-4.23 2.4 0 4.17 1.71 4.17 4.23 0 2.52-1.77 4.23-4.17 4.23zM141.544 19l-3.66 10.5-3.63-10.5h-4.26l5.7 15h4.41l5.7-15h-4.26zM150.354 28.09h11.31c.09-.51.15-1.02.15-1.59 0-4.41-3.15-7.92-7.59-7.92-4.71 0-7.92 3.45-7.92 7.92s3.18 7.92 8.22 7.92c2.88 0 5.13-1.17 6.54-3.21l-3.12-1.8c-.66.87-1.86 1.5-3.36 1.5-2.04 0-3.69-.84-4.23-2.82zm-.06-3c.45-1.92 1.86-3.03 3.93-3.03 1.62 0 3.24.87 3.72 3.03h-7.65zM164.516 34h3.87V12.1h-3.87V34zM185.248 34.36c3.69 0 6.9-2.01 6.9-6.3V13h-2.1v15.06c0 3.03-2.07 4.26-4.8 4.26-2.19 0-3.93-.78-4.62-2.61l-1.77 1.05c1.05 2.43 3.57 3.6 6.39 3.6zM203.124 18.64c-4.65 0-7.83 3.45-7.83 7.86 0 4.53 3.24 7.86 7.98 7.86 3.03 0 5.34-1.41 6.6-3.45l-1.74-1.02c-.81 1.44-2.46 2.55-4.83 2.55-3.18 0-5.55-1.89-5.97-4.95h13.17c.03-.3.06-.63.06-.93 0-4.11-2.85-7.92-7.44-7.92zm0 1.92c2.58 0 4.98 1.71 5.4 5.01h-11.19c.39-2.94 2.64-5.01 5.79-5.01zM221.224 20.92V19h-4.32v-4.2l-1.98.6V19h-3.15v1.92h3.15v9.09c0 3.6 2.25 4.59 6.3 3.99v-1.74c-2.91.12-4.32.33-4.32-2.25v-9.09h4.32zM225.176 22.93c0-1.62 1.59-2.37 3.15-2.37 1.44 0 2.97.57 3.6 2.1l1.65-.96c-.87-1.86-2.79-3.06-5.25-3.06-3 0-5.13 1.89-5.13 4.29 0 5.52 8.76 3.39 8.76 7.11 0 1.77-1.68 2.4-3.45 2.4-2.01 0-3.57-.99-4.11-2.52l-1.68.99c.75 1.92 2.79 3.45 5.79 3.45 3.21 0 5.43-1.77 5.43-4.32 0-5.52-8.76-3.39-8.76-7.11zM244.603 20.92V19h-4.32v-4.2l-1.98.6V19h-3.15v1.92h3.15v9.09c0 3.6 2.25 4.59 6.3 3.99v-1.74c-2.91.12-4.32.33-4.32-2.25v-9.09h4.32zM249.883 21.49V19h-1.98v15h1.98v-8.34c0-3.72 2.34-4.98 4.74-4.98v-1.92c-1.92 0-3.69.63-4.74 2.73zM263.358 18.64c-4.65 0-7.83 3.45-7.83 7.86 0 4.53 3.24 7.86 7.98 7.86 3.03 0 5.34-1.41 6.6-3.45l-1.74-1.02c-.81 1.44-2.46 2.55-4.83 2.55-3.18 0-5.55-1.89-5.97-4.95h13.17c.03-.3.06-.63.06-.93 0-4.11-2.85-7.92-7.44-7.92zm0 1.92c2.58 0 4.98 1.71 5.4 5.01h-11.19c.39-2.94 2.64-5.01 5.79-5.01zM286.848 19v2.94c-1.26-2.01-3.39-3.3-6.06-3.3-4.23 0-7.74 3.42-7.74 7.86s3.51 7.86 7.74 7.86c2.67 0 4.8-1.29 6.06-3.3V34h1.98V19h-1.98zm-5.91 13.44c-3.33 0-5.91-2.61-5.91-5.94 0-3.33 2.58-5.94 5.91-5.94s5.91 2.61 5.91 5.94c0 3.33-2.58 5.94-5.91 5.94zM309.01 18.64c-1.92 0-3.75.87-4.86 2.73-.84-1.74-2.46-2.73-4.56-2.73-1.8 0-3.42.72-4.59 2.55V19h-1.98v15H295v-8.31c0-3.72 2.16-5.13 4.32-5.13 2.13 0 3.51 1.41 3.51 4.08V34h1.98v-8.31c0-3.72 1.86-5.13 4.17-5.13 2.13 0 3.66 1.41 3.66 4.08V34h1.98v-9.36c0-3.75-2.31-6-5.61-6z" class="fill-black"/>
<path d="M11.395 44.428C4.557 40.198 0 32.632 0 24 0 10.745 10.745 0 24 0a23.891 23.891 0 0113.997 4.502c-.2 17.907-11.097 33.245-26.602 39.926z" fill="#6875F5"/> @manager
<path d="M14.134 45.885A23.914 23.914 0 0024 48c13.255 0 24-10.745 24-24 0-3.516-.756-6.856-2.115-9.866-4.659 15.143-16.608 27.092-31.75 31.751z" fill="#6875F5"/> Welcome
</svg> @endmanager
@viewer
Hi
@endviewer
{{ auth()->user()->name }} (role: {{ auth()->user()->role->label() }} )
</h1>

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 222 B

View file

@ -10,11 +10,18 @@
</x-slot> </x-slot>
<x-slot name="description"> <x-slot name="description">
@manager
{{ __('You may delete any of your projects if they are no longer needed.') }} {{ __('You may delete any of your projects if they are no longer needed.') }}
@endmanager
@viewer
{{ __('This is a overview of all projects. When mail scheduled it means it will create a report and mail the recipients.') }}
@endviewer
</x-slot> </x-slot>
<x-slot name="content"> <x-slot name="content">
<div class="space-y-6"> <div class="space-y-6">
@manager
<div class="flex flex-auto gap-2" x-data="{showCreateProjectInput:false}"> <div class="flex flex-auto gap-2" x-data="{showCreateProjectInput:false}">
<x-secondary-button x-show="!showCreateProjectInput" @click="showCreateProjectInput = true"> <x-secondary-button x-show="!showCreateProjectInput" @click="showCreateProjectInput = true">
{{ __('Create Project') }} {{ __('Create Project') }}
@ -29,6 +36,10 @@
<x-button class=" h-full" wire:click="createProject">Create</x-button> <x-button class=" h-full" wire:click="createProject">Create</x-button>
</div> </div>
</div> </div>
@endmanager
<div class="grid grid-cols-3 gap-3"> <div class="grid grid-cols-3 gap-3">
<div class="text-sm font-semibold text-gray-900"> <div class="text-sm font-semibold text-gray-900">
Name Name
@ -37,7 +48,9 @@
Mail Scheduled Mail Scheduled
</div> </div>
<div class="text-sm font-semibold text-gray-900"> <div class="text-sm font-semibold text-gray-900">
@manager
Actions Actions
@endmanager
</div> </div>
@foreach ($projectManager->projects->sortBy('name') as $project) @foreach ($projectManager->projects->sortBy('name') as $project)
<div> <div>
@ -50,10 +63,12 @@
{!! $project->mail_scheduled ? 'Yes' : 'No' !!} {!! $project->mail_scheduled ? 'Yes' : 'No' !!}
</div> </div>
<div> <div>
@manager
<button class="cursor-pointer text-sm text-red-500" <button class="cursor-pointer text-sm text-red-500"
wire:click="confirmReportDeletion({{ $project->id }})"> wire:click="confirmReportDeletion({{ $project->id }})">
<x-icon.trash/> <x-icon.trash/>
</button> </button>
@endmanager
</div> </div>
@endforeach @endforeach

View file

@ -3,7 +3,9 @@
<a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'mosaics') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'mosaics'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fg-mosaic fg-lg"></i>Mosaics</a> <a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'mosaics') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'mosaics'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fg-mosaic fg-lg"></i>Mosaics</a>
<a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'reports') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'reports'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fg-map-stat fg-lg"></i>Reports</a> <a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'reports') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'reports'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fg-map-stat fg-lg"></i>Reports</a>
<a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'mailings') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'mailings'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-regular fa-envelope"></i>Mailings</a> <a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'mailings') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'mailings'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-regular fa-envelope"></i>Mailings</a>
@manager
<a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'settings') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'settings'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-solid fa-gear"></i>Settings</a> <a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'settings') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'settings'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-solid fa-gear"></i>Settings</a>
<a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'exports') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'exports'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-solid fa-download"></i>Exports</a> <a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'exports') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'exports'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-solid fa-download"></i>Exports</a>
<a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'logs') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'logs'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-solid fa-regular fa-file"></i>Logs</a> <a class=" capitalize font-semibold text-md hover:rounded-lg hover:bg-gray-50 hover:text-indigo-600 hover:border-0 py-2 pl-2 pr-3 leading-6 whitespace-nowrap gap-2 flex items-baseline group text-gray-700 {{!($activeTab == 'logs') ?: 'rounded-lg bg-gray-50 text-indigo-600 border-0'}}" href="{{route('project.show',[$projectName,'logs'])}}"><i class="group-hover:text-indigo-600 w-6 text-gray-400 fa-solid fa-regular fa-file"></i>Logs</a>
@endmanager
</div> </div>

View file

@ -11,7 +11,7 @@
wire:key="{{$report->id}}"></livewire:components.badge> wire:key="{{$report->id}}"></livewire:components.badge>
</td> </td>
<td class="py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8 flex justify-end"> <td class="py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8 flex justify-end">
@manager
<x-menu> <x-menu>
<x-menu.button> <x-menu.button>
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5" <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="1.5"
@ -198,6 +198,7 @@ class="text-center rounded-xl bg-slate-300 text-slate-800 px-6 py-2 font-semibol
</x-dialog> </x-dialog>
</x-menu.items> </x-menu.items>
</x-menu> </x-menu>
@endmanager
</td> </td>
</tr> </tr>

View file

@ -8,10 +8,12 @@
</div> </div>
<div class="flex flex-col md:flex-row mt-4 items-center md:justify-between w-full gap-2"> <div class="flex flex-col md:flex-row mt-4 items-center md:justify-between w-full gap-2">
<x-search class="flex-1 w-full"></x-search> <x-search class="flex-1 w-full"></x-search>
@manager
<x-button wire:click="openDownloadModal" <x-button wire:click="openDownloadModal"
class="rounded-md bg-indigo-600 px-3 py-2 justify-center text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"> class="rounded-md bg-indigo-600 px-3 py-2 justify-center text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
{{ __('Create Download') }} {{ __('Create Download') }}
</x-button> </x-button>
@endmanager
</div> </div>
</div> </div>
<div class="mt-8 flow-root"> <div class="mt-8 flow-root">
@ -65,6 +67,8 @@ class="px-3 py-3.5 text-right pr-4 sm:pr-8 lg:pr-8 text-sm font-semibold text-gr
</div> </div>
</div> </div>
</div> </div>
@manager
<x-download-create-modal :manager="$this"/> <x-download-create-modal :manager="$this"/>
@endmanager
</div> </div>

View file

@ -7,10 +7,12 @@
</div> </div>
<div class="flex flex-col md:flex-row mt-4 items-center md:justify-between w-full gap-2"> <div class="flex flex-col md:flex-row mt-4 items-center md:justify-between w-full gap-2">
<x-search class="flex-1 w-full"></x-search> <x-search class="flex-1 w-full"></x-search>
@manager
<x-button wire:click="openCreateMosiacsModal" <x-button wire:click="openCreateMosiacsModal"
class="justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"> class="justify-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
Create Mosaic Create Mosaic
</x-button> </x-button>
@endmanager
</div> </div>
</div> </div>
<div class="mt-8 flow-root"> <div class="mt-8 flow-root">

View file

@ -12,10 +12,12 @@
class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50"> class="inline-flex items-center rounded-md bg-white px-3 py-2 text-sm font-semibold text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 hover:bg-gray-50">
Create Test Report Create Test Report
</button> </button>
@manager
<x-button wire:click="openCreateReportModal" <x-button wire:click="openCreateReportModal"
class="flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600"> class="flex justify-center rounded-md bg-indigo-600 px-3 py-2 text-center text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
Create Report Create Report
</x-button> </x-button>
@endmanager
</div> </div>
</div> </div>
@ -63,7 +65,9 @@ class="py-3.5 pl-3 pr-4 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg
</div> </div>
</div> </div>
</div> </div>
@manager
<x-report-manager-properties-modal :reportManager="$this"/> <x-report-manager-properties-modal :reportManager="$this"/>
<x-report-manager-test-report-modal :reportManager="$this"/> <x-report-manager-test-report-modal :reportManager="$this"/>
@endmanager
</div> </div>