Files
Leantime/app/Domain/Tickets/Templates/submodules/ticketHeader.blade.php

125 lines
6.2 KiB
PHP

@php
use Leantime\Core\Controller\Frontcontroller;
use Leantime\Domain\Sprints\Models\Sprints;
$currentUrlPath = BASE_URL . '/' . str_replace('.', '/', Frontcontroller::getCurrentRoute());
$currentSprintId = $currentSprint;
$searchSprint = $searchCriteria['sprint'] ?? '';
$sprint = false;
$currentSprintId = $currentSprintId == '' ? 'all' : $currentSprintId;
if ($currentSprintId == 'all') {
$sprint = new Sprints;
$sprint->id = 'all';
$sprint->name = __('links.all_todos');
}
if ($currentSprintId == 'backlog') {
$sprint = new Sprints;
$sprint->id = 'backlog';
$sprint->name = __('links.backlog');
}
if (is_array($sprints)) {
foreach ($sprints as $sprintRow) {
if ($sprintRow->id == $currentSprintId) {
$sprint = $sprintRow;
break;
}
}
}
@endphp
@dispatchEvent('beforePageHeaderOpen')
<div class="pageheader">
@dispatchEvent('afterPageHeaderOpen')
<div class="pageicon">
<span class="fa fa-fw fa-thumb-tack"></span>
</div>
<div class="pagetitle">
{{-- Build "Client // Project" only from the parts that exist, so a
missing client/project never leaves a stray " // ". (`.` binds
tighter than `??`, so the old inline expression mis-grouped.) --}}
@php
$headerParts = array_filter(
[session('currentProjectClient'), session('currentProjectName')],
fn ($part) => $part !== null && $part !== ''
);
@endphp
<h5>{{ implode(' / ', $headerParts) }}</h5>
{{-- Migrated to the shared subject switcher (was a hand-rolled
header-title-dropdown). The sprint menu items stay here they're
domain-specific — but the "To-Dos // <current> ▾" chrome is now the
component. Zero visual change. --}}
<x-global::subjectSwitcher
:parent="__('headlines.todos')"
:current="$sprint !== false ? $sprint->name : __('dropdown.choose_sprint')">
<li><a class="wikiModal inlineEdit" href="#/sprints/editSprint/"><i class="fa-solid fa-plus"></i> {!! __('links.create_sprint_no_icon') !!}</a></li>
<li class='nav-header border'></li>
<li>
<a href="javascript:void(0);" onclick="jQuery('#sprintSelect').val('all'); leantime.ticketsController.initTicketSearchUrlBuilder('{{ $currentUrlPath }}')">{!! __('links.all_todos') !!}</a>
</li>
<li>
<a href="javascript:void(0);" onclick="jQuery('#sprintSelect').val('backlog'); leantime.ticketsController.initTicketSearchUrlBuilder('{{ $currentUrlPath }}')">{!! __('links.backlog') !!}</a>
</li>
@foreach ($sprints as $sprintRow)
<li>
<a href="javascript:void(0);" onclick="jQuery('#sprintSelect').val({{ $sprintRow->id }}); leantime.ticketsController.initTicketSearchUrlBuilder('{{ $currentUrlPath }}')">{{ $tpl->escape($sprintRow->name) }}@if (! empty($sprintRow->isInherited)) <span class="label label-info">{{ __('label.program_sprint') }}</span>@endif<br /><small>{!! sprintf(__('label.date_from_date_to'), format($sprintRow->startDate)->date(), format($sprintRow->endDate)->date()) !!}</small></a>
</li>
@endforeach
</x-global::subjectSwitcher>
<input type="hidden" name="sprintSelect" id="sprintSelect" value="{{ $currentSprintId }}" />
</div>
{{-- Right cluster on the breadcrumb bar: board stats + (for a real sprint
view only) the sprint edit/delete menu. --}}
<div class="pageheader-right">
{{-- Header rule (2026-08-03): LEFT = orientation (where you are),
RIGHT = information (what about it) meta, then status, then ,
one vertically-centered row. --}}
@isset($boardSummary)
@php
// Board metrics as a one-line meta string; segments join with a
// single " · " so it reads cleanly no matter which are present.
$summaryParts = [sprintf(__('label.board_task_count'), $boardSummary->total)];
if ($boardSummary->unassigned > 0) {
$summaryParts[] = sprintf(__('label.board_unassigned'), $boardSummary->unassigned);
}
if ($boardSummary->dueThisWeek > 0) {
$summaryParts[] = sprintf(__('label.board_due_this_week'), $boardSummary->dueThisWeek);
}
if ($boardSummary->lastUpdated !== null) {
$summaryParts[] = sprintf(__('label.board_updated'), $boardSummary->lastUpdated->setToUserTimezone()->diffForHumans());
}
@endphp
<div class="pageheader-meta">{{ implode(' · ', $summaryParts) }}</div>
@endisset
@if (
($currentSprint !== false)
&& ($currentSprint !== null)
&& count($sprints) > 0
&& $currentSprintId != 'all'
&& $currentSprintId != 'backlog'
)
<span class="dropdown dropdownWrapper headerEditDropdown">
<a href="javascript:void(0)" class="dropdown-toggle btn btn-transparent" data-toggle="dropdown"><i class="fa-solid fa-ellipsis-v"></i></a>
<ul class="dropdown-menu editCanvasDropdown">
{{-- Inherited (program-owned) sprints are managed at the program level, never edited
or deleted from a child project. The service IDOR-fences this server-side too.
$sprint can be false (stale/deleted currentSprint), so guard the object access. --}}
@if ($login::userIsAtLeast($roles::$editor) && (! is_object($sprint) || empty($sprint->isInherited)))
<li><a href="#/sprints/editSprint/{{ $currentSprint }}">{!! __('link.edit_sprint') !!}</a></li>
<li><a href="#/sprints/delSprint/{{ $currentSprint }}" class="delete">{!! __('links.delete_sprint') !!}</a></li>
@endif
</ul>
</span>
@endif
</div>
@dispatchEvent('beforePageHeaderClose')
</div><!--pageheader-->
@dispatchEvent('afterPageHeaderClose')