OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)
This commit is contained in:
50
app/Domain/Tickets/Hxcontrollers/Milestones.php
Normal file
50
app/Domain/Tickets/Hxcontrollers/Milestones.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Tickets\Hxcontrollers;
|
||||
|
||||
use Leantime\Core\Controller\HtmxController;
|
||||
use Leantime\Domain\Tickets\Services\Tickets;
|
||||
|
||||
class Milestones extends HtmxController
|
||||
{
|
||||
protected static string $view = 'tickets::partials.milestoneCard';
|
||||
|
||||
private Tickets $ticketService;
|
||||
|
||||
/**
|
||||
* Controller constructor
|
||||
*/
|
||||
public function init(Tickets $ticketService): void
|
||||
{
|
||||
$this->ticketService = $ticketService;
|
||||
}
|
||||
|
||||
public function progress()
|
||||
{
|
||||
|
||||
$getParams = $_GET;
|
||||
|
||||
$milestone = $this->ticketService->getTicket($getParams['milestoneId']);
|
||||
$percentDone = $this->ticketService->getMilestoneProgress($getParams['milestoneId']);
|
||||
|
||||
$this->tpl->assign('progressColor', $getParams['progressColor'] ?? 'default');
|
||||
$this->tpl->assign('noText', $getParams['noText'] ?? false);
|
||||
$this->tpl->assign('milestone', $milestone);
|
||||
$this->tpl->assign('percentDone', $percentDone);
|
||||
|
||||
return 'progress';
|
||||
}
|
||||
|
||||
public function showCard()
|
||||
{
|
||||
|
||||
$getParams = $_GET;
|
||||
|
||||
$milestone = $this->ticketService->getTicket($getParams['milestoneId']);
|
||||
$percentDone = $this->ticketService->getMilestoneProgress($getParams['milestoneId']);
|
||||
|
||||
$this->tpl->assign('percentDone', $percentDone);
|
||||
$this->tpl->assign('milestone', $milestone);
|
||||
|
||||
}
|
||||
}
|
||||
129
app/Domain/Tickets/Hxcontrollers/Subtasks.php
Normal file
129
app/Domain/Tickets/Hxcontrollers/Subtasks.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Tickets\Hxcontrollers;
|
||||
|
||||
use Leantime\Core\Controller\HxComponent;
|
||||
use Leantime\Core\Events\Htmx\HtmxEvent;
|
||||
use Leantime\Domain\Tickets\Htmx\HtmxTicketEvents;
|
||||
use Leantime\Domain\Tickets\Services\Tickets;
|
||||
|
||||
/**
|
||||
* Subtasks list component for a ticket.
|
||||
*
|
||||
* Mounted with <x-global::hx :for="self::class" :id="$ticketId" />. It both emits and listens for
|
||||
* {@see HtmxTicketEvents::SUBTASK_UPDATE} so that a subtask change made here also refreshes other
|
||||
* components showing the same data (e.g. the dashboard to-do widget) and vice-versa — the emit and
|
||||
* listen sides reference the same enum case, so they cannot drift apart.
|
||||
*/
|
||||
class Subtasks extends HxComponent
|
||||
{
|
||||
protected static string $view = 'tickets::partials.subtasks';
|
||||
|
||||
/** Refresh swaps the inner content so the mount wrapper keeps its id + event triggers. */
|
||||
public static string $swap = 'innerHTML';
|
||||
|
||||
private Tickets $ticketService;
|
||||
|
||||
public function init(Tickets $ticketService): void
|
||||
{
|
||||
$this->ticketService = $ticketService;
|
||||
}
|
||||
|
||||
public static function route(): string
|
||||
{
|
||||
return 'tickets/subtasks';
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, HtmxEvent>
|
||||
*/
|
||||
public static function listensTo(): array
|
||||
{
|
||||
return [HtmxTicketEvents::SUBTASK_UPDATE];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array<int, HtmxEvent>
|
||||
*/
|
||||
public static function emits(): array
|
||||
{
|
||||
return [HtmxTicketEvents::SUBTASK_UPDATE];
|
||||
}
|
||||
|
||||
public function save(): void
|
||||
{
|
||||
$getParams = $_GET;
|
||||
$params = $_POST;
|
||||
|
||||
$ticket = $this->ticketService->getTicket($getParams['ticketId']);
|
||||
|
||||
if ($this->ticketService->upsertSubtask($params, $ticket)) {
|
||||
$this->tpl->setNotification($this->language->__('notifications.subtask_saved'), 'success');
|
||||
} else {
|
||||
$this->tpl->setNotification($this->language->__('notifications.subtask_save_error'), 'error');
|
||||
}
|
||||
|
||||
// Announce the change. Emit the broad event (for widgets listening to all tickets, e.g. the
|
||||
// dashboard to-do widget) AND the entity-scoped event (for the ticket modal's mount, which
|
||||
// listens via <x-global::hx :id> for "<event>#<ticketId>").
|
||||
$this->tpl->emit(HtmxTicketEvents::SUBTASK_UPDATE, HtmxTicketEvents::SUBTASK_UPDATE->scoped($ticket->id));
|
||||
|
||||
$ticketSubtasks = $this->ticketService->getAllSubtasks($ticket->id);
|
||||
$statusLabels = $this->ticketService->getStatusLabels(session('currentProject'));
|
||||
$efforts = $this->ticketService->getEffortLabels();
|
||||
|
||||
$this->tpl->assign('ticket', $ticket);
|
||||
$this->tpl->assign('ticketSubtasks', $ticketSubtasks);
|
||||
$this->tpl->assign('statusLabels', $statusLabels);
|
||||
$this->tpl->assign('efforts', $efforts);
|
||||
}
|
||||
|
||||
public function get(): void
|
||||
{
|
||||
if (! $this->incomingRequest->getMethod() == 'GET') {
|
||||
throw new \Exception('This endpoint only supports GET requests');
|
||||
}
|
||||
|
||||
$getVars = $_GET;
|
||||
// Accept the ticket id from the path (contract-driven mount → query['id']) or the legacy
|
||||
// ?ticketId= query used by the in-partial forms.
|
||||
$id = $getVars['ticketId'] ?? $getVars['id'] ?? null;
|
||||
|
||||
$ticket = $this->ticketService->getTicket($id);
|
||||
$ticketSubtasks = $this->ticketService->getAllSubtasks((int) $id);
|
||||
$statusLabels = $this->ticketService->getStatusLabels(session('currentProject'));
|
||||
$efforts = $this->ticketService->getEffortLabels();
|
||||
|
||||
$this->tpl->assign('ticket', $ticket);
|
||||
$this->tpl->assign('ticketSubtasks', $ticketSubtasks);
|
||||
$this->tpl->assign('statusLabels', $statusLabels);
|
||||
$this->tpl->assign('efforts', $efforts);
|
||||
}
|
||||
|
||||
public function delete()
|
||||
{
|
||||
$getVars = $_GET;
|
||||
$id = $getVars['ticketId'];
|
||||
$parentId = $getVars['parentTicket'];
|
||||
|
||||
if ($this->ticketService->delete($id)) {
|
||||
$this->tpl->setNotification($this->language->__('notifications.subtask_deleted'), 'success');
|
||||
} else {
|
||||
$this->tpl->setNotification($this->language->__('notifications.subtask_delete_error'), 'error');
|
||||
}
|
||||
|
||||
// Announce the change — broad event for all-ticket listeners + the parent-scoped event for
|
||||
// the ticket modal's mount (which listens for "<event>#<parentTicketId>").
|
||||
$this->tpl->emit(HtmxTicketEvents::SUBTASK_UPDATE, HtmxTicketEvents::SUBTASK_UPDATE->scoped($parentId));
|
||||
|
||||
$ticket = $this->ticketService->getTicket($parentId);
|
||||
$ticketSubtasks = $this->ticketService->getAllSubtasks($parentId);
|
||||
$statusLabels = $this->ticketService->getStatusLabels(session('currentProject'));
|
||||
$efforts = $this->ticketService->getEffortLabels();
|
||||
|
||||
$this->tpl->assign('ticket', $ticket);
|
||||
$this->tpl->assign('ticketSubtasks', $ticketSubtasks);
|
||||
$this->tpl->assign('statusLabels', $statusLabels);
|
||||
$this->tpl->assign('efforts', $efforts);
|
||||
}
|
||||
}
|
||||
77
app/Domain/Tickets/Hxcontrollers/TicketCard.php
Normal file
77
app/Domain/Tickets/Hxcontrollers/TicketCard.php
Normal file
@@ -0,0 +1,77 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Tickets\Hxcontrollers;
|
||||
|
||||
use Leantime\Core\Controller\HtmxController;
|
||||
use Leantime\Domain\Tickets\Services\Tickets;
|
||||
use Leantime\Domain\Timesheets\Services\Timesheets;
|
||||
|
||||
class TicketCard extends HtmxController
|
||||
{
|
||||
protected static string $view = 'tickets::partials.ticketCard';
|
||||
|
||||
private Tickets $ticketService;
|
||||
|
||||
private Timesheets $timesheetService;
|
||||
|
||||
/**
|
||||
* Controller constructor
|
||||
*/
|
||||
public function init(Tickets $ticketService, Timesheets $timesheetService): void
|
||||
{
|
||||
$this->ticketService = $ticketService;
|
||||
$this->timesheetService = $timesheetService;
|
||||
}
|
||||
|
||||
public function save(): void
|
||||
{
|
||||
|
||||
$postParams = $_POST;
|
||||
$id = $postParams['id'];
|
||||
|
||||
$ticket = $this->ticketService->getTicket($id);
|
||||
|
||||
$values = $ticket;
|
||||
|
||||
// Until we have everything as objects we'll need to use arrays
|
||||
$this->tpl->assign('row', (array) $ticket);
|
||||
$this->tpl->assign('statusLabels', $this->ticketService->getStatusLabels());
|
||||
$this->tpl->assign('efforts', $this->ticketService->getEffortLabels());
|
||||
$this->tpl->assign('priorities', $this->ticketService->getPriorityLabels());
|
||||
|
||||
$allProjectMilestones = $this->ticketService->getAllMilestones([
|
||||
'sprint' => '',
|
||||
'type' => 'milestone',
|
||||
'currentProject' => session('currentProject'),
|
||||
]);
|
||||
|
||||
$this->tpl->assign('milestones', $allProjectMilestones);
|
||||
|
||||
}
|
||||
|
||||
public function get($params): void
|
||||
{
|
||||
|
||||
$id = $params['id'] ?? $params['ticketId'] ?? null;
|
||||
$cardType = $params['type'] ?? 'full';
|
||||
|
||||
$ticket = $this->ticketService->getTicket($id);
|
||||
$onTheClock = $this->timesheetService->isClocked(session('userdata.id'));
|
||||
|
||||
$this->tpl->assign('cardType', $cardType);
|
||||
$this->tpl->assign('onTheClock', $onTheClock);
|
||||
$this->tpl->assign('statusLabels', $this->ticketService->getStatusLabels());
|
||||
$this->tpl->assign('efforts', $this->ticketService->getEffortLabels());
|
||||
$this->tpl->assign('priorities', $this->ticketService->getPriorityLabels());
|
||||
|
||||
$allProjectMilestones = $this->ticketService->getAllMilestones([
|
||||
'sprint' => '',
|
||||
'type' => 'milestone',
|
||||
'currentProject' => $ticket->projectId,
|
||||
]);
|
||||
$this->tpl->assign('milestones', $allProjectMilestones);
|
||||
|
||||
$this->tpl->assign('row', (array) $ticket);
|
||||
|
||||
}
|
||||
}
|
||||
37
app/Domain/Tickets/Hxcontrollers/TimerButton.php
Normal file
37
app/Domain/Tickets/Hxcontrollers/TimerButton.php
Normal file
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
namespace Leantime\Domain\Tickets\Hxcontrollers;
|
||||
|
||||
use Leantime\Core\Controller\HtmxController;
|
||||
use Leantime\Domain\Timesheets\Services\Timesheets;
|
||||
|
||||
class TimerButton extends HtmxController
|
||||
{
|
||||
protected static string $view = 'tickets::partials.timerButton';
|
||||
|
||||
private Timesheets $timesheetService;
|
||||
|
||||
/**
|
||||
* Controller constructor
|
||||
*/
|
||||
public function init(Timesheets $timesheetService): void
|
||||
{
|
||||
$this->timesheetService = $timesheetService;
|
||||
}
|
||||
|
||||
public function getStatus(): void
|
||||
{
|
||||
|
||||
$params = $this->incomingRequest->query->all();
|
||||
|
||||
$onTheClock = session()->exists('userdata') ? $this->timesheetService->isClocked(session('userdata.id')) : false;
|
||||
$this->tpl->assign('onTheClock', $onTheClock);
|
||||
$this->tpl->assign('parentTicketId', $params['request_parts'] ?? false);
|
||||
}
|
||||
|
||||
public function getStatusButton(): void
|
||||
{
|
||||
$this->getStatus();
|
||||
$this->tpl->displayPartial('tickets::partials.timerButton');
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user