fixed tags and also calander

This commit is contained in:
Mark Gregory
2026-06-16 17:42:07 +01:00
parent cd76070d17
commit 74baba8c89
10 changed files with 305 additions and 17 deletions
@@ -102,6 +102,32 @@ final class TicketCreate extends Component
return $this->redirectRoute('helpdesk.tickets.index', navigate: true);
}
/**
* Clear the create form, including Select2 and Flatpickr browser widgets.
*/
public function clearForm(): void
{
$this->resetErrorBag();
$this->resetValidation();
$this->subject = '';
$this->body = '';
$this->company_id = null;
$this->board_id = null;
$this->priority_id = null;
$this->category_id = null;
$this->project_id = null;
$this->product_id = null;
$this->team_id = null;
$this->due_at = null;
$this->tag_ids = [];
$this->attachments = [];
$this->dispatch('helpdesk-form-cleared');
$this->dispatch('helpdesk-editor-reset', model: 'body');
}
public function render(): View
{
return view('helpdesk::livewire.ticket-create', [
+28
View File
@@ -130,6 +130,34 @@ final class TicketEdit extends Component
return redirect()->route('helpdesk.tickets.show', $fresh);
}
/**
* Clear the edit form, including Select2 and Flatpickr browser widgets.
*/
public function clearForm(): void
{
$this->authorize('update', $this->ticket);
$this->resetErrorBag();
$this->resetValidation();
$this->subject = '';
$this->body = '';
$this->company_id = null;
$this->status_id = null;
$this->board_id = null;
$this->priority_id = null;
$this->category_id = null;
$this->project_id = null;
$this->product_id = null;
$this->team_id = null;
$this->agent_id = null;
$this->due_at = null;
$this->tag_ids = [];
$this->dispatch('helpdesk-form-cleared');
$this->dispatch('helpdesk-editor-reset', model: 'body');
}
public function render(): View
{
return view('helpdesk::livewire.ticket-edit', [
@@ -582,3 +582,61 @@
top: 50% !important;
transform: translateY(-50%) !important;
}
/* Helpdesk Flatpickr date picker */
.flatpickr-calendar {
border: 1px solid rgb(63 63 70);
background: rgb(24 24 27);
color: rgb(244 244 245);
box-shadow: 0 20px 45px rgb(0 0 0 / 0.35);
}
.flatpickr-calendar.arrowTop::before,
.flatpickr-calendar.arrowTop::after,
.flatpickr-calendar.arrowBottom::before,
.flatpickr-calendar.arrowBottom::after {
border-bottom-color: rgb(24 24 27);
border-top-color: rgb(24 24 27);
}
.flatpickr-months,
.flatpickr-months .flatpickr-month,
.flatpickr-current-month .flatpickr-monthDropdown-months,
.flatpickr-current-month input.cur-year {
background: rgb(24 24 27);
color: rgb(244 244 245);
}
.flatpickr-weekday,
span.flatpickr-weekday {
color: rgb(161 161 170);
}
.flatpickr-day {
color: rgb(228 228 231);
}
.flatpickr-day:hover,
.flatpickr-day:focus {
border-color: rgb(59 130 246);
background: rgb(39 39 42);
color: rgb(255 255 255);
}
.flatpickr-day.selected,
.flatpickr-day.startRange,
.flatpickr-day.endRange {
border-color: rgb(37 99 235);
background: rgb(37 99 235);
color: rgb(255 255 255);
}
.flatpickr-day.today {
border-color: rgb(34 197 94);
}
.flatpickr-day.flatpickr-disabled,
.flatpickr-day.prevMonthDay,
.flatpickr-day.nextMonthDay {
color: rgb(113 113 122);
}
+109 -9
View File
@@ -1,30 +1,130 @@
import './bootstrap';
import $ from 'jquery';
import select2 from 'select2/dist/js/select2.full.js';
import flatpickr from 'flatpickr';
import 'flatpickr/dist/flatpickr.css';
window.$ = $;
window.jQuery = $;
import select2 from 'select2/dist/js/select2.full.js';
select2(window, $);
function initialiseHelpdeskSelects()
{
console.log('initialising select2');
function livewireComponentFor(element) {
const componentRoot = element.closest('[wire\\:id]');
if (!componentRoot || ! window.Livewire) {
return null;
}
return window.Livewire.find(componentRoot.getAttribute('wire:id'));
}
function setLivewireProperty(element, model, value) {
const component = livewireComponentFor(element);
if (!component || !model) {
return;
}
component.set(model, value === '' ? null : value);
}
function initialiseHelpdeskSelects() {
$('[data-helpdesk-select2]').each(function () {
const $select = $(this);
const select = this;
const $select = $(select);
const placeholder = $select.data('placeholder') || $select.find('option[value=""]').first().text() || 'Select option';
if ($select.hasClass('select2-hidden-accessible')) {
return;
}
if (!$select.find('option[value=""]').length) {
$select.prepend(new Option('', '', false, false));
}
$select.select2({
width: '100%',
allowClear: true,
placeholder,
});
$select.on('change.helpdesk-select2', function () {
setLivewireProperty(select, $select.data('wire-model'), $select.val());
});
});
}
document.addEventListener('DOMContentLoaded', initialiseHelpdeskSelects);
document.addEventListener('livewire:navigated', initialiseHelpdeskSelects);
document.addEventListener('livewire:init', () => {
function clearHelpdeskSelects(root = document) {
$(root).find('[data-helpdesk-select2]').each(function () {
const $select = $(this);
$select.val(null);
$select.trigger('change.select2');
$select.trigger('change.helpdesk-select2');
$select.trigger('change');
});
}
function initialiseHelpdeskDatePickers() {
document.querySelectorAll('[data-helpdesk-flatpickr]').forEach((input) => {
if (input._helpdeskFlatpickr) {
return;
}
input._helpdeskFlatpickr = flatpickr(input, {
allowInput: true,
altInput: true,
altFormat: 'd M Y',
dateFormat: 'Y-m-d',
disableMobile: false,
onChange: (_selectedDates, dateText) => {
setLivewireProperty(input, input.dataset.wireModel, dateText || null);
},
onClose: (_selectedDates, dateText) => {
setLivewireProperty(input, input.dataset.wireModel, dateText || null);
},
});
});
}
function clearHelpdeskDatePickers(root = document) {
root.querySelectorAll('[data-helpdesk-flatpickr]').forEach((input) => {
if (input._helpdeskFlatpickr) {
input._helpdeskFlatpickr.clear();
}
input.value = '';
setLivewireProperty(input, input.dataset.wireModel, null);
});
}
function initialiseHelpdeskFormControls() {
initialiseHelpdeskSelects();
initialiseHelpdeskDatePickers();
}
function clearHelpdeskFormControls() {
clearHelpdeskSelects();
clearHelpdeskDatePickers();
}
window.initialiseHelpdeskFormControls = initialiseHelpdeskFormControls;
window.clearHelpdeskFormControls = clearHelpdeskFormControls;
document.addEventListener('DOMContentLoaded', initialiseHelpdeskFormControls);
document.addEventListener('livewire:navigated', initialiseHelpdeskFormControls);
document.addEventListener('helpdesk-form-cleared', clearHelpdeskFormControls);
document.addEventListener('livewire:init', () => {
initialiseHelpdeskFormControls();
Livewire.hook('morphed', () => {
initialiseHelpdeskSelects();
initialiseHelpdeskFormControls();
});
Livewire.on('helpdesk-form-cleared', () => {
clearHelpdeskFormControls();
});
});
@@ -0,0 +1,33 @@
@props([
'id',
'model',
'label' => null,
'required' => false,
'placeholder' => 'Select date',
])
<div>
@if ($label)
<label class="block text-sm font-semibold text-zinc-200" for="{{ $id }}">
{{ $label }}
@if ($required)
<span class="helpdesk-required-star">*</span>
@endif
</label>
@endif
<div class="mt-2" wire:ignore>
<input
id="{{ $id }}"
type="text"
value="{{ $attributes->get('value') }}"
data-helpdesk-flatpickr
data-wire-model="{{ $model }}"
placeholder="{{ $placeholder }}"
autocomplete="off"
{{ $attributes->except('value')->merge([
'class' => 'block w-full rounded-xl border border-zinc-700 bg-zinc-950 px-4 py-3 text-sm text-zinc-100 shadow-sm outline-none transition-colors duration-150 placeholder:text-zinc-500 focus:border-blue-500 focus:ring-2 focus:ring-blue-500/40',
]) }}
/>
</div>
</div>
@@ -3,6 +3,10 @@
'resources/css/app.css',
'resources/js/app.js',
])
@vite([
'Resources/assets/css/app.css',
'Resources/assets/js/app.js',
], 'build/helpdesk')
@include('helpdesk::partials.page-header', [
'eyebrow' => 'Helpdesk',
@@ -51,6 +55,7 @@
<select
id="company_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="company_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -76,10 +81,12 @@
<select
id="board_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="board_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
data-dusk="ticket-board"
>
<option value="">No board</option>
@foreach ($boards as $board)
<option value="{{ $board->id }}" @selected((int) $board_id === (int) $board->id)>{{ $board->name }}{{ $board->owner ? ' · '.$board->owner->name : '' }}</option>
@endforeach
@@ -100,6 +107,7 @@
<select
id="priority_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="priority_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
data-dusk="ticket-priority"
@@ -125,6 +133,7 @@
<select
id="category_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="category_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -149,6 +158,7 @@
<select
id="project_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="project_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -173,6 +183,7 @@
<select
id="team_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="team_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -236,9 +247,13 @@
</div>
<div class="xl:col-span-2">
<label class="block text-sm font-semibold text-zinc-200" for="due_at">Due date</label>
<input id="due_at" type="date" wire:model.defer="due_at" class="mt-2 block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
<x-helpdesk::date-picker
id="due_at"
model="due_at"
label="Due date"
placeholder="Select due date"
value="{{ $due_at }}"
/>
@error('due_at')
<p class="mt-2 text-sm text-red-500">{{ $message }}</p>
@@ -3,6 +3,10 @@
'resources/css/app.css',
'resources/js/app.js',
])
@vite([
'Resources/assets/css/app.css',
'Resources/assets/js/app.js',
], 'build/helpdesk')
@include('helpdesk::partials.page-header', [
'eyebrow' => 'Helpdesk',
@@ -70,6 +74,7 @@
<select
id="company_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="company_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -93,6 +98,7 @@
<select
id="board_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="board_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
data-dusk="ticket-edit-board"
@@ -118,10 +124,12 @@
<select
id="status_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="status_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
data-dusk="ticket-edit-status"
>
<option value="">No status</option>
@foreach ($statuses as $status)
<option value="{{ $status->id }}" @selected((string) $status_id === (string) $status->id)>{{ $status->name }}</option>
@endforeach
@@ -142,10 +150,12 @@
<select
id="priority_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="priority_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
data-dusk="ticket-edit-priority"
>
<option value="">Select priority</option>
@foreach ($priorities as $priority)
<option value="{{ $priority->id }}" @selected((string) $priority_id === (string) $priority->id)>{{ $priority->name }}</option>
@endforeach
@@ -164,6 +174,7 @@
<select
id="agent_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="agent_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
data-dusk="ticket-edit-agent"
@@ -189,6 +200,7 @@
<select
id="category_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="category_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -213,6 +225,7 @@
<select
id="project_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="project_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -237,6 +250,7 @@
<select
id="team_id"
data-helpdesk-select2
data-placeholder="Select option"
data-wire-model="team_id"
class="block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500"
>
@@ -300,9 +314,13 @@
</div>
<div class="xl:col-span-2">
<label class="block text-sm font-semibold text-zinc-200" for="due_at">Due date</label>
<input id="due_at" type="date" wire:model.defer="due_at" class="mt-2 block w-full rounded-xl border-zinc-700 bg-zinc-950 text-zinc-100 shadow-sm focus:border-blue-500 focus:ring-blue-500">
<x-helpdesk::date-picker
id="due_at"
model="due_at"
label="Due date"
placeholder="Select due date"
value="{{ $due_at }}"
/>
@error('due_at')
<p class="mt-2 text-sm text-red-500">{{ $message }}</p>
+9
View File
@@ -174,3 +174,12 @@ versions:
- Fixed malformed Helpdesk settings action buttons that caused Blade parse errors.
- Applied explicit coloured action buttons across settings tables, settings forms and Kanban board configuration actions.
- Kept module.json version in sync with changelog.yaml.
"1.3.7":
changed:
- Fixed ticket create/edit clear actions by adding public Livewire clearForm methods to both components.
- Stabilised Select2 clearing by loading module assets on ticket forms, adding placeholder support, manually syncing Select2 changes back to Livewire and clearing browser widgets after Livewire reset events.
- Replaced native due date inputs on ticket create/edit with a reusable Helpdesk Flatpickr date-picker component.
- Added Flatpickr module dependency and dark Helpdesk calendar styling.
- Kept module.json version in sync with changelog.yaml.
+1 -1
View File
@@ -22,5 +22,5 @@
"Modules\\Helpdesk\\Providers\\HelpdeskServiceProvider"
],
"files": [],
"version": "1.3.6"
"version": "1.3.7"
}
+2 -1
View File
@@ -12,6 +12,7 @@
},
"dependencies": {
"jquery": "3.7.1",
"select2": "^4.1.0"
"select2": "^4.1.0",
"flatpickr": "^4.6.13"
}
}