fixed tags and also calander
This commit is contained in:
@@ -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', [
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -22,5 +22,5 @@
|
||||
"Modules\\Helpdesk\\Providers\\HelpdeskServiceProvider"
|
||||
],
|
||||
"files": [],
|
||||
"version": "1.3.6"
|
||||
"version": "1.3.7"
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"jquery": "3.7.1",
|
||||
"select2": "^4.1.0"
|
||||
"select2": "^4.1.0",
|
||||
"flatpickr": "^4.6.13"
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user