Added new tab components for projects management
This commit is contained in:
parent
fc6edb2444
commit
279bd3ec1a
|
|
@ -12,9 +12,13 @@ public function index()
|
|||
return view('projects.index');
|
||||
}
|
||||
|
||||
public function show(Project $project,?string $currentTab = null)
|
||||
public function show(string $projectName,?string $currentTab = null)
|
||||
{
|
||||
return $currentTab ? view('projects.show', compact(['project', 'currentTab'])) : redirect(route('project.show', [$project->id, 'download']));
|
||||
if($project = Project::firstWhere('name',$projectName)) {
|
||||
$availableTabs = ['downloads', 'mosaics', 'reports', 'mailings', 'settings'];
|
||||
return in_array($currentTab, $availableTabs) ? view('projects.show', compact(['project', 'currentTab'])) : redirect(route('project.show', [$projectName, 'downloads']));
|
||||
}
|
||||
return abort(404);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
19
laravel_app/app/Livewire/Projects/Menu.php
Normal file
19
laravel_app/app/Livewire/Projects/Menu.php
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class Menu extends Component
|
||||
{
|
||||
public string $activeTab = "downloads";
|
||||
public string $projectName = '';
|
||||
public function mount()
|
||||
{
|
||||
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.projects.menu');
|
||||
}
|
||||
}
|
||||
84
laravel_app/app/Livewire/Projects/Tabs/Mailings.php
Normal file
84
laravel_app/app/Livewire/Projects/Tabs/Mailings.php
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects\Tabs;
|
||||
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectMailing;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class Mailings extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
public $project;
|
||||
public $mailingDetailsModal = false;
|
||||
|
||||
public $formData = [
|
||||
|
||||
];
|
||||
|
||||
public $search = '';
|
||||
|
||||
public $active_mailing = null;
|
||||
public function mount(Project $project)
|
||||
{
|
||||
$this->project = $project;
|
||||
$this->resetFormData();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function showMailingDetailsModal(ProjectMailing $mailing)
|
||||
{
|
||||
$this->formData = $mailing->toArray();
|
||||
$this->formData['attachments'] = $mailing->attachments->toArray();
|
||||
|
||||
$this->formData['recipients'] = $mailing->recipients->toArray();
|
||||
$this->mailingDetailsModal = true;
|
||||
}
|
||||
|
||||
public function closeMailingDetailsModal()
|
||||
{
|
||||
$this->mailingDetailsModal = false;
|
||||
$this->resetFormData();
|
||||
}
|
||||
|
||||
private function resetFormData()
|
||||
{
|
||||
$this->formData = [
|
||||
'subject' => '',
|
||||
'message' => '',
|
||||
'created_at' => '',
|
||||
'attachments' => [],
|
||||
'recipients' => [],
|
||||
];
|
||||
}
|
||||
|
||||
private function applySearch($query)
|
||||
{
|
||||
if ($this->search) {
|
||||
$query->where('subject', 'like', '%'.$this->search.'%');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function placeholder()
|
||||
{
|
||||
return view('livewire.projects.mailing-manager-placeholder');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$query = $this->project
|
||||
->mailings()
|
||||
->orderBy('created_at', 'desc');
|
||||
|
||||
$query = $this->applySearch($query);
|
||||
|
||||
$mailings = $query->paginate(10, pageName: 'mailingPage');
|
||||
return view('livewire.projects.tabs.mailings', [
|
||||
'mailings' => $mailings,
|
||||
]);
|
||||
}
|
||||
}
|
||||
100
laravel_app/app/Livewire/Projects/Tabs/Mosaic.php
Normal file
100
laravel_app/app/Livewire/Projects/Tabs/Mosaic.php
Normal file
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects\Tabs;
|
||||
|
||||
use App\Jobs\ProjectMosiacGeneratorJob;
|
||||
use App\Models\Project;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class Mosaic extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
public $project;
|
||||
|
||||
public $formData = [
|
||||
'week' => '',
|
||||
'year' => '',
|
||||
];
|
||||
public $showCreateModal = false;
|
||||
|
||||
public $search = "";
|
||||
|
||||
public function mount(Project $project)
|
||||
{
|
||||
$this->path = $project->download_path;
|
||||
}
|
||||
public function saveMosaic()
|
||||
{
|
||||
$this->validate([
|
||||
'formData.year' => 'required',
|
||||
'formData.week' => 'required',
|
||||
]);
|
||||
|
||||
$mosaic = $this->project->mosaics()->updateOrCreate([
|
||||
'name' => sprintf('Week %s, %s', $this->formData['week'], $this->formData['year']),
|
||||
'year' => $this->formData['year'],
|
||||
'week' => $this->formData['week'],
|
||||
], [
|
||||
'path' => $this->project->getMosaicPath(),
|
||||
]);
|
||||
|
||||
ProjectMosiacGeneratorJob::dispatch($mosaic);
|
||||
|
||||
$this->showCreateModal = false;
|
||||
}
|
||||
|
||||
public function openCreateMosiacsModal()
|
||||
{
|
||||
$this->showCreateModal = true;
|
||||
}
|
||||
|
||||
public function getDateRangeProperty()
|
||||
{
|
||||
if (empty($this->formData['week']) || strlen($this->formData['year']) !== 4) {
|
||||
return '<span class="text-red-500">Invalid week or year</span>';
|
||||
}
|
||||
$begin = now()
|
||||
->setISODate($this->formData['year'], $this->formData['week'])
|
||||
->startOfWeek();
|
||||
$end = now()
|
||||
->setISODate($this->formData['year'], $this->formData['week'])
|
||||
->endOfWeek();
|
||||
return $begin->format('Y-m-d').' - '.$end->format('Y-m-d');
|
||||
}
|
||||
|
||||
private function applySearch($query)
|
||||
{
|
||||
if ($this->search) {
|
||||
$query->where('name', 'like', '%' . $this->search . '%');
|
||||
$query->orWhere('year', 'like', '%' . $this->search . '%');
|
||||
$query->orWhere('week', 'like', '%' . $this->search . '%');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function update($property)
|
||||
{
|
||||
if ($property === 'search') {
|
||||
$this->resetPage('mosaicPage');
|
||||
}
|
||||
}
|
||||
public function placeholder()
|
||||
{
|
||||
return view('livewire.projects.mosaic-manager-placeholder');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$query = $this->project->mosaics()
|
||||
->orderBy('year', 'desc')
|
||||
->orderBy('week', 'desc');
|
||||
$query = $this->applySearch($query);
|
||||
$mosaics = $query->paginate(10, pageName: 'mosaicPage');
|
||||
|
||||
return view('livewire.projects.tabs.mosaic', [
|
||||
'mosaics' => $mosaics
|
||||
]);
|
||||
}
|
||||
}
|
||||
107
laravel_app/app/Livewire/Projects/Tabs/Report.php
Normal file
107
laravel_app/app/Livewire/Projects/Tabs/Report.php
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
<?php
|
||||
|
||||
namespace App\Livewire\Projects\Tabs;
|
||||
|
||||
use App\Jobs\ProjectReportGeneratorJob;
|
||||
use App\Models\Project;
|
||||
use App\Models\ProjectReport;
|
||||
use App\Rules\AllMosaicsPresentRule;
|
||||
use Livewire\Component;
|
||||
use Livewire\WithPagination;
|
||||
|
||||
class Report extends Component
|
||||
{
|
||||
use WithPagination;
|
||||
|
||||
public $formData = [];
|
||||
public $project_id;
|
||||
|
||||
public $search = "";
|
||||
|
||||
public $showReportModal = false;
|
||||
|
||||
public $listeners = ['refresh' => '$refresh'];
|
||||
|
||||
public function openCreateReportModal()
|
||||
{
|
||||
$this->resetFormData();
|
||||
$this->showReportModal = true;
|
||||
}
|
||||
private function resetFormData()
|
||||
{
|
||||
$this->formData['week'] = now()->weekOfYear;
|
||||
$this->formData['year'] = now()->year;
|
||||
}
|
||||
|
||||
public function saveProjectReport()
|
||||
{
|
||||
$this->validate([
|
||||
'formData.week' => ['required', 'integer', 'min:1', 'max:53'],
|
||||
'formData.year' => 'required|integer|min:2020|max:'.now()->addYear()->year,
|
||||
'formData' => [new AllMosaicsPresentRule($this->project_id)],
|
||||
]);
|
||||
|
||||
$newReport = Project::find($this->project_id)
|
||||
->reports()->create([
|
||||
'name' => 'Report for week '.$this->formData['week'].' of '.$this->formData['year'],
|
||||
'week' => $this->formData['week'],
|
||||
'year' => $this->formData['year'],
|
||||
'path' => 'reports/week_'.$this->formData['week'].'_'.$this->formData['year'].'.docx',
|
||||
]);
|
||||
|
||||
ProjectReportGeneratorJob::dispatch($newReport);
|
||||
$this->dispatch('refresh');
|
||||
|
||||
$this->showReportModal = false;
|
||||
|
||||
}
|
||||
|
||||
public function getDateRangeProperty()
|
||||
{
|
||||
if (empty($this->formData['week']) || strlen($this->formData['year']) !== 4) {
|
||||
return '<span class="text-red-500">Invalid week or year</span>';
|
||||
}
|
||||
// @TODO dit moet gecorrigeerd voor de project settings;
|
||||
$begin = now()
|
||||
->setISODate($this->formData['year'], $this->formData['week'])
|
||||
->startOfWeek();
|
||||
$end = now()
|
||||
->setISODate($this->formData['year'], $this->formData['week'])
|
||||
->endOfWeek();
|
||||
return $begin->format('Y-m-d').' - '.$end->format('Y-m-d');
|
||||
}
|
||||
|
||||
public function deleteReport(ProjectReport $report)
|
||||
{
|
||||
$report->deleteMe();
|
||||
$this->dispatch('refresh');
|
||||
}
|
||||
|
||||
private function applySearch($query)
|
||||
{
|
||||
if ($this->search) {
|
||||
$query->where('name', 'like', '%'.$this->search.'%');
|
||||
$query->orWhere('year', 'like', '%'.$this->search.'%');
|
||||
$query->orWhere('week', 'like', '%'.$this->search.'%');
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function placeholder()
|
||||
{
|
||||
return view('livewire.projects.report-manager-placeholder');
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
$query = Project::find($this->project_id)
|
||||
->reports()
|
||||
->orderBy('year', 'desc')
|
||||
->orderBy('week', 'desc');
|
||||
$query = $this->applySearch($query);
|
||||
$reports = $query->paginate(10, pageName: 'reportPage');
|
||||
|
||||
return view('livewire.projects.tabs.report')
|
||||
->with(compact('reports'));
|
||||
}
|
||||
}
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
@foreach ($projectManager->projects->sortBy('name') as $project)
|
||||
<div class="flex items-center justify-between">
|
||||
<div class="break-all">
|
||||
<a href="{!! route('project.show', $project->id) !!}">{{ $project->name }}</a>
|
||||
<a href="{!! route('project.show', $project->name) !!}">{{ $project->name }}</a>
|
||||
</div>
|
||||
<div class="flex items-center ml-2">
|
||||
<button class="cursor-pointer ml-6 text-sm text-gray-500"
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<div
|
||||
@if($project->hasPendingDownload())
|
||||
wire:poll.1s=""
|
||||
@endif
|
||||
{{-- @if($project->hasPendingDownload())--}}
|
||||
{{-- wire:poll.1s=""--}}
|
||||
{{-- @endif--}}
|
||||
>
|
||||
<div class="px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:flex-col sm:items-center">
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
<div class="flex flex-col w-fit bg-white gap-2 p-6 rounded-lg shadow">
|
||||
<a class="text-center uppercase tracking-widest font-semibold text-sm hover:bg-indigo-500 hover:text-white px-4 py-2 rounded-lg {{!($activeTab == 'downloads') ?: 'bg-indigo-600 text-white'}}" href="{{route('project.show',[$projectName,'downloads'])}}">Downloads</a>
|
||||
<a class="text-center uppercase tracking-widest font-semibold text-sm hover:bg-indigo-500 hover:text-white px-4 py-2 rounded-lg {{!($activeTab == 'mosaics') ?: 'bg-indigo-600 text-white'}}" href="{{route('project.show',[$projectName,'mosaics'])}}">Mosaics</a>
|
||||
<a class="text-center uppercase tracking-widest font-semibold text-sm hover:bg-indigo-500 hover:text-white px-4 py-2 rounded-lg {{!($activeTab == 'reports') ?: 'bg-indigo-600 text-white'}}" href="{{route('project.show',[$projectName,'reports'])}}">Reports</a>
|
||||
<a class="text-center uppercase tracking-widest font-semibold text-sm hover:bg-indigo-500 hover:text-white px-4 py-2 rounded-lg {{!($activeTab == 'mailings') ?: 'bg-indigo-600 text-white' }}" href="{{route('project.show',[$projectName,'mailings'])}}">Mailings</a>
|
||||
</div>
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
<div>
|
||||
<div class="px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:flex-col sm:items-center">
|
||||
<div class="w-full">
|
||||
<h1 class="text-base font-semibold leading-6 text-gray-900">{{ __('Mailing') }}</h1>
|
||||
<p class="mt-2 text-sm text-gray-700"></p>
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0 sm:flex sm:justify-between w-full">
|
||||
<x-search></x-search>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 ">
|
||||
<div class="overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div class="inline-block min-w-full py-2 align-middle mb-10">
|
||||
<div class="">
|
||||
<table class="min-w-full divide-y divide-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8">
|
||||
Id
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8">@lang('Subject')</th>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8">@lang('Status')</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">#</th>
|
||||
<th scope="col"
|
||||
class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">@lang('Attachment')
|
||||
</th>
|
||||
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-0">
|
||||
<span class="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200">
|
||||
@foreach($mailings as $mail)
|
||||
<tr>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8">{{ $mail->id }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->subject }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
<x-badge :status="$mail->status"></x-badge>
|
||||
</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->recipients()->count() }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">{{ $mail->attachments()->pluck('name')->join( ', ') }}</td>
|
||||
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-0">
|
||||
<button type="button" wire:click="showMailingDetailsModal({{ $mail->id }})"
|
||||
class="text-indigo-600 hover:text-indigo-900">Show
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="absolute inset-0 bg-white opacity-75" wire:loading></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="pt-4 flex justify-between items-center">
|
||||
<div class="text-gray-700 text-sm">
|
||||
Results: {{ \Illuminate\Support\Number::format($mailings->total()) }}
|
||||
</div>
|
||||
|
||||
{{ $mailings->links('livewire.pagination') }}
|
||||
</div>
|
||||
|
||||
|
||||
<x-modal wire:model.live="mailingDetailsModal">
|
||||
<x-form-modal submit="saveProject">
|
||||
<x-slot name="title">
|
||||
{{ __('Mailing') }}
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="description">
|
||||
<x-label for="created_at" value="{{ __('Created') }}"/>
|
||||
<x-label id="created_at"
|
||||
value="{{ \Carbon\Carbon::parse($formData['created_at'])->format('Y-m-d H:i') }}"/>
|
||||
</x-slot>
|
||||
|
||||
<x-slot name="form">
|
||||
<div class="col-span-6">
|
||||
<x-label for="recipients" value="{{ __('Recipients') }}"/>
|
||||
@foreach($formData['recipients'] as $key => $recipient)
|
||||
<div class="col-span-6 sm:col-span-4">
|
||||
<x-label class="inline-block" for="recipients"
|
||||
value="{{ $recipient['name'] }}"/>
|
||||
<x-label class="inline-block" for="recipients"
|
||||
value="<{{ $recipient['email'] }}>"/>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<x-label for="subject" value="{{ __('Subject') }}"/>
|
||||
<x-input id="subject" type="text" class="mt-1 block w-full" disabled
|
||||
wire:model="formData.subject"/>
|
||||
</div>
|
||||
<div class="col-span-6">
|
||||
<x-label for="message" value="{{ __('Message') }}"/>
|
||||
<textarea
|
||||
id="message"
|
||||
type="text"
|
||||
class="mt-1 block w-full"
|
||||
wire:model="formData.message"
|
||||
disabled
|
||||
></textarea>
|
||||
</div>
|
||||
@empty($formData['attachments'])
|
||||
<div class="col-span-6">
|
||||
<x-label for="message" value="{{ __('Attachment') }}"/>
|
||||
<x-label class="inline-block" for=""
|
||||
value="{{ __('No attachments where send with this message.') }}"/>
|
||||
</div>
|
||||
@else
|
||||
@foreach($formData['attachments'] as $key => $attachment)
|
||||
<div class="col-span-6">
|
||||
<x-label class="inline-block" for="recipients"
|
||||
value="{{ $attachment['name'] }}"/>
|
||||
</div>
|
||||
@endforeach
|
||||
@endempty
|
||||
</x-slot>
|
||||
<x-slot name="actions">
|
||||
<x-secondary-button class="mr-3"
|
||||
type="button"
|
||||
wire:click="closeMailingDetailsModal"
|
||||
>
|
||||
{{ __('Close') }}
|
||||
</x-secondary-button>
|
||||
</x-slot>
|
||||
</x-form-modal>
|
||||
</x-modal>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
<div
|
||||
@if($project->hasPendingMosaic())
|
||||
wire:poll.1s=""
|
||||
@endif
|
||||
>
|
||||
<div class="px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:flex-col sm:items-center">
|
||||
<div class="flex justify-between w-full my-4">
|
||||
<h1 class="text-base font-semibold leading-6 text-gray-900">Mosaics</h1>
|
||||
@if ($project->hasPendingDownload())
|
||||
<p class="text-base text-gray-700 animate-pulse">
|
||||
Pending mosaics for this project: {{ $project->mosaics()->statusPending()->count() }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0 sm:flex sm:justify-between w-full">
|
||||
<x-search></x-search>
|
||||
<x-button wire:click="openCreateMosiacsModal"
|
||||
class="block 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 Mosaic
|
||||
</x-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 flow-root">
|
||||
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div class="relative">
|
||||
<div class="inline-block min-w-full py-2 align-middle">
|
||||
<table class="min-w-full divide-y divide-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8">
|
||||
Name
|
||||
</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Year-Week
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="px-3 py-3.5 text-right text-sm font-semibold text-gray-900 sm:pr-8 lg:pr-8">
|
||||
Status
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
@foreach($mosaics as $mosaic)
|
||||
<tr>
|
||||
<td class="whitespace-nowrap py-4 pl-4 pr-3 text-sm font-medium text-gray-900 sm:pl-6 lg:pl-8">{{ $mosaic->name }}</td>
|
||||
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
|
||||
{{ $mosaic->year }}-{{ $mosaic->week}}
|
||||
</td>
|
||||
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6 lg:pr-8">
|
||||
<x-badge :status="$mosaic->status"></x-badge>
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pt-4 flex justify-between items-center">
|
||||
<div class="text-gray-700 text-sm">
|
||||
Results: {{ \Illuminate\Support\Number::format($mosaics->total()) }}
|
||||
</div>
|
||||
|
||||
{{ $mosaics->links('livewire.pagination') }}
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-white opacity-75" wire:loading></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<x-mosaic-create-modal :manager="$this"/>
|
||||
</div>
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<div>
|
||||
<div class="px-4 sm:px-6 lg:px-8">
|
||||
<div class="sm:flex sm:flex-col sm:items-center">
|
||||
<div class="w-full">
|
||||
<h1 class="text-base font-semibold leading-6 text-gray-900">Reports</h1>
|
||||
<p class="mt-2 text-sm text-gray-700"></p>
|
||||
</div>
|
||||
<div class="mt-4 sm:mt-0 sm:flex sm:justify-between w-full">
|
||||
<x-search></x-search>
|
||||
<x-button wire:click="openCreateReportModal"
|
||||
class="block 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
|
||||
</x-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-8 flow-root">
|
||||
<div class="-mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
||||
<div class="relative">
|
||||
<div class="inline-block min-w-full py-2 align-middle mb-10">
|
||||
<table class="min-w-full divide-y divide-gray-300">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Created At
|
||||
</th>
|
||||
<th scope="col"
|
||||
class="py-3.5 pl-4 pr-3 text-left text-sm font-semibold text-gray-900 sm:pl-6 lg:pl-8">
|
||||
Name
|
||||
</th>
|
||||
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900">
|
||||
Status
|
||||
</th>
|
||||
<th scope="col" class="relative py-3.5 pl-3 pr-4 sm:pr-6 lg:pr-8">
|
||||
<span class="sr-only">Edit</span>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="divide-y divide-gray-200 bg-white">
|
||||
@foreach($reports as $report)
|
||||
<livewire:projects.report-row :$report :key="$report->id"/>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="pt-4 flex justify-between items-center">
|
||||
<div class="text-gray-700 text-sm">
|
||||
Results: {{ \Illuminate\Support\Number::format($reports->total()) }}
|
||||
</div>
|
||||
|
||||
{{ $reports->links('livewire.pagination') }}
|
||||
</div>
|
||||
<div class="absolute inset-0 bg-white opacity-75" wire:loading></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<x-report-manager-properties-modal :reportManager="$this"/>
|
||||
</div>
|
||||
|
||||
|
|
@ -1,48 +1,29 @@
|
|||
<x-app-layout>
|
||||
<x-slot name="header">
|
||||
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
|
||||
{{ __('Project') }} {{ $project->name }}
|
||||
{{ __('Project') }} {{ $project->name}}
|
||||
</h2>
|
||||
</x-slot>
|
||||
|
||||
<div x-data x-htabs class="flex">
|
||||
<div x-tabs:list class="-mr-px flex items-stretch flex-col">
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="downloads"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Downloads') }}</button>
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="mosaics"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Mosaics') }}</button>
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="reports"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Reports') }}</button>
|
||||
<button x-tabs:tab type="button"
|
||||
data-tab-name="mailing"
|
||||
:class="$tab.isSelected ? 'border-gray-200 bg-white' : 'border-transparent'"
|
||||
class="inline-flex rounded-l-md border-t border-l border-b px-5 py-2.5"
|
||||
>{{ __('Mailings') }}</button>
|
||||
|
||||
<div id="main" class="flex">
|
||||
<livewire:projects.menu :project-name="$project->name" :active-tab="$currentTab"></livewire:projects.menu>
|
||||
<div class="flex-1 p-4 ml-2 rounded-lg bg-white shadow">
|
||||
@switch($currentTab)
|
||||
@case('downloads')
|
||||
<livewire:projects.tabs.download :project="$project"></livewire:projects.tabs.download>
|
||||
@break
|
||||
@case('mosaics')
|
||||
<livewire:projects.tabs.mosaic :project="$project"></livewire:projects.tabs.mosaic>
|
||||
@break
|
||||
@case('reports')
|
||||
<livewire:projects.tabs.report :project_id="$project->id"></livewire:projects.tabs.report>
|
||||
@break
|
||||
@case('mailings')
|
||||
<livewire:projects.tabs.mailings :project="$project"></livewire:projects.tabs.mailings>
|
||||
@break
|
||||
@default
|
||||
<div class="flex w-full h-screen justify-center items-center"> Menu Component not found.</div>
|
||||
@endswitch
|
||||
</div>
|
||||
|
||||
<div x-tabs:panels class="rounded-b-md border border-gray-200 bg-white w-full">
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.download-manager :project="$project" />
|
||||
</section>
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.mosaic-manager :project="$project" />
|
||||
</section>
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.report-manager :project="$project" />
|
||||
</section>
|
||||
<section x-tabs:panel class="p-8">
|
||||
<livewire:projects.mailing-manager :project="$project" />
|
||||
</section>
|
||||
</div>
|
||||
</div>
|
||||
</x-app-layout>
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@
|
|||
Route::get('/dashboard', function () {
|
||||
return view('dashboard');
|
||||
})->name('dashboard');
|
||||
Route::get('/projects/{project}/{currentTab?}', [\App\Http\Controllers\ProjectController::class, 'show'])->name('project.show');
|
||||
Route::get('/projects/{projectName}/{currentTab?}', [\App\Http\Controllers\ProjectController::class, 'show'])->name('project.show');
|
||||
Route::get('/projects/{projectReport}/download', [\App\Http\Controllers\ProjectReportController::class, 'download'])->name('project.report.download');
|
||||
Route::get('/projects', [\App\Http\Controllers\ProjectController::class, 'index'])->name('project');
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue