From 6ecc27e7cabbcaa8961ac1ad6170d067478b3a76 Mon Sep 17 00:00:00 2001 From: johnnyq Date: Mon, 9 Nov 2026 01:22:35 -0500 Subject: [PATCH] Version ITFlow's scripts and stylesheets so browsers fetch the new copies after an update instead of needing a cache clear: add staticFileUrl() in functions/app.php, which adds ?v= and the file's modification time to the address, and send every script and stylesheet tag through it, libs included, with page-relative addresses changed to start from the site root; add js/tinymce_defaults.js to set TinyMCE's cache_suffix so the plugins, theme and skins it loads itself are versioned too; load ticket collision detection only when a ticket is shown, so a ticket that isn't found no longer throws a script error; add changelog entries and a CONTRIBUTING rule that new tags must use staticFileUrl() --- CHANGELOG.md | 4 ++ CONTRIBUTING.md | 2 + admin/api_keys.php | 2 +- admin/categories.php | 4 +- admin/custom_links.php | 2 +- admin/document_template.php | 4 +- admin/getting_started.php | 24 ++++----- admin/mail_queue.php | 2 +- admin/managed_instance.php | 2 +- admin/modals/category/category_form.php | 2 +- admin/modals/custom_link/custom_link_form.php | 2 +- .../document_template_form.php | 2 +- .../document_template_use.php | 2 +- admin/modals/role/role_form.php | 2 +- admin/modals/tag/tag_form.php | 2 +- admin/modals/tax/tax_form.php | 2 +- .../ticket_status/ticket_status_form.php | 2 +- admin/post/users.php | 4 +- admin/project_template.php | 2 +- admin/software_template.php | 2 +- admin/starter_content.php | 2 +- admin/tags.php | 2 +- admin/text_messages.php | 2 +- admin/ticket_statuses.php | 2 +- admin/ticket_template.php | 4 +- admin/update.php | 2 +- admin/users.php | 2 +- admin/vendor_template.php | 2 +- agent/asset.php | 2 +- agent/assets.php | 2 +- agent/calendar.php | 12 ++--- agent/certificates.php | 2 +- agent/client_onboarding.php | 26 +++++----- agent/client_overview.php | 2 +- agent/clients.php | 2 +- agent/contacts.php | 2 +- agent/credentials.php | 2 +- agent/dashboard.php | 2 +- agent/document.php | 2 +- agent/domains.php | 2 +- agent/expense_import.php | 2 +- agent/expenses.php | 2 +- agent/files.php | 6 +-- agent/includes/client_side_nav.php | 2 +- agent/includes/inc_canned_response_picker.php | 2 +- agent/income.php | 2 +- agent/income_import.php | 2 +- agent/invoice.php | 6 +-- agent/invoices.php | 2 +- agent/locations.php | 2 +- agent/modals/asset/asset_bulk_add_ticket.php | 2 +- agent/modals/asset/asset_interface_add.php | 2 +- agent/modals/asset/asset_interface_edit.php | 2 +- agent/modals/calendar/calendar_event_add.php | 2 +- agent/modals/calendar/calendar_event_edit.php | 2 +- .../modals/client/client_bulk_add_ticket.php | 2 +- agent/modals/client/client_delete.php | 2 +- agent/modals/client/client_export_data.php | 2 +- .../modals/contract/contract_countersign.php | 2 +- agent/modals/contract/contract_form.php | 2 +- .../document/document_add_from_template.php | 2 +- .../modals/document/document_version_view.php | 2 +- agent/modals/document/document_view.php | 2 +- agent/modals/network/network_add.php | 2 +- agent/modals/network/network_edit.php | 2 +- agent/modals/project/project_add.php | 2 +- agent/modals/project/project_edit.php | 2 +- .../recurring_ticket/recurring_ticket_add.php | 4 +- .../recurring_ticket_edit.php | 2 +- agent/modals/share/share_add.php | 2 +- agent/modals/sms/sms_ticket_open.php | 2 +- agent/modals/ticket/ticket_add.php | 4 +- agent/modals/ticket/ticket_change_client.php | 2 +- agent/modals/ticket/ticket_edit_schedule.php | 2 +- agent/network.php | 2 +- agent/networks.php | 2 +- agent/product.php | 2 +- agent/products.php | 2 +- agent/project.php | 2 +- agent/projects.php | 2 +- agent/quote.php | 6 +-- agent/reconcile.php | 2 +- agent/recurring_invoice.php | 6 +-- agent/recurring_tickets.php | 2 +- agent/reports/asset_lifecycle.php | 2 +- agent/reports/audit_activity.php | 2 +- agent/reports/budget.php | 2 +- agent/reports/canned_responses.php | 2 +- agent/reports/client_profitability.php | 2 +- agent/reports/client_review.php | 2 +- agent/reports/client_ticket_time_detail.php | 2 +- agent/reports/credential_rotation.php | 2 +- agent/reports/document_templates.php | 2 +- agent/reports/documentation_coverage.php | 2 +- agent/reports/expense_by_vendor.php | 2 +- agent/reports/expense_summary.php | 2 +- agent/reports/income_by_client.php | 2 +- agent/reports/income_summary.php | 2 +- agent/reports/index.php | 2 +- agent/reports/inventory.php | 2 +- agent/reports/license_templates.php | 2 +- agent/reports/mileage.php | 2 +- agent/reports/outstanding_balances.php | 2 +- agent/reports/profit_loss.php | 2 +- agent/reports/quote_pipeline.php | 2 +- agent/reports/recurring_by_client.php | 2 +- agent/reports/renewals.php | 2 +- agent/reports/satisfaction.php | 2 +- agent/reports/sla_by_client.php | 2 +- agent/reports/sla_summary.php | 2 +- agent/reports/tax_summary.php | 2 +- agent/reports/ticket_aging.php | 2 +- agent/reports/ticket_by_client.php | 2 +- agent/reports/ticket_summary.php | 2 +- agent/reports/ticket_templates.php | 2 +- agent/reports/tickets_unbilled.php | 2 +- agent/reports/time_by_tech.php | 2 +- agent/reports/vendor_templates.php | 2 +- agent/services.php | 2 +- agent/shares.php | 2 +- agent/software.php | 2 +- agent/ticket.php | 16 +++--- agent/ticket_kanban.php | 6 +-- agent/tickets.php | 2 +- agent/trips.php | 2 +- agent/unbilled_time.php | 4 +- agent/user/mfa_enforcement.php | 12 ++--- agent/user/modals/canned_response_save.php | 2 +- agent/vendors.php | 2 +- client/contract.php | 2 +- client/includes/footer.php | 33 ++++++------ client/includes/header.php | 14 ++--- client/join.php | 8 +-- client/login_reset.php | 8 +-- client/signup.php | 8 +-- functions/app.php | 18 +++++++ functions/demo.php | 4 +- guest/guest_approve_ticket_task.php | 2 +- guest/guest_pay_invoice_stripe.php | 2 +- guest/guest_view_contract.php | 2 +- guest/guest_view_ticket.php | 2 +- guest/includes/guest_header.php | 12 ++--- guest/share.php | 4 +- includes/canned_response_form.php | 2 +- includes/contract_placeholders.php | 2 +- includes/footer.php | 51 ++++++++++--------- includes/header.php | 18 +++---- includes/managed_blocked.php | 6 +-- includes/modal_footer.php | 8 +-- join.php | 8 +-- js/tinymce_defaults.js | 23 +++++++++ login.php | 12 ++--- setup/index.php | 20 ++++---- 153 files changed, 347 insertions(+), 296 deletions(-) create mode 100644 js/tinymce_defaults.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 525c1100e..d5a31fdb5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ Update from Maintenance > Update — Queue Update hands the job to cron, which u - Phone numbers: outside North America, a number shown with its country code kept the 0 - or the 8 in Russia - that is only dialled within the country, as "+49 0172 1234567" for a German mobile, wherever it showed: ITFlow's pages, the client portal (a contact's own profile, and the Contact us details), emails, PDFs and exports. Click-to-call dialled it that way too, and so failed. Numbers are now written the way each country writes them: "+49 172 1234567", and "0172 1234567" without the country code. This covers every country, not only the ones ITFlow had its own rules for. A German landline such as Munich's is split after its area code ("+49 89 1234567"), Italy keeps the 0 its landlines are dialled with from abroad ("+39 06 1234 5678"), and South African numbers read "+27 82 123 4567". A number typed with or without that leading 0, or with its country code at the front, shows and dials the same. North American numbers look as they did. - Lists: on a list with only a row or two, a row's actions menu was cut off at the bottom of the list, hiding its last options - Delete among them. Menus now open over the page, and still turn upward when there's no room below. This covers every list, the board and the client portal. - Client portal: for a client whose name has an apostrophe - O'Brien Dental, say - adding a contact or saying one has left, setting up autopay, and the alert that a card payment went through but couldn't be recorded all ended in an error. The contact was saved but nobody was told, and that payment alert never reached you. They work now. +- Updates: after an update, pages could act up - menus, buttons, editors and forms not working, or pages looking half old and half new - until each person cleared their browser's cache, and sometimes closed the browser and cleared it again. Browsers kept the copies of ITFlow's scripts and stylesheets from before the update and went on using them with the new pages, for days or weeks. Each one is now asked for by an address that changes when the file does, so after an update browsers fetch what changed straight away and keep using what didn't. This starts with this update: nobody needs to clear their cache for it. ### Developer Updates @@ -84,6 +85,9 @@ Update from Maintenance > Update — Queue Update hands the job to cron, which u - `demoModeReset()` (`cron/demo_reset.php`, registered only in demo mode, daily at 02:00, `interval_safe` false, ends the cycle) keeps the companies row, the timezone, `config_cron_last_dispatch_at` and the `cron_jobs` rows (columns db.sql still has), drops every table and loads db.sql, then `seedDefaultData()`, `setupSaveRegion()`, the three demo agents with a new vault key under the demo password, every `starterContentLoad()` pack and `demoDataLoad()` with the vault opened in-process and the session globals set to the demo admin, and a portal user for the first demo client's primary contact; it empties every folder in uploads/ but settings/, keeping their index.php and .htaccess. A reset that stopped part way leaves no settings - `php cron/demo_reset.php` still runs then. The domain and certificate refreshers aren't registered in demo mode. The Mail Queue job cancels queued mail with a reason, and `certificateConnect()` connects only to a public address on port 443, by that address (`demoModePublicAddress()`). - `js/bootstrap_defaults.js`, loaded straight after `bootstrap.bundle.min.js` in `includes/footer.php` and `client/includes/footer.php`, sets `bootstrap.Dropdown.Default.popperConfig` to `{strategy: 'fixed'}`, so dropdown menus are placed against the viewport and a `.table-responsive` wrapper (overflow auto) no longer clips them. Dropdowns in a navbar are unaffected - Bootstrap doesn't use Popper there. - `client/post.php`: `$session_client_name` is the client's name as stored (`client/includes/check_login.php`), so the five `appNotify()` and `logAudit()` calls that put it in their text now pass it through `escapeSql()`. `smsSaveMedia()` pins curl to the address it checked (`CURLOPT_RESOLVE`), so a name that resolves differently the second time can't point the download somewhere private. +- `staticFileUrl($path)` in `functions/app.php` returns `$path?v=` and the file's `filemtime()`, or the path as it is when the file isn't there. Every ` + - + - + + - + + - - - - - - - + + + + + + + + diff --git a/admin/mail_queue.php b/admin/mail_queue.php index cc772fc9d..1992558e1 100644 --- a/admin/mail_queue.php +++ b/admin/mail_queue.php @@ -257,7 +257,7 @@ $filtered_dates = isset($_GET['dtf']) && $_GET['dtf'] !== '' && $_GET['dtf'] !== - + - + - + diff --git a/admin/modals/custom_link/custom_link_form.php b/admin/modals/custom_link/custom_link_form.php index cc183b09f..180915404 100644 --- a/admin/modals/custom_link/custom_link_form.php +++ b/admin/modals/custom_link/custom_link_form.php @@ -100,4 +100,4 @@ $l_description = (string) ($l['custom_link_description'] ?? ''); - + diff --git a/admin/modals/document_template/document_template_form.php b/admin/modals/document_template/document_template_form.php index 9bb46a391..14357a736 100644 --- a/admin/modals/document_template/document_template_form.php +++ b/admin/modals/document_template/document_template_form.php @@ -66,7 +66,7 @@ $ai_model = aiReady('Documentation') ? getAiModel('Documentation') : null;
Any other word in square brackets - [Firewall Model] - is asked for when a document is made, and set up on the template's page. Pasted images are kept with the template and copied into each document made from it.
- + + >An admin role opens every part of ITFlow, so there are no levels to set. Its levels are kept, for if it stops being one. - + diff --git a/admin/modals/tag/tag_form.php b/admin/modals/tag/tag_form.php index fc2578e6a..4f8bdee33 100644 --- a/admin/modals/tag/tag_form.php +++ b/admin/modals/tag/tag_form.php @@ -103,4 +103,4 @@ if (!in_array($t_icon, $t_icons, true)) { - + diff --git a/admin/modals/tax/tax_form.php b/admin/modals/tax/tax_form.php index 5154d8d43..e225b3ea6 100644 --- a/admin/modals/tax/tax_form.php +++ b/admin/modals/tax/tax_form.php @@ -106,4 +106,4 @@ $tax_part_row = function ($key, array $part = []) { - + diff --git a/admin/modals/ticket_status/ticket_status_form.php b/admin/modals/ticket_status/ticket_status_form.php index a29b2d5fe..895e17d6f 100644 --- a/admin/modals/ticket_status/ticket_status_form.php +++ b/admin/modals/ticket_status/ticket_status_form.php @@ -109,4 +109,4 @@ $s_reply = $s ? (intval($s['ticket_status_client_reply'] ?? 1) === 0 ? 0 : 1) : - + diff --git a/admin/post/users.php b/admin/post/users.php index 0675033c5..91a8a6568 100644 --- a/admin/post/users.php +++ b/admin/post/users.php @@ -585,8 +585,8 @@ if (isset($_POST['ir_reset_user_password'])) { Incident response - new agent passwords - - + +
diff --git a/admin/project_template.php b/admin/project_template.php index 25623fddf..d2c571163 100644 --- a/admin/project_template.php +++ b/admin/project_template.php @@ -166,7 +166,7 @@ $archived = !empty($template['project_template_archived_at']);
- + + - + diff --git a/admin/tags.php b/admin/tags.php index cb916b052..85221b2ad 100644 --- a/admin/tags.php +++ b/admin/tags.php @@ -271,7 +271,7 @@ $csrf = $_SESSION['csrf_token']; - + - + - + - + + + - + - + - + - + $source) { - - - - - - + + + + + + diff --git a/agent/certificates.php b/agent/certificates.php index c3354d112..bb6859e8f 100644 --- a/agent/certificates.php +++ b/agent/certificates.php @@ -474,6 +474,6 @@ $export_extra = [ - + - - - - - + + + + + @@ -196,14 +196,14 @@ define('FROM_CLIENT_ONBOARDING', true); - - - - - - - - + + + + + + + + diff --git a/agent/client_overview.php b/agent/client_overview.php index ddf6d02af..6af138702 100644 --- a/agent/client_overview.php +++ b/agent/client_overview.php @@ -702,4 +702,4 @@ $money_format = function ($amount) use ($currency_format, $client_currency_code, - + diff --git a/agent/clients.php b/agent/clients.php index ab48c7aff..bb9128d76 100644 --- a/agent/clients.php +++ b/agent/clients.php @@ -804,7 +804,7 @@ $total_leads = intval($row['leads']); - + - + - + - + diff --git a/agent/document.php b/agent/document.php index a80346496..120be1e0d 100644 --- a/agent/document.php +++ b/agent/document.php @@ -293,7 +293,7 @@ $page_title = $row['document_name']; - + - + 'Statement', 'columns' => 'Columns', 'review' => 'Review'] - + - + window.itflowFilesPreview = ; - - - + + + - +