OneBot: Leantime 改造版源码(BOM/Univer 表格/AI 接管/品牌替换等)

This commit is contained in:
wangruiguo
2026-09-03 18:49:20 +08:00
commit d647428529
3501 changed files with 1988906 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
@props([
'milestone' => null,
'noText' => false,
'percentDone' => 0,
'progressColor' => 'default'
])
<div class="ticketBox fixed">
<div class="row">
<div class="col-md-8" style="margin-bottom:5px;">
<strong><a href="<?=BASE_URL ?>/tickets/showKanban?milestone={{ $milestone->id }}" >{{ $milestone->headline }}</a></strong>
</div>
<div class="col-md-4 align-right">
</div>
</div>
@fragment('progress')
@if($noText === false || $noText === null)
<div class="row progress-wrapper">
<div class="col-md-7 percent-label">
{{ __("label.due") }}
<?php echo format($milestone->editTo )->date($tpl->__("text.no_date_defined")); ?>
</div>
<div class="col-md-5 percent-label" style="text-align:right">
<?=sprintf($tpl->__("text.percent_complete"), format($percentDone)->decimal())?>
</div>
</div>
@endif
<div class="row">
<div class="col-md-12">
<div class="progress" data-tippy-content="<?=sprintf($tpl->__("text.percent_complete"), format($percentDone)->decimal())?>">
<div class="progress-bar progress-bar-success"
role="progressbar"
aria-valuenow="{{ $percentDone }}"
aria-valuemin="0" aria-valuemax="100"
style="width: {{ $percentDone }}%; {{ $progressColor !== 'default' ? ' background: #'.$progressColor.'; ' : '' }}">
<span class="sr-only">{{ sprintf($tpl->__("text.percent_complete"), format($percentDone)->decimal()) }}</span>
</div>
</div>
</div>
</div>
<script>
// Idempotent init — a bare tippy('[data-tippy-content]') here re-instanced
// every tooltip on the page each time a milestone card rendered (flashing
// + duplicate header tooltips). initTooltips skips already-instanced els.
window.leantime?.initTooltips?.();
</script>
@endfragment
</div>

View File

@@ -0,0 +1,87 @@
@php
/**
* Quick-add form partial for Kanban columns
*
* @var int $statusId - Status column ID
* @var string|null $swimlaneKey - Swimlane identifier
* @var bool $isEmpty - Whether column is empty
* @var array|null $reopenState - Session flash data
*/
$isActive = !empty($reopenState)
&& $reopenState['status'] == $statusId
&& ($reopenState['swimlane'] ?? null) == ($swimlaneKey ?? null);
$savedHeadline = $isActive ? ($reopenState['headline'] ?? '') : '';
$hasError = $isActive && !empty($reopenState['error']);
@endphp
<div class="quickaddContainer tw-mb-s {{ $isEmpty ? 'quickaddContainer--empty' : '' }}" data-status="{{ $statusId }}" data-swimlane="{{ $swimlaneKey ?? '' }}">
<a href="javascript:void(0);"
class="quickAddLink {{ $isEmpty ? 'empty-state' : 'inline-add' }}"
onclick="leantime.kanbanController.toggleQuickAdd(this)"
aria-expanded="{{ $isActive ? 'true' : 'false' }}"
aria-controls="quickadd-form-{{ $statusId }}-{{ $swimlaneKey ?? 'default' }}"
style="{{ $isActive ? 'display:none;' : '' }}">
<i class="fa-solid fa-plus"></i>
<span>Add To-Do</span>
</a>
<form method="post"
class="quickAddForm {{ $isActive ? 'active' : '' }}"
id="quickadd-form-{{ $statusId }}-{{ $swimlaneKey ?? 'default' }}"
data-quickadd-form
style="{{ $isActive ? '' : 'display:none;' }}"
data-submitting="false">
<input type="hidden" name="quickadd" value="1" />
<input type="hidden" name="status" value="{{ $statusId }}" />
<input type="hidden" name="swimlane" value="{{ $swimlaneKey ?? '' }}" />
<input type="hidden" name="groupBy" value="{{ $currentGroupBy ?? '' }}" />
<input type="hidden" name="milestone" value="{{ $searchCriteria['milestone'] ?? '' }}" />
<input type="hidden" name="sprint" value="{{ session('currentSprint') ?? '' }}" />
<input type="hidden" name="stay_open" value="0" data-stay-open-input />
@if (! empty($programBoard) && ! empty($availableProjects))
{{-- Program board: a new task must belong to exactly one child project. --}}
<div class="form-group">
<select name="quickaddProjectId" class="form-control" required aria-label="{{ __('label.project') }}">
<option value="">{{ __('label.project') }}</option>
@foreach ($availableProjects as $quickAddProjectId => $quickAddProjectName)
<option value="{{ $quickAddProjectId }}">{{ $tpl->escape($quickAddProjectName) }}</option>
@endforeach
</select>
</div>
@endif
<div class="form-group">
<label for="headline-{{ $statusId }}-{{ $swimlaneKey ?? 'default' }}" class="sr-only">Task name</label>
<input type="text"
name="headline"
id="headline-{{ $statusId }}-{{ $swimlaneKey ?? 'default' }}"
class="form-control quickAddInput {{ $hasError ? 'error' : '' }}"
placeholder="What are you working on? ↵"
value="{{ htmlspecialchars($savedHeadline) }}"
{{ $isActive ? 'autofocus' : '' }}
data-quickadd-input />
@if ($hasError)
<div class="error-message" role="alert">{{ htmlspecialchars($reopenState['error']) }}</div>
@endif
<div id="quick-add-help-{{ $statusId }}-{{ $swimlaneKey ?? 'default' }}" class="sr-only">
Press Enter to save and close. Press Shift plus Enter to save and add another task. Press Escape to cancel.
</div>
</div>
<div class="formButtonContainer">
<x-global::forms.button inputType="submit" contentRole="primary" onclick="this.closest('form').dataset.submitting = 'true'; this.closest('form').querySelector('[data-stay-open-input]').value = '0';">Save</x-global::forms.button>
<x-global::forms.button inputType="button" contentRole="secondary"
onclick="leantime.kanbanController.toggleQuickAdd(this.closest('.quickaddContainer').querySelector('.quickAddLink'))">
Cancel
</x-global::forms.button>
<i class="fa fa-circle-question"
data-tippy-content="<strong>Keyboard Shortcuts:</strong><br>Enter: Save and close<br>Shift+Enter: Save and add another<br>Esc: Cancel"
tabindex="0"
aria-label="Keyboard shortcuts help"></i>
</div>
</form>
</div>

View File

@@ -0,0 +1,163 @@
<ul class="sortableTicketList" style="margin-bottom:120px;">
<li class="">
<a href="javascript:void(0);" class="quickAddLink" id="subticket_new_link" onclick="jQuery('#subticket_new').toggle('fast', function() {jQuery(this).find('input[name=headline]').focus();}); jQuery(this).toggle('fast');"><i class="fas fa-plus-circle"></i> {{ __("links.add_task") }}</a>
<div class="ticketBox hideOnLoad" id="subticket_new" >
<form method="post" class="form-group"
hx-post="{{ BASE_URL }}/tickets/subtasks/save?ticketId={{ $ticket->id }}"
hx-indicator=".htmx-indicator-small"
hx-target="#ticketSubtasks">
<input type="hidden" value="new" name="subtaskId" />
<input type="hidden" value="1" name="subtaskSave" />
<input name="headline" type="text" title="{{ __("label.headline") }}" style="width:100%" placeholder="{{ __("input.placeholders.what_are_you_working_on") }}" />
<input type="submit" value="{{ __("buttons.save") }}" name="quickadd" />
<div class="htmx-indicator-small">
<x-global::loader id="loadingthis" size="25px" />
</div>
<input type="hidden" name="dateToFinish" id="dateToFinish" value="" />
<input type="hidden" name="status" value="3" />
<input type="hidden" name="sprint" value="{{ session("currentSprint") }}" />
<x-global::forms.button tag="a" link="javascript:void(0);" onclick="jQuery('#subticket_new').toggle('fast'); jQuery('#subticket_new_link').toggle('fast');" contentRole="tertiary">
{{ __("links.cancel") }}
</x-global::forms.button>
</form>
<div class="clearfix"></div>
</div>
</li>
@php
$sumPlanHours = 0;
$sumEstHours = 0;
@endphp
@foreach ($ticketSubtasks as $subticket)
@php
$sumPlanHours = $sumPlanHours + $subticket['planHours'];
$sumEstHours = $sumEstHours + $subticket['hourRemaining'];
if ($subticket['dateToFinish'] == "0000-00-00 00:00:00" || $subticket['dateToFinish'] == "1969-12-31 00:00:00") {
$date = $tpl->__("text.anytime");
} else {
$date = format($subticket['dateToFinish'])->date();
}
@endphp
<li class="ui-state-default" id="ticket_{{ $subticket['id'] }}" >
<div class="ticketBox fixed priority-border-{{ $subticket['priority'] }}" data-val="{{ $subticket['id'] }}" >
<div class="row">
<div class="col-md-12" style="padding:0 15px;">
@if($login::userIsAtLeast($roles::$editor))
<div class="inlineDropDownContainer" >
<a href="javascript:void(0)" class="dropdown-toggle ticketDropDown" data-toggle="dropdown">
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu">
<li><a href="javascript:void(0);" hx-delete="{{ BASE_URL }}/tickets/subtasks/delete?ticketId={{ $subticket["id"] }}&parentTicket={{ $ticket->id }}" hx-target="#ticketSubtasks" class="delete"><i class="fa fa-trash"></i> {{ __("links.delete_todo") }}</a></li>
</ul>
</div>
@endif
<a href="#/tickets/showTicket/{{ $subticket['id'] }}">{{ $subticket['headline'] }}</a>
</div>
</div>
<div class="row">
<div class="col-md-9" style="padding:0 15px;">
<div class="row">
<div class="col-md-4">
{{ __("label.due") }}<input type="text" title="{{ __("label.due") }}" value="{{ $date }}" class="duedates secretInput quickDueDates" data-id="{{ $subticket['id'] }}" name="date" />
</div>
<div class="col-md-4">
{{ __("label.planned_hours") }}<input type="text" value="{{ $subticket['planHours'] }}" name="planHours" data-label="planHours-{{ $subticket['id'] }}" class="small-input secretInput asyncInputUpdate" style="width:40px"/>
</div>
<div class="col-md-4">
{{ __("label.estimated_hours_remaining") }}<input type="text" value="{{ $subticket['hourRemaining'] }}" name="hourRemaining" data-label="hourRemaining-{{ $subticket['id'] }}" class="small-input secretInput asyncInputUpdate" style="width:40px"/>
</div>
</div>
</div>
<div class="col-md-3" style="padding-top:3px;" >
<div class="right">
<div class="dropdown ticketDropdown effortDropdown show">
<a class="dropdown-toggle f-left label-default effort" href="javascript:void(0);" role="button" id="effortDropdownMenuLink{{ $subticket['id'] }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="text">@if ($subticket['storypoints'] != '' && $subticket['storypoints'] > 0 && isset($efforts[$subticket['storypoints']]))
{{ $efforts[$subticket['storypoints']] }}
@else
{{ __("label.story_points_unkown") }}
@endif
</span>
&nbsp;<i class="fa fa-caret-down" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu" aria-labelledby="effortDropdownMenuLink{{ $subticket['id'] }}">
<li class="nav-header border">{{ __("dropdown.how_big_todo") }}</li>
@foreach($efforts as $effortKey => $effortValue)
<li class='dropdown-item'>
<a href='javascript:void(0);' data-value='{{ $subticket['id'] }}_{{ $effortKey }}' id='ticketEffortChange{{ $subticket['id'] . $effortKey }}'> {{ $effortValue }}</a>
</li>
@endforeach
</ul>
</div>
@php
if (isset($statusLabels[$subticket['status']])) {
$class = $statusLabels[$subticket['status']]["class"];
$name = $statusLabels[$subticket['status']]["name"];
} else {
$class = 'label-important';
$name = 'new';
}
@endphp
<div class="dropdown ticketDropdown statusDropdown colorized show">
<a class="dropdown-toggle f-left status {{ $class }}" href="javascript:void(0);" role="button" id="statusDropdownMenuLink{{ $subticket['id'] }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="text">{{$name }}
</span>
&nbsp;<i class="fa fa-caret-down" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu" aria-labelledby="statusDropdownMenuLink{{ $subticket['id'] }}">
<li class="nav-header border">{{ __('dropdown.choose_status') }}</li>
@foreach ($statusLabels as $key => $label)
<li class='dropdown-item'>
<a href='javascript:void(0);' class='{{ $label["class"] }}' data-label='{{ $label["name"] }}' data-value='{{ $subticket['id'] }}_{{ $key }}_{{ $label["class"] }}' id='ticketStatusChange{{ $subticket['id'] . $key }}' >{{ $label["name"] }}</a>
</li>
@endforeach
</ul>
</div>
</div>
</div>
</div>
</div>
</li>
@endforeach
</ul>
<script>
jQuery(document).ready(function(){
<?php if ($login::userIsAtLeast($roles::$editor)) { ?>
leantime.ticketsController.initAsyncInputChange();
leantime.ticketsController.initDueDateTimePickers();
leantime.ticketsController.initEffortDropdown();
leantime.ticketsController.initStatusDropdown();
<?php } else { ?>
leantime.authController.makeInputReadonly(".nyroModalCont");
<?php } ?>
});
</script>

View File

@@ -0,0 +1,139 @@
<div class="ticketBox fixed priority-border-{{ $row['priority'] }}" data-val="{{ $row['id'] }}">
<div class="row">
<div class="col-md-8 titleContainer">
@if($cardType == "full")
<small>{{ $row['projectName'] }}</small><br />
@if($row['dependingTicketId'] > 0)
<a href="#/tickets/showTicket/{{ $row['dependingTicketId'] }}">{{ $row['parentHeadline'] }}</a> //
@endif
@endif
<strong><a href="#/tickets/showTicket/{{ $row['id'] }}" >{{ $row['headline'] }}</a></strong>
</div>
<div class="col-md-4 timerContainer" style="padding:5px 15px;" id="timerContainer-{{ $row['id'] }}">
@include("tickets::partials.ticketsubmenu", ["ticket" => $row, "onTheClock" => $onTheClock])
@if($cardType == "full")
<div class="scheduler pull-right">
@if( $row['editFrom'] != "0000-00-00 00:00:00" && $row['editFrom'] != "1969-12-31 00:00:00")
<i class="fa-solid fa-calendar-check infoIcon tw-mr-xs" style="color:var(--accent2)" data-tippy-content="{{ __('text.schedule_to_start_on') }} {{ format($row['editFrom'])->date() }}"></i>
@else
<i class="fa-regular fa-calendar-xmark infoIcon tw-mr-xs" data-tippy-content="{{ __('text.not_scheduled_drag_ai') }}"></i>
@endif
</div>
@endif
</div>
</div>
<div class="row">
<div class="col-md-4" style="padding:0 15px;">
@if($cardType == "full")
<i class="fa-solid fa-business-time infoIcon" data-tippy-content=" {{ __("label.due") }}"></i>
<input type="text" title="{{ __("label.due") }}" value="{{ format($row['dateToFinish'])->date(__("text.anytime")) }}" class="duedates secretInput" style="margin-left:0px;" data-id="{{ $row['id'] }}" name="date" />
@endif
</div>
<div class="col-md-8 dropdownContainer" style="padding-top:5px;">
<div class="dropdown ticketDropdown statusDropdown colorized show right ">
<a class="dropdown-toggle f-left status {{ $statusLabels[$row['status']]["class"] }}" href="javascript:void(0);" role="button" id="statusDropdownMenuLink{{ $row['id'] }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="text">
@if(isset($statusLabels[$row['status']]))
{{ $statusLabels[$row['status']]["name"] }}
@else
unknown
@endif
</span>
&nbsp;<i class="fa fa-caret-down" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu pull-right" aria-labelledby="statusDropdownMenuLink{{ $row['id'] }}">
<li class="nav-header border">{{ __("dropdown.choose_status") }}</li>
@foreach ($statusLabels as $key => $label)
<li class='dropdown-item'>
<a href='javascript:void(0);'
class='{{ $label["class"] }}'
data-label='{{ $label["name"] }}'
data-value='{{ $row['id'] }}_{{ $key }}_{{ $label["class"] }}'
id='ticketStatusChange{{$row['id'] . $key }}'>
{{ $label["name"] }}
</a>
</li>
@endforeach
</ul>
</div>
<?php /*
<div class="dropdown ticketDropdown effortDropdown show right">
<a class="dropdown-toggle f-left label-default effort" href="javascript:void(0);" role="button" id="effortDropdownMenuLink{{ $row['id'] }}" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="text">
@if ($row['storypoints'] != '' && $row['storypoints'] > 0)
{{ $efforts["" . $row['storypoints']] ?? $row['storypoints'] }}
@else
{{ __("label.story_points_unkown") }}
@endif
</span>
&nbsp;<i class="fa fa-caret-down" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu" aria-labelledby="effortDropdownMenuLink{{ $row['id'] }}">
<li class="nav-header border">{{ __("dropdown.how_big_todo") }}</li>
@foreach($efforts as $effortKey => $effortValue)
<li class='dropdown-item'>
<a href='javascript:void(0);'
data-value='{{ $row['id'] . "_" . $effortKey }}'
id='ticketEffortChange{{ $row['id'] . $effortKey }}'>
{{ $effortValue }}
</a>
</li>
@endforeach
</ul>
</div>
*/ ?>
@if($cardType == "full")
<div class="dropdown ticketDropdown milestoneDropdown colorized show right tw-mr-sm">
<a style="background-color:{{ $row['milestoneColor'] }}"
class="dropdown-toggle f-left label-default milestone"
href="javascript:void(0);"
role="button" id="milestoneDropdownMenuLink{{ $row['id'] }}"
data-toggle="dropdown"
aria-haspopup="true"
aria-expanded="false">
<span class="text">
@if($row['milestoneid'] != "" && $row['milestoneid'] != 0)
{{ $row['milestoneHeadline'] }}
@else
{{ __("label.no_milestone") }}
@endif
</span>
&nbsp;<i class="fa fa-caret-down" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu pull-right" aria-labelledby="milestoneDropdownMenuLink{{ $row['id'] }}">
<li class="nav-header border">{{ __("dropdown.choose_milestone") }}</li>
<li class='dropdown-item'>
<a style='background-color:#b0b0b0'
href='javascript:void(0);'
data-label="{{__("label.no_milestone") }}"
data-value='{{ $row['id'] }}_0_#b0b0b0'>
{{ __("label.no_milestone") }}
</a>
</li>
@if(isset($milestones))
@foreach($milestones as $milestone)
@if(is_object($milestone))
<li class='dropdown-item'>
<a href='javascript:void(0);'
data-label='{{ $milestone->headline }}'
data-value='{{ $row['id'] }}_{{ $milestone->id }}_{{ $milestone->tags }}'
id='ticketMilestoneChange{{ $row['id'] . $milestone->id }}'
style='background-color:{{ $milestone->tags }}'>
{{ $milestone->headline }}
</a>
</li>
@endif
@endforeach
@endif
</ul>
</div>
@endif
</div>
</div>
</div>

View File

@@ -0,0 +1,40 @@
@props([
'ticket' => false,
'onTheClock' => false,
'allowSubtaskCreation' => false
])
@if ($login::userIsAtLeast(\Leantime\Domain\Auth\Models\Roles::$editor))
<div class="inlineDropDownContainer" style="float:right;">
<a href="javascript:void(0);" class="dropdown-toggle ticketDropDown" data-toggle="dropdown">
<i class="fa fa-ellipsis-v" aria-hidden="true"></i>
</a>
<ul class="dropdown-menu">
<li class="nav-header">{{ __("subtitles.todo") }}</li>
@dispatchEvent("beforeShowTicket", ["ticket"=>$ticket])
<li><a href="#/tickets/showTicket/{{ $ticket["id"] }}" class=''><i class="fa fa-edit"></i> {{ __("links.edit_todo") }}</a></li>
@dispatchEvent("beforeMoveTicket", ["ticket"=>$ticket])
<li><a href="#/tickets/moveTicket/{{ $ticket["id"] }}" class=""><i class="fa-solid fa-arrow-right-arrow-left"></i> {{ __("links.move_todo") }}</a></li>
@if($allowSubtaskCreation)
<li><a href="javascript:void(0);" onclick="jQuery('#subtask-form-{{$ticket['id']}}').toggle();"
class="add-subtask-link">
<i class="fa-solid fa-diagram-predecessor"></i> Add Subtask</a></li>
@endif
@dispatchEvent("beforeDeleteTicket", ["ticket"=>$ticket])
<li><a href="#/tickets/delTicket/{{ $ticket["id"] }}" class="delete"><i class="fa fa-trash"></i> {{ __("links.delete_todo") }}</a></li>
@dispatchEvent("submenuSection", ["ticket"=>$ticket])
<li class="nav-header border">{{ __("subtitles.track_time") }}</li>
@dispatchEvent("beforeTimer", ["ticket"=>$ticket])
<li class="timerContainer tw-px-[10px]">
@include('tickets::partials.timerButton', ['parentTicketId' => $ticket['id'], 'onTheClock' => $onTheClock, 'style'=> 'full'])
</li>
@dispatchEvent("end")
</ul>
</div>
@endif

View File

@@ -0,0 +1,78 @@
@props([
'parentTicketId' => false,
'onTheClock' => false,
'style' => 'simple' //simple just the button, full witrh button text
])
<div id="timer-button-container-{{ $parentTicketId }}"
hx-get="{{BASE_URL}}/tickets/timerButton/get-status-button/{{ $parentTicketId }}"
hx-trigger="timerUpdate from:body"
hx-swap="outerHTML"
class="tw-relative timerContainer">
@if ($onTheClock === false)
<a href="javascript:void(0);" data-value="{{ $parentTicketId }}"
hx-patch="{{ BASE_URL }}/hx/timesheets/stopwatch/start-timer/"
hx-target="#timerHeadMenu"
hx-swap="outerHTML"
onclick="this.classList.add('starting');"
hx-vals='{"ticketId": "{{ $parentTicketId }}", "action":"start"}'
data-tippy-content="{{ __("links.start_work") }}">
<span class="fa-regular fa-circle-play" style="font-size:18px; padding-top:3px;"></span>
@if($style=="full")
{{ __("links.start_work") }}
@endif
</a>
@endif
@if ($onTheClock !== false && $onTheClock["id"] == $parentTicketId)
<a href="javascript:void(0);" data-value="{{ $parentTicketId }}"
hx-trigger="click delay:500ms"
hx-patch="{{ BASE_URL }}/hx/timesheets/stopwatch/stop-timer/"
hx-target="#timerHeadMenu"
hx-vals='{"ticketId": "{{ $parentTicketId }}", "action":"stop"}'
hx-swap="outerHTML"
onclick="this.classList.add('stopped');"
data-tippy-content="@if (is_array($onTheClock) == true) {!! strip_tags(sprintf(__("links.stop_work_started_at"), dtHelper()::createFromTimestamp($onTheClock["since"], 'UTC')->setToUserTimezone()->format(__("language.timeformat")))) !!} @else {!! strip_tags(sprintf(__("links.stop_work_started_at"), dtHelper()::now()->setToUserTimezone()->format(__("language.timeformat")))) !!} @endif"
>
<span class="fa-regular fa-circle-stop" style="font-size:18px; padding-top:3px;"></span>
@if($style=="full")
@if (is_array($onTheClock) == true)
{!! sprintf(__("links.stop_work_started_at"), dtHelper()::createFromTimestamp($onTheClock["since"], 'UTC')->setToUserTimezone()->format(__("language.timeformat"))) !!}
@else
{!! sprintf(__("links.stop_work_started_at"), dtHelper()::now()->setToUserTimezone()->format(__("language.timeformat"))) !!}
@endif
@endif
<!-- These elements will be added dynamically when the timer is stopped -->
<div class="success-circle"></div>
<div class="particles-container">
<div class="particle particle-1"></div>
<div class="particle particle-2"></div>
<div class="particle particle-3"></div>
<div class="particle particle-4"></div>
<div class="particle particle-5"></div>
<div class="particle particle-6"></div>
<div class="particle particle-7"></div>
<div class="particle particle-8"></div>
</div>
</a>
@endif
@if ($onTheClock !== false && $onTheClock["id"] != $parentTicketId)
<span class='working'>
@if($style=="full")
{{ __("text.timer_set_other_todo") }}
@else
<span class="fa-solid fa-user-clock" style="font-size:16px; padding-top:3px; color:var(--grey);" data-tippy-content="{{ __("text.timer_set_other_todo") }}"></span>
@endif
</span>
@endif
</div>

View File

@@ -0,0 +1,43 @@
@props([
'parentTicketId' => false,
'onTheClock' => false
])
<li id="timerContainer-{{ $parentTicketId }}"
hx-get="{{BASE_URL}}/tickets/timerButton/get-status/{{ $parentTicketId }}"
hx-trigger="timerUpdate from:body"
hx-swap="outerHTML"
class="timerContainer">
@if ($onTheClock === false)
<a href="javascript:void(0);" data-value="{{ $parentTicketId }}"
hx-patch="{{ BASE_URL }}/hx/timesheets/stopwatch/start-timer/"
hx-target="#timerHeadMenu"
hx-swap="outerHTML"
hx-vals='{"ticketId": "{{ $parentTicketId }}", "action":"start"}'>
<span class="fa-regular fa-clock"></span> {{ __("links.start_work") }}
</a>
@endif
@if ($onTheClock !== false && $onTheClock["id"] == $parentTicketId)
<a href="javascript:void(0);" data-value="{{ $parentTicketId }}"
hx-patch="{{ BASE_URL }}/hx/timesheets/stopwatch/stop-timer/"
hx-target="#timerHeadMenu"
hx-vals='{"ticketId": "{{ $parentTicketId }}", "action":"stop"}'
hx-swap="outerHTML">
<span class="fa fa-stop"></span>
@if (is_array($onTheClock) == true)
{!! sprintf(__("links.stop_work_started_at"), date(__("language.timeformat"), $onTheClock["since"])) !!}
@else
{!! sprintf(__("links.stop_work_started_at"), date(__("language.timeformat"), time())) !!}
@endif
</a>
@endif
@if ($onTheClock !== false && $onTheClock["id"] != $parentTicketId)
<span class='working'>
{{ __("text.timer_set_other_todo") }}
</span>
@endif
</li>