Compare commits
7
Commits
develop
...
fe68238143
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fe68238143 | ||
|
|
2f422a5320 | ||
|
|
18e95bc653 | ||
|
|
942645f880 | ||
|
|
dc6dd989ed | ||
|
|
c71479d119 | ||
|
|
8db97cd60c |
@@ -8,6 +8,7 @@ use App\Http\Controllers\Controller;
|
|||||||
use Illuminate\Http\RedirectResponse;
|
use Illuminate\Http\RedirectResponse;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\UploadedFile;
|
use Illuminate\Http\UploadedFile;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
|
|||||||
+23
-3
@@ -29,10 +29,10 @@ host('develop')
|
|||||||
->set('deploy_path', '/var/www/helpdesk_dev');
|
->set('deploy_path', '/var/www/helpdesk_dev');
|
||||||
|
|
||||||
host('mpba')
|
host('mpba')
|
||||||
->set('hostname', 'helpdesk.mpba.dev')
|
->set('hostname', 'sirius.absdev.net')
|
||||||
->set('remote_user', 'mag')
|
->set('remote_user', 'mag')
|
||||||
->set('branch', 'main')
|
->set('branch', 'main')
|
||||||
->set('deploy_path', '/var/www/helpdesk_mpba');
|
->set('deploy_path', '/var/www/helpdesk');
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Install the root npm tree, then every module that owns its own lock file,
|
* Install the root npm tree, then every module that owns its own lock file,
|
||||||
@@ -86,9 +86,29 @@ task('artisan:clear', function (): void {
|
|||||||
});
|
});
|
||||||
|
|
||||||
task('services:restart', function (): void {
|
task('services:restart', function (): void {
|
||||||
|
// Validate and reload nginx.
|
||||||
run('sudo -n nginx -t');
|
run('sudo -n nginx -t');
|
||||||
run('sudo -n systemctl reload nginx');
|
run('sudo -n systemctl reload nginx');
|
||||||
run('sudo -n systemctl restart php8.3-fpm');
|
|
||||||
|
// Detect the PHP-FPM socket configured in nginx.
|
||||||
|
$socket = trim(run(
|
||||||
|
"sudo -n nginx -T 2>/dev/null"
|
||||||
|
. " | grep -oE 'php[0-9]+\\.[0-9]+-fpm\\.sock'"
|
||||||
|
. " | sort -Vu"
|
||||||
|
. " | tail -n 1"
|
||||||
|
));
|
||||||
|
|
||||||
|
if ($socket === '') {
|
||||||
|
throw new \RuntimeException(
|
||||||
|
'Unable to detect the PHP-FPM version from nginx configuration.'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Convert php8.5-fpm.sock into php8.5-fpm.
|
||||||
|
$service = str_replace('.sock', '', $socket);
|
||||||
|
writeln("<info>Detected PHP-FPM service: {$service}</info>");
|
||||||
|
// Restart the detected PHP-FPM service.
|
||||||
|
run("sudo -n systemctl restart {$service}");
|
||||||
|
writeln("<info>PHP-FPM restarted successfully.</info>");
|
||||||
});
|
});
|
||||||
|
|
||||||
after('deploy:update_code', 'deploy:write_revision_file');
|
after('deploy:update_code', 'deploy:write_revision_file');
|
||||||
|
|||||||
Executable → Regular
+15
-14
@@ -10,10 +10,11 @@
|
|||||||
class="space-y-2"
|
class="space-y-2"
|
||||||
x-data="{
|
x-data="{
|
||||||
model: @js($model),
|
model: @js($model),
|
||||||
value: @entangle($model),
|
value: '',
|
||||||
init() {
|
init() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.writeEditorValue(this.value || '');
|
this.value = this.$wire.get(this.model) || '';
|
||||||
|
this.writeEditorValue(this.value);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
writeEditorValue(value) {
|
writeEditorValue(value) {
|
||||||
@@ -30,29 +31,29 @@
|
|||||||
|
|
||||||
this.$refs.editor.textContent = nextValue;
|
this.$refs.editor.textContent = nextValue;
|
||||||
},
|
},
|
||||||
syncToLivewire(live = true) {
|
syncToLivewire(live = false) {
|
||||||
this.value = this.$refs.editor?.innerText || '';
|
const text = this.$refs.editor?.innerText || '';
|
||||||
|
this.value = text;
|
||||||
if (this.$refs.input) {
|
if (this.$refs.input) {
|
||||||
this.$refs.input.value = this.value;
|
this.$refs.input.value = text;
|
||||||
}
|
}
|
||||||
|
// Update Livewire's local state before the save request is assembled.
|
||||||
this.$wire.set(this.model, this.value, live);
|
this.$wire.set(this.model, text, live);
|
||||||
},
|
},
|
||||||
resetEditor() {
|
resetEditor() {
|
||||||
this.value = '';
|
this.value = '';
|
||||||
this.writeEditorValue('');
|
this.writeEditorValue('');
|
||||||
this.syncToLivewire(true);
|
this.syncToLivewire(false);
|
||||||
},
|
},
|
||||||
runCommand(command) {
|
runCommand(command) {
|
||||||
this.$refs.editor?.focus();
|
this.$refs.editor?.focus();
|
||||||
document.execCommand(command, false, null);
|
document.execCommand(command, false, null);
|
||||||
this.syncToLivewire(true);
|
this.syncToLivewire(false);
|
||||||
},
|
},
|
||||||
wrapBlock(tagName) {
|
wrapBlock(tagName) {
|
||||||
this.$refs.editor?.focus();
|
this.$refs.editor?.focus();
|
||||||
document.execCommand('formatBlock', false, tagName);
|
document.execCommand('formatBlock', false, tagName);
|
||||||
this.syncToLivewire(true);
|
this.syncToLivewire(false);
|
||||||
},
|
},
|
||||||
}"
|
}"
|
||||||
x-on:helpdesk-editor-sync.window="if (! $event.detail?.model || $event.detail.model === @js($model)) syncToLivewire($event.detail?.live ?? true)"
|
x-on:helpdesk-editor-sync.window="if (! $event.detail?.model || $event.detail.model === @js($model)) syncToLivewire($event.detail?.live ?? true)"
|
||||||
@@ -116,14 +117,14 @@
|
|||||||
data-helpdesk-sync-target="{{ $model }}"
|
data-helpdesk-sync-target="{{ $model }}"
|
||||||
data-helpdesk-editor-model="{{ $model }}"
|
data-helpdesk-editor-model="{{ $model }}"
|
||||||
@if ($editorDusk) data-dusk="{{ $editorDusk }}" dusk="{{ $editorDusk }}" @endif
|
@if ($editorDusk) data-dusk="{{ $editorDusk }}" dusk="{{ $editorDusk }}" @endif
|
||||||
x-on:paste="syncToLivewire(false)"
|
x-on:input="syncToLivewire(false)"
|
||||||
x-on:blur="syncToLivewire(true)"
|
x-on:paste="$nextTick(() => syncToLivewire(false))"
|
||||||
|
x-on:blur="syncToLivewire(false)"
|
||||||
class="helpdesk-rich-editor block min-h-[14rem] w-full overflow-y-auto whitespace-pre-wrap break-words border-0 bg-zinc-950 px-5 py-4 text-base leading-7 text-zinc-100 outline-none transition placeholder:text-zinc-500 empty:before:pointer-events-none empty:before:text-zinc-500 empty:before:content-[attr(data-placeholder)] focus:ring-2 focus:ring-blue-500"
|
class="helpdesk-rich-editor block min-h-[14rem] w-full overflow-y-auto whitespace-pre-wrap break-words border-0 bg-zinc-950 px-5 py-4 text-base leading-7 text-zinc-100 outline-none transition placeholder:text-zinc-500 empty:before:pointer-events-none empty:before:text-zinc-500 empty:before:content-[attr(data-placeholder)] focus:ring-2 focus:ring-blue-500"
|
||||||
></div>
|
></div>
|
||||||
|
|
||||||
<textarea
|
<textarea
|
||||||
x-ref="input"
|
x-ref="input"
|
||||||
wire:model.defer="{{ $model }}"
|
|
||||||
spellcheck="true"
|
spellcheck="true"
|
||||||
lang="en-GB"
|
lang="en-GB"
|
||||||
autocorrect="on"
|
autocorrect="on"
|
||||||
|
|||||||
Executable → Regular
+5
-25
@@ -18,33 +18,9 @@
|
|||||||
x-on:submit.capture="
|
x-on:submit.capture="
|
||||||
if (helpdeskAttachmentsUploading) {
|
if (helpdeskAttachmentsUploading) {
|
||||||
$event.preventDefault();
|
$event.preventDefault();
|
||||||
|
$event.stopImmediatePropagation();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const editor = document.querySelector('[data-helpdesk-sync-target="body"], [data-helpdesk-editor-model="body"]');
|
|
||||||
const target = Array.from(document.querySelectorAll('textarea')).find(function (textarea) {
|
|
||||||
|
|
||||||
return textarea.getAttribute('wire:model.defer') === 'body'
|
|
||||||
|
|
||||||
|| textarea.getAttribute('wire:model') === 'body'
|
|
||||||
|
|
||||||
|| textarea.getAttribute('name') === 'body'
|
|
||||||
|
|
||||||
|| textarea.id === 'body';
|
|
||||||
|
|
||||||
});
|
|
||||||
const body = (editor?.innerText || editor?.textContent || editor?.value || '').trim();
|
|
||||||
|
|
||||||
if (target) {
|
|
||||||
target.value = body;
|
|
||||||
target.dispatchEvent(new Event('input', { bubbles: true }));
|
|
||||||
target.dispatchEvent(new Event('change', { bubbles: true }));
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($wire) {
|
|
||||||
$wire.set('body', body, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
$dispatch('helpdesk-editor-sync', { model: 'body', live: false });
|
$dispatch('helpdesk-editor-sync', { model: 'body', live: false });
|
||||||
"
|
"
|
||||||
class="helpdesk-ticket-form space-y-6"
|
class="helpdesk-ticket-form space-y-6"
|
||||||
@@ -245,6 +221,10 @@
|
|||||||
editor-dusk="ticket-body-editor"
|
editor-dusk="ticket-body-editor"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
@error('body')
|
||||||
|
<p class="mt-2 text-sm text-red-500" role="alert">{{ $message }}</p>
|
||||||
|
@enderror
|
||||||
|
|
||||||
<p class="mt-2 flex items-center gap-2 text-xs font-medium text-zinc-400">
|
<p class="mt-2 flex items-center gap-2 text-xs font-medium text-zinc-400">
|
||||||
<i class="fa-solid fa-circle-info text-blue-400" aria-hidden="true"></i>
|
<i class="fa-solid fa-circle-info text-blue-400" aria-hidden="true"></i>
|
||||||
Rich formatting is available. Browser spelling suggestions appear by right-clicking or Ctrl-clicking red-underlined words.
|
Rich formatting is available. Browser spelling suggestions appear by right-clicking or Ctrl-clicking red-underlined words.
|
||||||
|
|||||||
@@ -122,7 +122,7 @@
|
|||||||
<span
|
<span
|
||||||
class="inline-flex shrink-0 items-center gap-2 rounded-xl bg-white/15 px-3 py-1.5 text-xs font-extrabold ring-1 ring-white/20">
|
class="inline-flex shrink-0 items-center gap-2 rounded-xl bg-white/15 px-3 py-1.5 text-xs font-extrabold ring-1 ring-white/20">
|
||||||
<i class="fa-solid fa-paperclip text-xs" aria-hidden="true"></i>
|
<i class="fa-solid fa-paperclip text-xs" aria-hidden="true"></i>
|
||||||
{{ $ticket->attachments->count() }} file{{ $ticket->attachments->count() === 1 ? '' : 's' }}
|
{{ $ticket->attachments->filter(fn ($attachment) => ! $attachment->isDeletedAttachment())->count() }} file{{ $ticket->attachments->filter(fn ($attachment) => ! $attachment->isDeletedAttachment())->count() === 1 ? '' : 's' }}
|
||||||
<i class="fa-solid fa-chevron-right transition group-open:rotate-90" aria-hidden="true"></i>
|
<i class="fa-solid fa-chevron-right transition group-open:rotate-90" aria-hidden="true"></i>
|
||||||
</span>
|
</span>
|
||||||
</summary>
|
</summary>
|
||||||
@@ -510,12 +510,12 @@
|
|||||||
class="inline-flex cursor-pointer items-center justify-center rounded-lg bg-blue-600 px-3 py-2 text-xs font-bold text-white shadow-sm transition hover:bg-blue-700 focus-within:outline-none focus-within:ring-2 focus-within:ring-blue-400/70">
|
class="inline-flex cursor-pointer items-center justify-center rounded-lg bg-blue-600 px-3 py-2 text-xs font-bold text-white shadow-sm transition hover:bg-blue-700 focus-within:outline-none focus-within:ring-2 focus-within:ring-blue-400/70">
|
||||||
<i class="fa-solid fa-paperclip mr-2 text-xs" aria-hidden="true"></i>
|
<i class="fa-solid fa-paperclip mr-2 text-xs" aria-hidden="true"></i>
|
||||||
<span>Choose files</span>
|
<span>Choose files</span>
|
||||||
<input name="comment_attachments[]" type="file" multiple accept="{{ $helpdeskAttachmentAccept }}" class="sr-only"
|
<input name="attachments[]" type="file" multiple accept="{{ $helpdeskAttachmentAccept }}" class="sr-only"
|
||||||
data-helpdesk-file-input>
|
data-helpdesk-file-input>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@error('comment_attachments')
|
@error('attachments')
|
||||||
<p class="mt-2 text-xs font-semibold text-red-600 dark:text-red-400">{{ $message }}</p>
|
<p class="mt-2 text-xs font-semibold text-red-600 dark:text-red-400">{{ $message }}</p>
|
||||||
@enderror
|
@enderror
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@
|
|||||||
Respond
|
Respond
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
@if (auth()->user()?->isMpbaPlatformAdmin())
|
@if (auth()->user()?->isHelpdeskAdmin())
|
||||||
<form method="POST"
|
<form method="POST"
|
||||||
action="{{ route('helpdesk.tickets.comments.destroy', [$currentTicket, $comment]) }}"
|
action="{{ route('helpdesk.tickets.comments.destroy', [$currentTicket, $comment]) }}"
|
||||||
onsubmit="return confirm('Delete this response? This will remove it from the visible conversation but keep the replication identity/audit trail.');">
|
onsubmit="return confirm('Delete this response? This will remove it from the visible conversation but keep the replication identity/audit trail.');">
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
JAVA_HOME="/opt/homebrew/opt/openjdk" \
|
|
||||||
PATH="/opt/homebrew/opt/openjdk/bin:$PATH" \
|
|
||||||
sonar-scanner \
|
|
||||||
-Dsonar.projectKey=Helpdesk \
|
|
||||||
-Dsonar.sources=. \
|
|
||||||
-Dsonar.host.url=http://127.0.0.1:9001 \
|
|
||||||
-Dsonar.login=sqp_36027127786b9a8ed4d0d165bdb3405ed07421d8
|
|
||||||
Executable
+12
@@ -0,0 +1,12 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
# sqp_c0b887930297d93cf088476023c244d901c51204
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
JAVA_HOME="/opt/homebrew/opt/openjdk" \
|
||||||
|
PATH="/opt/homebrew/opt/openjdk/bin:$PATH" \
|
||||||
|
sonar-scanner \
|
||||||
|
-Dsonar.projectKey=Helpdesk-System \
|
||||||
|
-Dsonar.sources=. \
|
||||||
|
-Dsonar.host.url=https://sonarcube.absdev.net \
|
||||||
|
-Dsonar.token="${SONAR_TOKEN:?SONAR_TOKEN is not set}"
|
||||||
Reference in New Issue
Block a user