added jquery and also fixed fontawsome
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
@props(['comments', 'level' => 0])
|
||||
|
||||
<div class="space-y-3">
|
||||
@foreach ($comments as $comment)
|
||||
@php
|
||||
$commentUser = $comment->relationLoaded('user') ? $comment->getRelation('user') : null;
|
||||
$commentAttachments = $comment->relationLoaded('attachments') ? $comment->getRelation('attachments') : collect();
|
||||
$commentReplies = $comment->relationLoaded('replies') ? $comment->getRelation('replies') : collect();
|
||||
@endphp
|
||||
|
||||
<div class="rounded-2xl border border-zinc-200 bg-white p-4 shadow-sm dark:border-zinc-700 dark:bg-zinc-900" style="margin-left: {{ min((int) $level, 4) * 1.25 }}rem">
|
||||
<div class="flex items-start justify-between gap-3">
|
||||
<div>
|
||||
<div class="font-medium text-zinc-900 dark:text-zinc-100">
|
||||
{{ $commentUser?->name ?? 'Unknown user' }}
|
||||
</div>
|
||||
<div class="text-xs text-zinc-500">
|
||||
{{ $comment->created_at?->format('d M Y H:i') }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@if ($comment->is_internal)
|
||||
<flux:badge color="amber">Internal</flux:badge>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<div class="prose prose-sm mt-3 max-w-none dark:prose-invert">
|
||||
{!! $comment->body !!}
|
||||
</div>
|
||||
|
||||
@if ($commentAttachments->isNotEmpty())
|
||||
<div class="mt-3 flex flex-wrap gap-2">
|
||||
@foreach ($commentAttachments as $attachment)
|
||||
<a href="{{ $attachment->url() }}" target="_blank" class="rounded-lg border border-zinc-200 px-3 py-1 text-xs text-zinc-600 hover:bg-zinc-50 dark:border-zinc-700 dark:text-zinc-300 dark:hover:bg-zinc-800">
|
||||
{{ $attachment->original_name }}
|
||||
</a>
|
||||
@endforeach
|
||||
</div>
|
||||
@endif
|
||||
|
||||
<div class="mt-3 flex justify-end">
|
||||
<flux:button size="sm" variant="ghost" wire:click="startReply({{ $comment->id }})">Reply</flux:button>
|
||||
</div>
|
||||
|
||||
@if (($reply_parent_id ?? null) === $comment->id)
|
||||
<form wire:submit="addReply" class="mt-4 rounded-xl border border-blue-200 bg-blue-50 p-4 dark:border-blue-900 dark:bg-blue-950/40">
|
||||
<x-helpdesk::html-editor wire:key="reply-editor-{{ $comment->id }}" wire:model="replyBody" label="Reply" rows="4" placeholder="Write a reply..." />
|
||||
|
||||
<div class="mt-4 flex justify-end gap-2">
|
||||
<flux:button type="button" wire:click="cancelReply" variant="ghost">Cancel</flux:button>
|
||||
<flux:button type="submit" variant="primary" class="!bg-emerald-600 !text-white hover:!bg-emerald-700">Post reply</flux:button>
|
||||
</div>
|
||||
</form>
|
||||
@endif
|
||||
|
||||
@if ($commentReplies->isNotEmpty())
|
||||
<div class="mt-4">
|
||||
@include('helpdesk::partials.comment-thread', [
|
||||
'comments' => $commentReplies,
|
||||
'level' => ((int) $level) + 1,
|
||||
])
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
@@ -0,0 +1,27 @@
|
||||
<div class="mb-8 overflow-hidden rounded-3xl border border-slate-800 bg-slate-950 shadow-sm">
|
||||
<div class="px-6 py-8 text-white">
|
||||
<div class="flex flex-col gap-4 lg:flex-row lg:items-center lg:justify-between">
|
||||
<div>
|
||||
<p class="text-sm font-semibold uppercase tracking-[0.3em] text-blue-300">
|
||||
{{ $eyebrow ?? 'Helpdesk' }}
|
||||
</p>
|
||||
|
||||
<h1 class="mt-3 text-3xl font-bold tracking-tight">
|
||||
{{ $title ?? 'Helpdesk' }}
|
||||
</h1>
|
||||
|
||||
@if(! empty($subtitle))
|
||||
<p class="mt-2 max-w-3xl text-sm text-slate-300">
|
||||
{{ $subtitle }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@isset($actions)
|
||||
<div class="flex flex-wrap items-center gap-3">
|
||||
{{ $actions }}
|
||||
</div>
|
||||
@endisset
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,117 @@
|
||||
@once
|
||||
<style>
|
||||
.select2-container { width: 100% !important; }
|
||||
.select2-container--default .select2-selection--single {
|
||||
min-height: 2.75rem;
|
||||
border-radius: 0.75rem;
|
||||
border-color: rgb(63 63 70);
|
||||
background: rgb(9 9 11);
|
||||
color: rgb(244 244 245);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.select2-container--default .select2-selection--single .select2-selection__rendered {
|
||||
color: rgb(244 244 245);
|
||||
line-height: 2.75rem;
|
||||
padding-left: 0.85rem;
|
||||
}
|
||||
.select2-container--default .select2-selection--single .select2-selection__arrow {
|
||||
height: 2.75rem;
|
||||
}
|
||||
.select2-dropdown {
|
||||
border-color: rgb(63 63 70);
|
||||
background: rgb(24 24 27);
|
||||
color: rgb(244 244 245);
|
||||
}
|
||||
.select2-container--default .select2-results__option--highlighted[aria-selected] {
|
||||
background: rgb(37 99 235);
|
||||
color: white;
|
||||
}
|
||||
.select2-container--default .select2-results__option[aria-selected=true] {
|
||||
background: rgb(39 39 42);
|
||||
color: white;
|
||||
}
|
||||
.select2-search__field {
|
||||
background: rgb(9 9 11);
|
||||
color: rgb(244 244 245);
|
||||
border-color: rgb(63 63 70) !important;
|
||||
}
|
||||
</style>
|
||||
@endonce
|
||||
|
||||
<script>
|
||||
(function () {
|
||||
function loadScript(src, callback) {
|
||||
const existing = document.querySelector('script[src="' + src + '"]');
|
||||
if (existing) {
|
||||
existing.addEventListener('load', callback, { once: true });
|
||||
if (existing.dataset.loaded === '1') callback();
|
||||
return;
|
||||
}
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.src = src;
|
||||
script.onload = function () {
|
||||
script.dataset.loaded = '1';
|
||||
callback();
|
||||
};
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
function loadStyle(href) {
|
||||
if (document.querySelector('link[href="' + href + '"]')) return;
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = href;
|
||||
document.head.appendChild(link);
|
||||
}
|
||||
|
||||
function initialiseHelpdeskSelects() {
|
||||
if (!window.jQuery || !window.jQuery.fn || !window.jQuery.fn.select2) return;
|
||||
|
||||
window.jQuery('[data-helpdesk-select2]').each(function () {
|
||||
const select = window.jQuery(this);
|
||||
|
||||
if (select.data('select2')) {
|
||||
select.select2('destroy');
|
||||
}
|
||||
|
||||
select.select2({
|
||||
width: '100%',
|
||||
placeholder: this.querySelector('option[value=""]')?.textContent || 'Select option',
|
||||
allowClear: true
|
||||
});
|
||||
|
||||
select.off('change.helpdesk').on('change.helpdesk', function () {
|
||||
this.dispatchEvent(new Event('change', { bubbles: true }));
|
||||
this.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function bootHelpdeskSelects() {
|
||||
loadStyle('https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css');
|
||||
|
||||
const bootSelect2 = function () {
|
||||
if (window.jQuery && window.jQuery.fn && window.jQuery.fn.select2) {
|
||||
initialiseHelpdeskSelects();
|
||||
return;
|
||||
}
|
||||
|
||||
loadScript('https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js', initialiseHelpdeskSelects);
|
||||
};
|
||||
|
||||
if (window.jQuery) {
|
||||
bootSelect2();
|
||||
return;
|
||||
}
|
||||
|
||||
console.warn('Helpdesk Select2 requires global jQuery from resources/js/app.js. Run npm install jquery and npm run build.');
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', bootHelpdeskSelects);
|
||||
document.addEventListener('livewire:navigated', bootHelpdeskSelects);
|
||||
document.addEventListener('livewire:updated', bootHelpdeskSelects);
|
||||
bootHelpdeskSelects();
|
||||
})();
|
||||
</script>
|
||||
@@ -0,0 +1,40 @@
|
||||
@php
|
||||
$helpdeskEnabled = Route::has('helpdesk.index');
|
||||
|
||||
if (class_exists(\Nwidart\Modules\Facades\Module::class)) {
|
||||
$helpdeskModule = \Nwidart\Modules\Facades\Module::find('Helpdesk');
|
||||
$helpdeskEnabled = $helpdeskModule !== null && $helpdeskModule->isEnabled() && Route::has('helpdesk.index');
|
||||
}
|
||||
@endphp
|
||||
|
||||
@if($helpdeskEnabled)
|
||||
<div class="wms-sidebar-group">
|
||||
<div class="wms-sidebar-heading" data-wms-sidebar-label>{{ __('Support') }}</div>
|
||||
|
||||
<a href="{{ route('helpdesk.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.index')) is-active @endif" title="{{ __('Helpdesk') }}">
|
||||
<i class="fa-solid fa-headset wms-sidebar-icon" aria-hidden="true"></i>
|
||||
<span data-wms-sidebar-label>{{ __('Helpdesk') }}</span>
|
||||
</a>
|
||||
|
||||
@if(Route::has('helpdesk.tickets.index'))
|
||||
<a href="{{ route('helpdesk.tickets.index') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.tickets.*')) is-active @endif" title="{{ __('Tickets') }}">
|
||||
<i class="fa-solid fa-ticket wms-sidebar-icon" aria-hidden="true"></i>
|
||||
<span data-wms-sidebar-label>{{ __('Tickets') }}</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if(Route::has('helpdesk.kanban'))
|
||||
<a href="{{ route('helpdesk.kanban') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.kanban')) is-active @endif" title="{{ __('Kanban') }}">
|
||||
<i class="fa-solid fa-table-columns wms-sidebar-icon" aria-hidden="true"></i>
|
||||
<span data-wms-sidebar-label>{{ __('Kanban') }}</span>
|
||||
</a>
|
||||
@endif
|
||||
|
||||
@if(Route::has('helpdesk.settings'))
|
||||
<a href="{{ route('helpdesk.settings') }}" wire:navigate class="wms-sidebar-link @if(request()->routeIs('helpdesk.settings')) is-active @endif" title="{{ __('Support Settings') }}">
|
||||
<i class="fa-solid fa-gears wms-sidebar-icon" aria-hidden="true"></i>
|
||||
<span data-wms-sidebar-label>{{ __('Support Settings') }}</span>
|
||||
</a>
|
||||
@endif
|
||||
</div>
|
||||
@endif
|
||||
Reference in New Issue
Block a user