mirror of
https://github.com/itflow-org/itflow
synced 2026-08-15 20:15:12 +00:00
Fix Card Margin bottoms client header and ticket cards on the right
This commit is contained in:
@@ -59,6 +59,83 @@ if (isset($_POST['client_set_notes'])) {
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Inline notes for sales documents.
|
||||
*
|
||||
* These replace the invoice/quote/recurring-invoice note modals, which posted
|
||||
* to post.php and reloaded the page. Same permission, client-access and audit
|
||||
* behaviour as those handlers had - only the delivery changed.
|
||||
*/
|
||||
|
||||
if (isset($_POST['invoice_set_notes'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$invoice_id = intval($_POST['invoice_id']);
|
||||
$note = escapeSql($_POST['note']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT invoice_client_id, invoice_number, invoice_prefix FROM invoices WHERE invoice_id = $invoice_id");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$invoice_prefix = escapeSql($row['invoice_prefix']);
|
||||
$invoice_number = intval($row['invoice_number']);
|
||||
$client_id = intval($row['invoice_client_id']);
|
||||
|
||||
enforceClientAccess();
|
||||
|
||||
mysqli_query($mysqli, "UPDATE invoices SET invoice_note = '$note' WHERE invoice_id = $invoice_id");
|
||||
|
||||
logAudit("Invoice", "Edit", "$session_name edited notes on invoice $invoice_prefix$invoice_number", $client_id, $invoice_id);
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['quote_set_notes'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$quote_id = intval($_POST['quote_id']);
|
||||
$note = escapeSql($_POST['note']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT quote_client_id, quote_number, quote_prefix FROM quotes WHERE quote_id = $quote_id");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$quote_prefix = escapeSql($row['quote_prefix']);
|
||||
$quote_number = intval($row['quote_number']);
|
||||
$client_id = intval($row['quote_client_id']);
|
||||
|
||||
enforceClientAccess();
|
||||
|
||||
mysqli_query($mysqli, "UPDATE quotes SET quote_note = '$note' WHERE quote_id = $quote_id");
|
||||
|
||||
logAudit("Quote", "Edit", "$session_name edited notes on quote $quote_prefix$quote_number", $client_id, $quote_id);
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['recurring_invoice_set_notes'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
$note = escapeSql($_POST['note']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT recurring_invoice_prefix, recurring_invoice_number, recurring_invoice_client_id FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$recurring_invoice_prefix = escapeSql($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
$client_id = intval($row['recurring_invoice_client_id']);
|
||||
|
||||
enforceClientAccess();
|
||||
|
||||
mysqli_query($mysqli, "UPDATE recurring_invoices SET recurring_invoice_note = '$note' WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
|
||||
logAudit("Recurring Invoice", "Edit", "$session_name edited notes on recurring invoice $recurring_invoice_prefix$recurring_invoice_number", $client_id, $recurring_invoice_id);
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['contact_set_notes'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php $show_add_credit = 0; // Remove once credits is added hides the button ?>
|
||||
|
||||
<div class="card d-print-none">
|
||||
<div class="card mb-3 d-print-none">
|
||||
<div class="card-header pb-1 pt-2 px-3">
|
||||
<div class="card-title">
|
||||
<a href="#" data-bs-toggle="collapse" data-bs-target="#clientHeader"><h4 class="text-dark" data-bs-toggle="tooltip" data-bs-placement="right" title="Client ID: <?= $client_id ?>"><strong><?= $client_name ?></strong> <?php if ($client_archived_at) { echo "(archived)"; } ?></h4></a>
|
||||
|
||||
@@ -508,14 +508,22 @@ if (isset($_GET['invoice_id'])) {
|
||||
<div class="card">
|
||||
<div class="card-header text-bold">
|
||||
Notes:
|
||||
<div class="card-tools d-print-none">
|
||||
<a href="#" class="btn btn-light btn-tool" data-bs-toggle="modal" data-bs-target="#invoiceNoteModal">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
</div>
|
||||
<span class="d-print-none" data-note-status-for="invoiceNotes"></span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= nl2br($invoice_note) ?>
|
||||
<div class="card-body p-2">
|
||||
<?php if (lookupUserPermission("module_sales") >= 2) { ?>
|
||||
<textarea class="form-control itflow-inline-note d-print-none" rows="6"
|
||||
id="invoiceNotes"
|
||||
placeholder="Enter some notes"
|
||||
data-endpoint="invoice_set_notes"
|
||||
data-id-field="invoice_id"
|
||||
data-id="<?= $invoice_id ?>"
|
||||
data-csrf="<?= $_SESSION['csrf_token'] ?>"><?= $invoice_note ?></textarea>
|
||||
<?php } else { ?>
|
||||
<div class="d-print-none"><?= nl2br($invoice_note) ?></div>
|
||||
<?php } ?>
|
||||
<!-- Printed output must be plain text, not a form control -->
|
||||
<div class="d-none d-print-block"><?= nl2br($invoice_note) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -738,10 +746,14 @@ if (isset($_GET['invoice_id'])) {
|
||||
</div>
|
||||
<?php
|
||||
include_once "modals/invoice/invoice_add_ticket.php";
|
||||
include_once "modals/invoice/invoice_note.php";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<script src="/js/inline_notes.js"></script>
|
||||
|
||||
<?php
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
?>
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
<div class="modal" id="invoiceNoteModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title text-white"><i class="fas fa-fw fa-edit me-2"></i>Invoice Notes</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="invoice_id" value="<?= $invoice_id ?>">
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<textarea class="form-control" rows="8" name="note" placeholder="Enter some notes"><?= $invoice_note ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="invoice_note" class="btn btn-primary text-bold"><i class="fas fa-check me-2"></i>Save</button>
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><i class="fas fa-times me-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,29 +0,0 @@
|
||||
<div class="modal" id="quoteNoteModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title text-white">
|
||||
<i class="fas fa-fw fa-edit me-2"></i>Quote Notes
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="quote_id" value="<?= $quote_id ?>">
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<textarea class="form-control" rows="8" name="note" placeholder="Enter some notes"><?= $quote_note ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="quote_note" class="btn btn-primary text-bold">
|
||||
<i class="fas fa-check me-2"></i>Save
|
||||
</button>
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal">
|
||||
<i class="fas fa-times me-2"></i>Cancel
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,23 +0,0 @@
|
||||
<div class="modal" id="recurringInvoiceNoteModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title text-white"><i class="fa fa-fw fa-edit me-2"></i>Editing: <strong>Recurring Invoice</strong> Notes</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?= $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="recurring_invoice_id" value="<?= $recurring_invoice_id ?>">
|
||||
<div class="modal-body">
|
||||
<div class="mb-3">
|
||||
<textarea class="form-control" rows="8" name="note" placeholder="Enter some notes"><?= $recurring_invoice_note ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="recurring_invoice_note" class="btn btn-primary text-bold"><i class="fas fa-check me-2"></i>Save</button>
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal"><i class="fas fa-times me-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -393,34 +393,6 @@ if (isset($_POST['add_invoice_item'])) {
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['invoice_note'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$invoice_id = intval($_POST['invoice_id']);
|
||||
$note = escapeSql($_POST['note']);
|
||||
|
||||
// Get Invoice Details for logging
|
||||
$sql = mysqli_query($mysqli,"SELECT invoice_client_id, invoice_number, invoice_prefix FROM invoices WHERE invoice_id = $invoice_id");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$invoice_prefix = escapeSql($row['invoice_prefix']);
|
||||
$invoice_number = intval($row['invoice_number']);
|
||||
$client_id = intval($row['invoice_client_id']);
|
||||
|
||||
enforceClientAccess();
|
||||
|
||||
mysqli_query($mysqli,"UPDATE invoices SET invoice_note = '$note' WHERE invoice_id = $invoice_id");
|
||||
|
||||
logAudit("Invoice", "Edit", "$session_name added note to invoice $invoice_prefix$invoice_number", $client_id, $invoice_id);
|
||||
|
||||
flashAlert("Notes added");
|
||||
|
||||
redirect();
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['edit_invoice_item'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
@@ -341,34 +341,6 @@ if (isset($_POST['edit_quote_item'])) {
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['quote_note'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$quote_id = intval($_POST['quote_id']);
|
||||
$note = escapeSql($_POST['note']);
|
||||
|
||||
// Get Quote Details
|
||||
$sql = mysqli_query($mysqli,"SELECT quote_client_id, quote_number, quote_prefix FROM quotes WHERE quote_id = $quote_id");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$quote_prefix = escapeSql($row['quote_prefix']);
|
||||
$quote_number = escapeSql($row['quote_number']);
|
||||
$client_id = intval($row['quote_client_id']);
|
||||
|
||||
enforceClientAccess();
|
||||
|
||||
mysqli_query($mysqli,"UPDATE quotes SET quote_note = '$note' WHERE quote_id = $quote_id");
|
||||
|
||||
logAudit("Quote", "Edit", "$session_name added notes to quote $quote_prefix$quote_number", $client_id, $quote_id);
|
||||
|
||||
flashAlert("Notes added");
|
||||
|
||||
redirect();
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['edit_quote'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
@@ -319,34 +319,6 @@ if (isset($_POST['edit_recurring_invoice_item'])) {
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['recurring_invoice_note'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
enforceUserPermission('module_sales', 2);
|
||||
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
$note = escapeSql($_POST['note']);
|
||||
|
||||
// Get Recurring details for logging
|
||||
$sql = mysqli_query($mysqli,"SELECT recurring_invoice_prefix, recurring_invoice_number, recurring_invoice_client_id FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$recurring_invoice_prefix = escapeSql($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
$client_id = intval($row['recurring_invoice_client_id']);
|
||||
|
||||
enforceClientAccess();
|
||||
|
||||
mysqli_query($mysqli,"UPDATE recurring_invoices SET recurring_invoice_note = '$note' WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
|
||||
logAudit("Recurring Invoice", "Edit", "$session_name added note to recurring invoice $recurring_invoice_prefix$recurring_invoice_number", $client_id, $recurring_invoice_id);
|
||||
|
||||
flashAlert("Notes added");
|
||||
|
||||
redirect();
|
||||
|
||||
}
|
||||
|
||||
if (isset($_GET['delete_recurring_invoice_item'])) {
|
||||
|
||||
validateCSRFToken();
|
||||
|
||||
@@ -432,16 +432,22 @@ if (isset($_GET['quote_id'])) {
|
||||
<div class="card">
|
||||
<div class="card-header text-bold">
|
||||
Notes:
|
||||
<div class="card-tools d-print-none">
|
||||
<?php if (lookupUserPermission("module_sales") >= 2) { ?>
|
||||
<a href="#" class="btn btn-light btn-tool" data-bs-toggle="modal" data-bs-target="#quoteNoteModal">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<span class="d-print-none" data-note-status-for="quoteNotes"></span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= nl2br($quote_note) ?>
|
||||
<div class="card-body p-2">
|
||||
<?php if (lookupUserPermission("module_sales") >= 2) { ?>
|
||||
<textarea class="form-control itflow-inline-note d-print-none" rows="6"
|
||||
id="quoteNotes"
|
||||
placeholder="Enter some notes"
|
||||
data-endpoint="quote_set_notes"
|
||||
data-id-field="quote_id"
|
||||
data-id="<?= $quote_id ?>"
|
||||
data-csrf="<?= $_SESSION['csrf_token'] ?>"><?= $quote_note ?></textarea>
|
||||
<?php } else { ?>
|
||||
<div class="d-print-none"><?= nl2br($quote_note) ?></div>
|
||||
<?php } ?>
|
||||
<!-- Printed output must be plain text, not a form control -->
|
||||
<div class="d-none d-print-block"><?= nl2br($quote_note) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -579,9 +585,13 @@ if (isset($_GET['quote_id'])) {
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/quote/quote_note.php";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<script src="/js/inline_notes.js"></script>
|
||||
|
||||
<?php
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
?>
|
||||
|
||||
@@ -396,15 +396,23 @@ if (isset($_GET['recurring_invoice_id'])) {
|
||||
<div class="col-sm-7">
|
||||
<div class="card">
|
||||
<div class="card-header text-bold">
|
||||
Notes
|
||||
<div class="card-tools d-print-none">
|
||||
<a href="#" class="btn btn-light btn-tool" data-bs-toggle="modal" data-bs-target="#recurringInvoiceNoteModal">
|
||||
<i class="fas fa-edit"></i>
|
||||
</a>
|
||||
</div>
|
||||
Notes:
|
||||
<span class="d-print-none" data-note-status-for="recurringInvoiceNotes"></span>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<?= nl2br($recurring_invoice_note) ?>
|
||||
<div class="card-body p-2">
|
||||
<?php if (lookupUserPermission("module_sales") >= 2) { ?>
|
||||
<textarea class="form-control itflow-inline-note d-print-none" rows="6"
|
||||
id="recurringInvoiceNotes"
|
||||
placeholder="Enter some notes"
|
||||
data-endpoint="recurring_invoice_set_notes"
|
||||
data-id-field="recurring_invoice_id"
|
||||
data-id="<?= $recurring_invoice_id ?>"
|
||||
data-csrf="<?= $_SESSION['csrf_token'] ?>"><?= $recurring_invoice_note ?></textarea>
|
||||
<?php } else { ?>
|
||||
<div class="d-print-none"><?= nl2br($recurring_invoice_note) ?></div>
|
||||
<?php } ?>
|
||||
<!-- Printed output must be plain text, not a form control -->
|
||||
<div class="d-none d-print-block"><?= nl2br($recurring_invoice_note) ?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -486,10 +494,14 @@ if (isset($_GET['recurring_invoice_id'])) {
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/recurring_invoice/recurring_invoice_note.php";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<script src="/js/inline_notes.js"></script>
|
||||
|
||||
<?php
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
?>
|
||||
|
||||
@@ -416,7 +416,7 @@ if (isset($_GET['ticket_id'])) {
|
||||
Ticket header - everything you need to identify the ticket and know
|
||||
what state it is in, without scrolling or hunting across cards.
|
||||
-->
|
||||
<div class="card">
|
||||
<div class="card mb-3">
|
||||
<div class="card-body pb-2">
|
||||
|
||||
<div class="d-flex flex-wrap justify-content-between">
|
||||
@@ -932,7 +932,7 @@ if (isset($_GET['ticket_id'])) {
|
||||
|
||||
<!-- Tasks -->
|
||||
<?php if (!$ticket_is_resolved || $task_count) { ?>
|
||||
<div class="card">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header px-3 py-2">
|
||||
<h5 class="card-title mt-1">
|
||||
<i class="fas fa-fw fa-tasks me-2"></i>Tasks
|
||||
@@ -1092,7 +1092,7 @@ if (isset($_GET['ticket_id'])) {
|
||||
// is for links - setting the ticket's contact belongs here
|
||||
$can_set_contact = $can_edit_ticket && !$ticket_is_resolved && $client_id;
|
||||
if ($contact_id || $can_set_contact) { ?>
|
||||
<div class="card">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header px-3 py-2">
|
||||
<h5 class="card-title mt-1"><i class="fas fa-fw fa-user-check me-2"></i>Contact</h5>
|
||||
<?php if ($can_set_contact) { ?>
|
||||
@@ -1163,7 +1163,7 @@ if (isset($_GET['ticket_id'])) {
|
||||
$can_link = $can_edit_ticket && !$ticket_is_closed;
|
||||
$has_links = $asset_id || $vendor_id || $project_id || $watcher_count;
|
||||
if ($has_links || $can_link) { ?>
|
||||
<div class="card">
|
||||
<div class="card mb-3">
|
||||
<div class="card-header px-3 py-2">
|
||||
<h5 class="card-title mt-1"><i class="fas fa-fw fa-link me-2"></i>Linked</h5>
|
||||
<div class="card-tools">
|
||||
|
||||
85
js/inline_notes.js
Normal file
85
js/inline_notes.js
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
* Inline notes.
|
||||
*
|
||||
* Replaces the invoice / quote / recurring-invoice note modals with a textarea
|
||||
* that saves on blur, the same way the client overview Quick Notes field works.
|
||||
*
|
||||
* Markup contract:
|
||||
* <textarea class="itflow-inline-note"
|
||||
* data-endpoint="invoice_set_notes"
|
||||
* data-id-field="invoice_id"
|
||||
* data-id="42"
|
||||
* data-csrf="...">notes</textarea>
|
||||
*
|
||||
* Losing an explicit Save button means the user needs telling that the save
|
||||
* happened, so each field reports its own state next to the label rather than
|
||||
* saving silently.
|
||||
*/
|
||||
function itflowInlineNotes(textarea) {
|
||||
if (!textarea || textarea.dataset.inlineNoteReady) {
|
||||
return;
|
||||
}
|
||||
textarea.dataset.inlineNoteReady = '1';
|
||||
|
||||
// Saving only when the text actually changed avoids a write on every
|
||||
// click-through, which would otherwise spam the audit log.
|
||||
let lastSaved = textarea.value;
|
||||
|
||||
const status = document.createElement('span');
|
||||
status.className = 'itflow-note-status small ms-2 d-print-none';
|
||||
const label = document.querySelector('[data-note-status-for="' + textarea.id + '"]');
|
||||
(label || textarea.parentNode).appendChild(status);
|
||||
|
||||
function setStatus(text, cls) {
|
||||
status.textContent = text;
|
||||
status.className = 'itflow-note-status small ms-2 d-print-none ' + cls;
|
||||
}
|
||||
|
||||
function save() {
|
||||
if (textarea.value === lastSaved) {
|
||||
return;
|
||||
}
|
||||
const payload = {
|
||||
csrf_token: textarea.dataset.csrf,
|
||||
note: textarea.value
|
||||
};
|
||||
payload[textarea.dataset.endpoint] = 'TRUE';
|
||||
payload[textarea.dataset.idField] = textarea.dataset.id;
|
||||
|
||||
setStatus('Saving...', 'text-muted');
|
||||
|
||||
itflowPost('ajax.php', payload, function () {
|
||||
lastSaved = textarea.value;
|
||||
setStatus('Saved', 'text-success');
|
||||
setTimeout(function () {
|
||||
if (status.textContent === 'Saved') {
|
||||
setStatus('', '');
|
||||
}
|
||||
}, 2000);
|
||||
}, function () {
|
||||
setStatus('Not saved - check your connection', 'text-danger');
|
||||
});
|
||||
}
|
||||
|
||||
textarea.addEventListener('blur', save);
|
||||
|
||||
// Ctrl/Cmd+Enter saves without leaving the field
|
||||
textarea.addEventListener('keydown', function (e) {
|
||||
if ((e.ctrlKey || e.metaKey) && e.key === 'Enter') {
|
||||
e.preventDefault();
|
||||
save();
|
||||
}
|
||||
});
|
||||
|
||||
// Warn rather than lose the text if the page is closed mid-edit
|
||||
window.addEventListener('beforeunload', function (e) {
|
||||
if (textarea.value !== lastSaved) {
|
||||
e.preventDefault();
|
||||
e.returnValue = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function () {
|
||||
document.querySelectorAll('.itflow-inline-note').forEach(itflowInlineNotes);
|
||||
});
|
||||
Reference in New Issue
Block a user