installation
This commit is contained in:
parent
26c455a51e
commit
c6cb25129c
90
inbound.php
90
inbound.php
@ -70,6 +70,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$id = $_POST['id'] ?? 0;
|
$id = $_POST['id'] ?? 0;
|
||||||
|
|
||||||
if ($ref_no && $subject) {
|
if ($ref_no && $subject) {
|
||||||
|
$should_notify = false;
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
@ -78,7 +79,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$mail_id = db()->lastInsertId();
|
$mail_id = db()->lastInsertId();
|
||||||
|
|
||||||
if ($assigned_to) {
|
if ($assigned_to) {
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
$should_notify = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تمت إضافة البريد بنجاح';
|
$_SESSION['success'] = 'تمت إضافة البريد بنجاح';
|
||||||
@ -93,7 +94,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $id]);
|
||||||
|
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
$should_notify = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تم تحديث البيانات بنجاح';
|
$_SESSION['success'] = 'تم تحديث البيانات بنجاح';
|
||||||
@ -117,9 +118,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
db()->commit();
|
db()->commit();
|
||||||
|
|
||||||
|
// Notify after commit to avoid holding locks during email sending
|
||||||
|
if ($should_notify) {
|
||||||
|
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
||||||
|
}
|
||||||
|
|
||||||
redirect('inbound.php');
|
redirect('inbound.php');
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
db()->rollBack();
|
if (db()->inTransaction()) db()->rollBack();
|
||||||
if ($e->getCode() == 23000) {
|
if ($e->getCode() == 23000) {
|
||||||
$error = 'رقم القيد مستخدم مسبقاً';
|
$error = 'رقم القيد مستخدم مسبقاً';
|
||||||
} else {
|
} else {
|
||||||
@ -404,7 +411,7 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="form-label fw-bold">الوصف / ملاحظات</label>
|
<label class="form-label fw-bold">الوصف / ملاحظات</label>
|
||||||
<textarea name="description" id="modalDescription" class="form-control" rows="3"></textarea>
|
<textarea name="description" id="modalDescription" class="form-control" rows="5"></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<label class="form-label fw-bold">المرفقات</label>
|
<label class="form-label fw-bold">المرفقات</label>
|
||||||
@ -445,8 +452,27 @@ function getStatusBadgeInList($mail) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
let descriptionEditor;
|
||||||
let mailModal;
|
let mailModal;
|
||||||
|
|
||||||
|
function initEditors() {
|
||||||
|
if (typeof ClassicEditor === 'undefined') {
|
||||||
|
console.error('CKEditor not loaded');
|
||||||
|
return Promise.resolve();
|
||||||
|
}
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
language: 'ar',
|
||||||
|
toolbar: ['heading', '|', 'bold', 'italic', 'link', 'bulletedList', 'numberedList', 'undo', 'redo']
|
||||||
|
};
|
||||||
|
|
||||||
|
return ClassicEditor.create(document.querySelector('#modalDescription'), config)
|
||||||
|
.then(editor => { descriptionEditor = editor; })
|
||||||
|
.catch(err => {
|
||||||
|
console.error('CKEditor Init Error:', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function openMailModal(action, data = null) {
|
function openMailModal(action, data = null) {
|
||||||
if (!mailModal) {
|
if (!mailModal) {
|
||||||
const modalEl = document.getElementById('mailModal');
|
const modalEl = document.getElementById('mailModal');
|
||||||
@ -469,7 +495,6 @@ function openMailModal(action, data = null) {
|
|||||||
sender: document.getElementById('modalSender'),
|
sender: document.getElementById('modalSender'),
|
||||||
recipient: document.getElementById('modalRecipient'),
|
recipient: document.getElementById('modalRecipient'),
|
||||||
subject: document.getElementById('modalSubject'),
|
subject: document.getElementById('modalSubject'),
|
||||||
description: document.getElementById('modalDescription'),
|
|
||||||
status_id: document.getElementById('modalStatusId'),
|
status_id: document.getElementById('modalStatusId'),
|
||||||
assigned_to: document.getElementById('modalAssignedTo')
|
assigned_to: document.getElementById('modalAssignedTo')
|
||||||
};
|
};
|
||||||
@ -487,37 +512,49 @@ function openMailModal(action, data = null) {
|
|||||||
else fields[key].value = '';
|
else fields[key].value = '';
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (descriptionEditor) descriptionEditor.setData('');
|
||||||
|
else document.getElementById('modalDescription').value = '';
|
||||||
} else {
|
} else {
|
||||||
label.textContent = 'تعديل البريد الوارد';
|
label.textContent = 'تعديل البريد الوارد';
|
||||||
modalId.value = data.id;
|
modalId.value = data.id;
|
||||||
Object.keys(fields).forEach(key => {
|
Object.keys(fields).forEach(key => {
|
||||||
if (fields[key]) fields[key].value = data[key] || '';
|
if (fields[key]) fields[key].value = data[key] || '';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (descriptionEditor) descriptionEditor.setData(data.description || '');
|
||||||
|
else document.getElementById('modalDescription').value = data.description || '';
|
||||||
}
|
}
|
||||||
|
|
||||||
mailModal.show();
|
mailModal.show();
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
<?php if ($deepLinkData): ?>
|
initEditors().finally(() => {
|
||||||
openMailModal('edit', <?= json_encode($deepLinkData) ?>);
|
<?php if ($deepLinkData): ?>
|
||||||
<?php elseif ($error && isset($_POST['action'])): ?>
|
openMailModal('edit', <?= json_encode($deepLinkData) ?>);
|
||||||
const errorData = <?= json_encode([
|
<?php elseif ($error && isset($_POST['action'])): ?>
|
||||||
'id' => $_POST['id'] ?? 0,
|
const errorData = <?= json_encode([
|
||||||
'ref_no' => $_POST['ref_no'] ?? '',
|
'id' => $_POST['id'] ?? 0,
|
||||||
'date_registered' => $_POST['date_registered'] ?? date('Y-m-d'),
|
'ref_no' => $_POST['ref_no'] ?? '',
|
||||||
'due_date' => $_POST['due_date'] ?? '',
|
'date_registered' => $_POST['date_registered'] ?? date('Y-m-d'),
|
||||||
'sender' => $_POST['sender'] ?? '',
|
'due_date' => $_POST['due_date'] ?? '',
|
||||||
'recipient' => $_POST['recipient'] ?? '',
|
'sender' => $_POST['sender'] ?? '',
|
||||||
'subject' => $_POST['subject'] ?? '',
|
'recipient' => $_POST['recipient'] ?? '',
|
||||||
'description' => $_POST['description'] ?? '',
|
'subject' => $_POST['subject'] ?? '',
|
||||||
'status_id' => $_POST['status_id'] ?? $default_status_id,
|
'description' => $_POST['description'] ?? '',
|
||||||
'assigned_to' => $_POST['assigned_to'] ?? ''
|
'status_id' => $_POST['status_id'] ?? $default_status_id,
|
||||||
]) ?>;
|
'assigned_to' => $_POST['assigned_to'] ?? ''
|
||||||
openMailModal('<?= $_POST['action'] ?>', errorData);
|
]) ?>;
|
||||||
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
openMailModal('<?= $_POST['action'] ?>', errorData);
|
||||||
openMailModal('add');
|
<?php elseif (isset($_GET['action']) && $_GET['action'] === 'add'): ?>
|
||||||
<?php endif; ?>
|
openMailModal('add');
|
||||||
|
<?php endif; ?>
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('mailForm').addEventListener('submit', function() {
|
||||||
|
if (descriptionEditor) descriptionEditor.updateSourceElement();
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
function confirmDelete(id) {
|
function confirmDelete(id) {
|
||||||
@ -546,6 +583,11 @@ function confirmDelete(id) {
|
|||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.ck-editor__editable_inline {
|
||||||
|
min-height: 250px;
|
||||||
|
direction: rtl;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
.modal-content {
|
.modal-content {
|
||||||
border-radius: 15px;
|
border-radius: 15px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
|||||||
@ -38,7 +38,13 @@
|
|||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<!-- Bootstrap Bundle -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
|
||||||
|
<!-- CKEditor -->
|
||||||
|
<script src="https://cdn.ckeditor.com/ckeditor5/40.0.0/classic/ckeditor.js"></script>
|
||||||
|
<!-- SweetAlert2 -->
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
<!-- Main App JS -->
|
||||||
<script src="assets/js/main.js?v=<?= time() ?>"></script>
|
<script src="assets/js/main.js?v=<?= time() ?>"></script>
|
||||||
<script>
|
<script>
|
||||||
// Sidebar Toggle for Mobile
|
// Sidebar Toggle for Mobile
|
||||||
|
|||||||
@ -24,6 +24,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
|||||||
$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: 1;
|
$default_status_id = db()->query("SELECT id FROM mailbox_statuses WHERE is_default = 1 LIMIT 1")->fetchColumn() ?: 1;
|
||||||
|
|
||||||
if ($recipient_id && $subject) {
|
if ($recipient_id && $subject) {
|
||||||
|
$should_notify = false;
|
||||||
|
$recipient_email = '';
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
$stmt = db()->prepare("INSERT INTO mailbox (type, ref_no, date_registered, subject, description, status_id, assigned_to, created_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
|
||||||
@ -47,12 +49,20 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify recipient
|
// Get recipient info for notification
|
||||||
$stmt_recp = db()->prepare("SELECT full_name, email FROM users WHERE id = ?");
|
$stmt_recp = db()->prepare("SELECT full_name, email FROM users WHERE id = ?");
|
||||||
$stmt_recp->execute([$recipient_id]);
|
$stmt_recp->execute([$recipient_id]);
|
||||||
$recipient = $stmt_recp->fetch();
|
$recipient = $stmt_recp->fetch();
|
||||||
|
|
||||||
if ($recipient && !empty($recipient['email'])) {
|
if ($recipient && !empty($recipient['email'])) {
|
||||||
|
$should_notify = true;
|
||||||
|
$recipient_email = $recipient['email'];
|
||||||
|
}
|
||||||
|
|
||||||
|
db()->commit();
|
||||||
|
|
||||||
|
// Notify after commit
|
||||||
|
if ($should_notify) {
|
||||||
$email_subject = "رسالة داخلية جديدة من " . $_SESSION['name'];
|
$email_subject = "رسالة داخلية جديدة من " . $_SESSION['name'];
|
||||||
$htmlBody = "
|
$htmlBody = "
|
||||||
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
<div dir='rtl' style='font-family: Arial, sans-serif;'>
|
||||||
@ -65,14 +75,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['
|
|||||||
<p>يمكنك الرد من خلال النظام.</p>
|
<p>يمكنك الرد من خلال النظام.</p>
|
||||||
</div>
|
</div>
|
||||||
";
|
";
|
||||||
MailService::sendMail($recipient['email'], $email_subject, $htmlBody);
|
MailService::sendMail($recipient_email, $email_subject, $htmlBody);
|
||||||
}
|
}
|
||||||
|
|
||||||
db()->commit();
|
|
||||||
$_SESSION['success'] = 'تم إرسال الرسالة بنجاح';
|
$_SESSION['success'] = 'تم إرسال الرسالة بنجاح';
|
||||||
redirect('internal_outbox.php');
|
redirect('internal_outbox.php');
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
db()->rollBack();
|
if (db()->inTransaction()) db()->rollBack();
|
||||||
$error = 'حدث خطأ: ' . $e->getMessage();
|
$error = 'حدث خطأ: ' . $e->getMessage();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -271,7 +280,7 @@ function getStatusBadgeInternal($mail) {
|
|||||||
<div class="col-md-12">
|
<div class="col-md-12">
|
||||||
<label class="form-label fw-bold">إلى <span class="text-danger">*</span></label>
|
<label class="form-label fw-bold">إلى <span class="text-danger">*</span></label>
|
||||||
<select name="recipient_id" class="form-select border-2" required>
|
<select name="recipient_id" class="form-select border-2" required>
|
||||||
<option value="">-- اختر המوظف --</option>
|
<option value="">-- اختر الموظف --</option>
|
||||||
<?php foreach ($users_list as $u): ?>
|
<?php foreach ($users_list as $u): ?>
|
||||||
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name'] . ' (@' . $u['username'] . ')') ?></option>
|
<option value="<?= $u['id'] ?>"><?= htmlspecialchars($u['full_name'] . ' (@' . $u['username'] . ')') ?></option>
|
||||||
<?php endforeach; ?>
|
<?php endforeach; ?>
|
||||||
@ -301,6 +310,7 @@ function getStatusBadgeInternal($mail) {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
let composeEditor;
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
if (typeof ClassicEditor !== 'undefined') {
|
if (typeof ClassicEditor !== 'undefined') {
|
||||||
ClassicEditor
|
ClassicEditor
|
||||||
@ -310,6 +320,7 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
direction: 'rtl'
|
direction: 'rtl'
|
||||||
})
|
})
|
||||||
.then(editor => {
|
.then(editor => {
|
||||||
|
composeEditor = editor;
|
||||||
// Force RTL style on editable area
|
// Force RTL style on editable area
|
||||||
editor.ui.view.editable.element.style.direction = 'rtl';
|
editor.ui.view.editable.element.style.direction = 'rtl';
|
||||||
editor.ui.view.editable.element.style.textAlign = 'right';
|
editor.ui.view.editable.element.style.textAlign = 'right';
|
||||||
@ -319,6 +330,10 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
document.getElementById('composeForm').addEventListener('submit', function() {
|
||||||
|
if (composeEditor) composeEditor.updateSourceElement();
|
||||||
|
});
|
||||||
|
|
||||||
<?php if (isset($_GET['action']) && $_GET['action'] === 'compose'): ?>
|
<?php if (isset($_GET['action']) && $_GET['action'] === 'compose'): ?>
|
||||||
var myModal = new bootstrap.Modal(document.getElementById('composeModal'));
|
var myModal = new bootstrap.Modal(document.getElementById('composeModal'));
|
||||||
myModal.show();
|
myModal.show();
|
||||||
|
|||||||
@ -60,6 +60,10 @@ class MailService
|
|||||||
$mail->SMTPAuth = true;
|
$mail->SMTPAuth = true;
|
||||||
$mail->Username = $cfg['smtp_user'] ?? '';
|
$mail->Username = $cfg['smtp_user'] ?? '';
|
||||||
$mail->Password = $cfg['smtp_pass'] ?? '';
|
$mail->Password = $cfg['smtp_pass'] ?? '';
|
||||||
|
|
||||||
|
// Set timeout to 10 seconds to prevent long hangs
|
||||||
|
$mail->Timeout = 10;
|
||||||
|
$mail->SMTPKeepAlive = false;
|
||||||
|
|
||||||
$fromEmail = $opts['from_email'] ?? ($cfg['from_email'] ?? 'no-reply@localhost');
|
$fromEmail = $opts['from_email'] ?? ($cfg['from_email'] ?? 'no-reply@localhost');
|
||||||
$fromName = $opts['from_name'] ?? ($cfg['from_name'] ?? 'App');
|
$fromName = $opts['from_name'] ?? ($cfg['from_name'] ?? 'App');
|
||||||
@ -184,4 +188,4 @@ class MailService
|
|||||||
|
|
||||||
return self::sendMail($to, $subject, $html, $message, ['reply_to' => $email]);
|
return self::sendMail($to, $subject, $html, $message, ['reply_to' => $email]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
13
outbound.php
13
outbound.php
@ -82,6 +82,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$id = $_POST['id'] ?? 0;
|
$id = $_POST['id'] ?? 0;
|
||||||
|
|
||||||
if ($ref_no && $subject) {
|
if ($ref_no && $subject) {
|
||||||
|
$should_notify = false;
|
||||||
try {
|
try {
|
||||||
db()->beginTransaction();
|
db()->beginTransaction();
|
||||||
if ($action === 'add') {
|
if ($action === 'add') {
|
||||||
@ -90,7 +91,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$mail_id = db()->lastInsertId();
|
$mail_id = db()->lastInsertId();
|
||||||
|
|
||||||
if ($assigned_to) {
|
if ($assigned_to) {
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
$should_notify = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تمت إضافة البريد الصادر بنجاح';
|
$_SESSION['success'] = 'تمت إضافة البريد الصادر بنجاح';
|
||||||
@ -106,7 +107,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
$stmt->execute([$ref_no, $date_registered, $due_date, $sender, $recipient, $subject, $description, $status_id, $assigned_to, $mail_id]);
|
||||||
|
|
||||||
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
if ($assigned_to && $assigned_to != $old_assigned_to) {
|
||||||
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
$should_notify = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
$_SESSION['success'] = 'تم تحديث البيانات بنجاح';
|
$_SESSION['success'] = 'تم تحديث البيانات بنجاح';
|
||||||
@ -130,9 +131,15 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|||||||
}
|
}
|
||||||
|
|
||||||
db()->commit();
|
db()->commit();
|
||||||
|
|
||||||
|
// Notify after commit
|
||||||
|
if ($should_notify) {
|
||||||
|
sendAssignmentNotification($assigned_to, $ref_no, $subject);
|
||||||
|
}
|
||||||
|
|
||||||
redirect('outbound.php');
|
redirect('outbound.php');
|
||||||
} catch (PDOException $e) {
|
} catch (PDOException $e) {
|
||||||
db()->rollBack();
|
if (db()->inTransaction()) db()->rollBack();
|
||||||
if ($e->getCode() == 23000) {
|
if ($e->getCode() == 23000) {
|
||||||
$error = 'رقم القيد مستخدم مسبقاً';
|
$error = 'رقم القيد مستخدم مسبقاً';
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user