diff --git a/.idea/leantime-oss.iml b/.idea/leantime-oss.iml
index fc8d27cf07..65dc0d0f04 100644
--- a/.idea/leantime-oss.iml
+++ b/.idea/leantime-oss.iml
@@ -120,8 +120,9 @@
+ __('label.incremental_ticket_id_description'); echo $incDesc === 'label.incremental_ticket_id_description' ? 'Incremental ticket numbering (1, 2, 3...) for this project. When disabled, tickets use a different ID scheme.' : $incDesc; ?> +
+
diff --git a/app/Domain/Tickets/Models/Tickets.php b/app/Domain/Tickets/Models/Tickets.php
index 20dae33c77..443ecf809b 100644
--- a/app/Domain/Tickets/Models/Tickets.php
+++ b/app/Domain/Tickets/Models/Tickets.php
@@ -68,6 +68,10 @@ class Tickets
public ?string $projectKey = null;
+ public mixed $incrementalTicketId = null;
+
+ public mixed $projectTicketNumber = null;
+
public ?string $clientName = '';
public ?string $userFirstname = '';
@@ -125,6 +129,8 @@ public function __construct(array|bool $values = false)
$this->milestoneid = $values['milestoneid'] ?? '';
$this->projectName = $values['projectName'] ?? '';
$this->projectKey = $values['projectKey'] ?? null;
+ $this->incrementalTicketId = $values['incrementalTicketId'] ?? null;
+ $this->projectTicketNumber = $values['projectTicketNumber'] ?? null;
$this->clientName = $values['clientName'] ?? '';
$this->userFirstname = $values['userFirstname'] ?? '';
$this->userLastname = $values['userLastname'] ?? '';
diff --git a/app/Domain/Tickets/Repositories/Tickets.php b/app/Domain/Tickets/Repositories/Tickets.php
index 5e9f5b7469..115e21c27f 100644
--- a/app/Domain/Tickets/Repositories/Tickets.php
+++ b/app/Domain/Tickets/Repositories/Tickets.php
@@ -30,6 +30,7 @@ class Tickets
'statusType' => 'NEW',
'kanbanCol' => true,
'sortKey' => 1,
+ 'slackNotify' => false,
],
1 => [
'name' => 'status.blocked',
@@ -37,6 +38,7 @@ class Tickets
'statusType' => 'INPROGRESS',
'kanbanCol' => true,
'sortKey' => 2,
+ 'slackNotify' => false,
],
4 => [
'name' => 'status.in_progress',
@@ -44,6 +46,7 @@ class Tickets
'statusType' => 'INPROGRESS',
'kanbanCol' => true,
'sortKey' => 3,
+ 'slackNotify' => false,
],
2 => [
'name' => 'status.waiting_for_approval',
@@ -51,6 +54,7 @@ class Tickets
'statusType' => 'INPROGRESS',
'kanbanCol' => true,
'sortKey' => 4,
+ 'slackNotify' => false,
],
0 => [
'name' => 'status.done',
@@ -58,6 +62,7 @@ class Tickets
'statusType' => 'DONE',
'kanbanCol' => true,
'sortKey' => 5,
+ 'slackNotify' => false,
],
-1 => [
'name' => 'status.archived',
@@ -65,6 +70,7 @@ class Tickets
'statusType' => 'DONE',
'kanbanCol' => false,
'sortKey' => 6,
+ 'slackNotify' => false,
],
];
@@ -156,6 +162,9 @@ public function getStateLabels($projectId = null): array
}
} else {
$statusList[$key] = $status;
+ if (! isset($statusList[$key]['slackNotify'])) {
+ $statusList[$key]['slackNotify'] = false;
+ }
}
}
}
@@ -346,6 +355,8 @@ public function getAllBySearchCriteria(array $searchCriteria, string $sort = 'st
COALESCE(ROUND(timesheet_agg.total_hours, 2), 0) AS bookedHours,
zp_projects.name AS projectName,
zp_projects.projectKey AS projectKey,
+ COALESCE(zp_projects.incrementalTicketId, 1) AS incrementalTicketId,
+ (SELECT COUNT(*) FROM zp_tickets t2 WHERE t2.projectId = zp_tickets.projectId AND t2.id <= zp_tickets.id) AS projectTicketNumber,
zp_clients.name AS clientName,
zp_clients.id AS clientId,
t1.id AS authorId,
@@ -893,6 +904,8 @@ public function getTicket($id): \Leantime\Domain\Tickets\Models\Tickets|bool
milestones.headline AS milestoneHeadline,
zp_projects.name AS projectName,
zp_projects.projectKey AS projectKey,
+ COALESCE(zp_projects.incrementalTicketId, 1) AS incrementalTicketId,
+ (SELECT COUNT(*) FROM zp_tickets t2 WHERE t2.projectId = zp_tickets.projectId AND t2.id <= zp_tickets.id) AS projectTicketNumber,
zp_projects.details AS projectDescription,
zp_clients.name AS clientName,
zp_user.firstname AS userFirstname,
diff --git a/app/Domain/Tickets/Services/Tickets.php b/app/Domain/Tickets/Services/Tickets.php
index 72a15c356f..fad454ed01 100644
--- a/app/Domain/Tickets/Services/Tickets.php
+++ b/app/Domain/Tickets/Services/Tickets.php
@@ -141,6 +141,7 @@ public function saveStatusLabels($params): bool
'statusType' => $params['labelType-'.$labelKey] ?? 'NEW',
'kanbanCol' => $params['labelKanbanCol-'.$labelKey] ?? false,
'sortKey' => $params['labelSort-'.$labelKey] ?? 99,
+ 'slackNotify' => isset($params['labelSlackNotify-'.$labelKey]) && $params['labelSlackNotify-'.$labelKey],
];
}
@@ -714,6 +715,17 @@ public function getAllGrouped($searchCriteria): array
// Sort main groups
switch ($searchCriteria['groupBy']) {
+ case 'editorId':
+ $currentUserId = (string) session('userdata.id');
+ if (isset($ticketGroups[$currentUserId])) {
+ $currentUserGroup = $ticketGroups[$currentUserId];
+ unset($ticketGroups[$currentUserId]);
+ $ticketGroups = array_sort($ticketGroups, 'label');
+ $ticketGroups = [$currentUserId => $currentUserGroup] + $ticketGroups;
+ } else {
+ $ticketGroups = array_sort($ticketGroups, 'label');
+ }
+ break;
case 'status':
case 'priority':
case 'storypoints':
diff --git a/app/Domain/Tickets/Templates/partials/ticketCard.blade.php b/app/Domain/Tickets/Templates/partials/ticketCard.blade.php
index a7dea364cb..a6f315ac1d 100644
--- a/app/Domain/Tickets/Templates/partials/ticketCard.blade.php
+++ b/app/Domain/Tickets/Templates/partials/ticketCard.blade.php
@@ -7,7 +7,11 @@
{{ $row['parentHeadline'] }} //
@endif
@endif
- {{ !empty($row['projectKey']) ? $row['projectKey'] . '-' : '#' }}{{ $row['id'] }}
+ @php
+ $useIncremental = isset($row['incrementalTicketId']) && (int)($row['incrementalTicketId'] ?? 0) === 1;
+ $displayNum = $useIncremental && isset($row['projectTicketNumber']) ? (int)$row['projectTicketNumber'] : $row['id'];
+ $prefix = !empty($row['projectKey']) ? $row['projectKey'] . '-' : '#';
+ @endphp{{ $prefix }}{{ $displayNum }}
@if(isset($row['pinned']) && $row['pinned'])
diff --git a/app/Domain/Tickets/Templates/showAll.tpl.php b/app/Domain/Tickets/Templates/showAll.tpl.php
index df7b025d21..b4eb16e158 100644
--- a/app/Domain/Tickets/Templates/showAll.tpl.php
+++ b/app/Domain/Tickets/Templates/showAll.tpl.php
@@ -136,11 +136,10 @@
dispatchTplEvent('allTicketsTable.afterRowStart', ['rowNum' => $rowNum, 'tickets' => $allTickets]); ?>
escape($row['projectKey']) . '-' . $tpl->escape($row['id']);
- } else {
- echo '#' . $tpl->escape($row['id']);
- }
+ $useIncremental = isset($row['incrementalTicketId']) && (int) $row['incrementalTicketId'] === 1;
+ $displayNum = $useIncremental && isset($row['projectTicketNumber']) ? (int) $row['projectTicketNumber'] : $row['id'];
+ $prefix = !empty($row['projectKey']) ? $tpl->escape($row['projectKey']) . '-' : '#';
+ echo $prefix . $tpl->escape($displayNum);
?>
diff --git a/app/Domain/Tickets/Templates/showKanban.tpl.php b/app/Domain/Tickets/Templates/showKanban.tpl.php
index e1179e54b5..f8667ac10a 100644
--- a/app/Domain/Tickets/Templates/showKanban.tpl.php
+++ b/app/Domain/Tickets/Templates/showKanban.tpl.php
@@ -266,7 +266,12 @@ class="ticketBox moveable container priority-border-= $row['priority']?>"
= $tpl->escape($row['parentHeadline']) ?> //
-
+
@@ -418,8 +423,14 @@ class="ticketBox moveable container priority-border-= $row['priority']?>"
- = count($tagsArray)?>
+
+ htmlspecialchars(trim($tag)), $tags);
+ echo implode(', ', $tags);
+ ?>