diff --git a/CHANGELOG.md b/CHANGELOG.md index b2713af5b..5e0fa7a16 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,12 +25,14 @@ From here on the command line is optional. Maintenance > Update hands the work t - Database updates have been removed from the web interface entirely. Cron applies them as part of a queued update, or you run `php scripts/update_cli.php --update_db` yourself. - Running `php scripts/update_cli.php` with no arguments updates the files and then the database in one go, and the file update is forced — any local edits you have made to shipped files are discarded. Use `--update_db` if you only want the database half; it never touches your files. - If you have added your own CSS or JavaScript under `agent/custom/`, expect it to need updating. The interface has moved to a new major version of the framework it is built on and most class names have changed. Details are in Developer Updates below. +- Deleting a payment now requires Full access to both Sales and Financial, up from Modify. Refunding requires the same. Deleting a payment removes money from the books, so it is treated as a delete rather than an edit — agents who could remove payments before may no longer be able to. - The five built-in ticket statuses now have fixed SLA clock behaviour and can no longer be configured. New and Open always run; On Hold, Resolved and Closed always pause the resolution clock. Only custom statuses keep the SLA Clock dropdown, and the built-ins are marked "(fixed)" in the list. - On Hold pauses the resolution clock, not the response clock, and only once the ticket has had its first reply. A ticket parked on hold before anyone replies still breaches its response target — reply first, then hold. - Breaches already recorded against on-hold tickets under the old behaviour are left as they are. Change a ticket's priority or SLA to re-stamp it if you want it recalculated. - Holidays and closure days are new and start empty. Until you add them, SLA clocks keep running through your closures exactly as they did before. - Tickets default to Medium priority when none is given, and ticket replies default to Public. -- Send Email and Mark Sent on invoices and quotes now open modals rather than sending straight away, so any bookmarked direct links to those actions no longer work. +- Closed tickets can no longer be deleted. A closed ticket is treated as a permanent record. +- Send Email on invoices and quotes now opens a contact picker rather than sending straight away. Quick Send, described below, keeps the old one-click behaviour, but any bookmarked direct links to the send action no longer work. ### New Features & Updates @@ -42,49 +44,49 @@ From here on the command line is optional. Maintenance > Update hands the work t - SLA: holidays and closure days. Define the days you are closed and the SLA clock pauses through them, with a one-click importer for US federal holidays. - Networks: a full IP address section under each subnet — address, hostname and description, with search, sort, bulk delete, CSV import and export. Addresses are checked against the subnet they are being added to and duplicates within a subnet are refused, so the same guard applies whether you type one in or import a thousand. Both IPv4 and IPv6, sorted numerically so .9 comes before .10. - Designate one client record as your own organization, under Company Details. Clicking your company name at the top of the side navigation now takes you straight to it. -- Invoices and Quotes: Send Email opens a modal listing the client's contacts with their email addresses, with the usual defaults pre-checked — primary and billing for invoices, primary for quotes. Who it went to is recorded in the document history. Quick Send is still there for a one-click send to the defaults. +- Invoices and Quotes: Quick Send is a one-click send to the default contacts, the way Send Email used to work — primary and billing for invoices, primary for quotes. It sits at the top of the actions menu with a lightning bolt and asks for confirmation, and never opens the picker. +- Invoices and Quotes: Send Email, below it, opens a modal listing every contact on the client with their email addresses and the same defaults pre-checked, for when the invoice needs to go somewhere other than the usual place. Who it went to is recorded in the document history either way. - Invoices and Quotes: Mark Sent asks how it was sent — snail mail, an email client, in person and so on — and records the reason in the history. +- Stripe: refund a card payment from the invoice itself. The refund goes through Stripe, is written to the invoice history, and the payment is removed, replacing the old routine of deleting the payment in ITFlow and refunding it by hand in the Stripe dashboard. +- Stripe: adding or editing the Stripe provider now checks the secret key against Stripe and tells you if it is wrong, instead of the key looking fine until the first client tries to pay. +- Stripe: a client paying from a guest invoice link no longer needs a Stripe customer record to exist first — Pay Now sets one up as part of the payment. - Client account statements. Send one from the invoice list with a date range and an option to leave out paid invoices, view it on the guest invoice page, and download it as a PDF from the client portal. - Files: documents and files are now told apart, with a filter for all documents or just files. Thumbnail view shows every file, previews work for documents, PDFs and text, and your choice of list or thumbnail view survives navigating between folders. - Client Portal: the profile page has been rebuilt — department, location, title and phone with inline editing, PIN changes, recent sign-ins and recent activity, with a separate full activity page. -- Client Portal: empty tables now say what is missing instead of showing a bare header row. +- Client Portal: empty tables now say what is missing instead of showing a bare header row, and the saved payment method wording is clearer about what saving a card actually does. +- Guest: the ticket task approval page has been rebuilt. The request being approved leads the page, the ticket body sits underneath as context, the approve action is a proper button rather than a link in a paragraph, and approving or declining lands on a real confirmation screen. Internal routing jargon that meant nothing to a client has been dropped. +- Guest and client portal pages now have proper footers, and the agent footer stays at the bottom of short pages instead of floating mid-screen. - Phone numbers show their country code, and the country is kept when you edit the number. The international phone input is now used on every phone field. - Maintenance > Update: Queue Update hands the update to cron, which runs it in its own process and updates the files and the database in one pass. Check now looks for new commits without needing shell access, listing the pending commits with their dates and descriptions. - Mail Parser: you are now notified when the parser skips an autogenerated email rather than it disappearing silently. - Demo data. Twenty fictional clients with two years of history — a mix of managed and break-fix, tickets, invoices, expenses, assets and contracts, including FOSS products — loaded from Maintenance > Starter Content and tagged so it can be cleared out again. +- API: reads accept an optional `client_id` filter on top of the key's own client scoping, so a key that can see everything can ask for one client's records. It can only narrow — a key with no access to that client still gets nothing. +- API: new endpoints to close a ticket and to delete a client. Closing resolves the ticket first if it has not been resolved already, so the SLA figures come out right. Thanks to @BoredManCodes for the client delete endpoint. - Client pages load noticeably faster, running roughly a third fewer queries than before, and several pages that were slow on large installs have been sped up. - Lists now say whether nothing matched your filters or there are no records at all, instead of showing an empty table either way. - Assets and Contacts: an "Add primary" link where a client has no primary location or contact set. - The client header at the top of client pages collapses, and stays collapsed as you move between pages. -- Page changes fade in rather than flashing, and the calendar reserves its height so the page no longer jumps as it loads. +- Page changes fade in rather than flashing, the calendar reserves its height so the page no longer jumps as it loads, and table listings line up consistently across the app. ### Security - A restricted agent could open an asset, contact or location belonging to a client they have no access to by entering its id in the address bar. Those pages are now gated on the module permission that owns them and checked against the agent's client access rules, like every other record page. - Client Portal: changing a password or a PIN now requires the current password. Contacts signing in through SSO are exempt — there is no local password to check and the identity provider has already done it. - A user name containing HTML could inject markup into the page through the ticket task approver list. It no longer can. +- Deleting and refunding payments now require Full access to both Sales and Financial, as described under Breaking Changes. ### Bug Fixes - Tickets could not be opened for clients marked as a lead. - Client Portal: raising a ticket sent no new-ticket notification — the notification errored out instead. -- Notification pagination, asset OS autocomplete, the contact authentication toggle, AI ticket summaries and AI document template generation all did nothing when opened from a modal. -- Fixed the readable password generator. -- Date filter: All Time defaulted to 1970 rather than the current month. -- Printing: side navigation and the top bar no longer print, the extra blank page is gone, cards print without their borders and the font is smaller, matching how it printed before. -- Dark mode: fixed the light-mode flash on load, and the calendar, editor, confirmation dialogs, light backgrounds and buttons, and table checkboxes all follow the theme now. -- Copy to clipboard was rendered as a button rather than a link. -- Fixed the active side navigation highlight, and the Networks entry now stays active while viewing a subnet's IP addresses. -- Select boxes no longer flash unstyled while the page loads. +- The readable password generator called a function that no longer existed, so generating one did nothing. - Client pages flashed blank on every load. -- Fixed the mail settings tabs regression. - Invoice emails went to archived contacts, and every copy carried the primary contact's name in the greeting rather than the name of the contact receiving it. -- Client Portal: setting a PIN containing `<` or `>` silently cleared it while reporting that it saved. -- Client Portal: audit entries were logged with an empty name. -- Client Portal: the statement page and its PDF now render in the client's currency, matching the guest view and the emailed statement. +- Guest: the confirmation dialog on ticket task approvals and on quote accept and decline rendered as plain text at the foot of the page instead of as a dialog, because the guest pages never loaded its stylesheet. - Filtering the audit log by date was slow on large installs. -- Quick Send asks for confirmation before sending. -- Fixed a bug sending client account statements. +- API: deleting an asset reported how many interfaces it had removed rather than confirming the asset itself was deleted. +- API: updating a client failed outright if the request did not include the lead field. +- API: a request that authenticated correctly but then failed on the query wrote nothing to the app log, leaving nothing to debug from. ### Developer Updates @@ -93,32 +95,40 @@ Front-end framework migration: - AdminLTE 4 dropped a number of v3 classes ITFlow relies on. `text-bold`, `text-sm`, `btn-default`, `img-circle`, the `.alert .icon` pairing, the sidebar badge positioning, the `small-box` watermark icon and all sixteen theme colours are reproduced in `css/itflow_custom.css` at v3's computed values, driven by a single `--itflow-accent` variable per theme. - Bootstrap 5 split `.bg-*` from `.text-bg-*`, so every `bg-dark` card and modal header needed its text colour restored explicitly. - `input-group-append` and `input-group-prepend` wrappers are deleted rather than renamed, selects moved from `form-control` to `form-select`, `data-toggle="buttons"` groups became `.btn-check`, and `custom-control`, `custom-select` and `custom-file` are gone. -- `css/itflow_custom.css` was previously loaded only by `includes/header.php`. It is now loaded by the client portal, guest, login, setup and MFA enforcement headers as well, which is what fixes theming on those pages. +- `.input-group > .form-control` at specificity (0,2,0) outranks `.form-control-color`'s `width:3rem` at (0,1,0), which collapsed every colour swatch. Fixed with a matching-specificity `.input-group > .form-control-color` rule rather than a `w-auto` override, which only hands the width to the UA default. +- Stylesheets and scripts were repeatedly found loaded by `includes/header.php` only. `css/itflow_custom.css` and `libs/sweetalert2/css/sweetalert2.min.css` are now loaded by the client portal, guest, login, setup and MFA headers as well — the SweetAlert2 gap is why guest dialogs rendered in normal flow, since all of its positioning lives in the stylesheet while `includes/footer.php` was loading the JS fine. jQuery removal: - jQuery, jQuery UI, select2, Inputmask, daterangepicker, Moment, Tempus Dominus, toastr, pdfmake, Dropzone and Popper are all gone. Replacements are Tom Select, Flatpickr, IMask, SweetAlert2 and Bootstrap's own toasts, plus `js/autocomplete.js` for the product and OS autocompletes. - New helpers in `js/app.js`: `itflowPostForm()` reproduces jQuery's bracketed array encoding that `ajax.php` parses, `itflowBindOnce()` replaces the namespaced `.off().on()` pattern, and `initTomSelect` / `refreshTomSelect` / `clearTomSelect` / `setTomSelectValue` wrap Tom Select. - `includes/modal_footer.php` re-executes `js/app.js` on every ajax modal open, so every initialiser needs a re-entry guard or it double-initialises. -- New `itflowReady()` restores jQuery's `.ready()` semantics. Scripts injected into an ajax modal run after `DOMContentLoaded` has already fired, so a bare listener never ran — that is what killed the six modals listed under Bug Fixes. +- New `itflowReady()` restores jQuery's `.ready()` semantics. Scripts injected into an ajax modal run after `DOMContentLoaded` has already fired, so a bare listener never runs — this is what broke notification pagination, asset OS autocomplete, the contact authentication toggle, AI ticket summaries and AI document template generation mid-cycle. - `js/ajax_modal.js` re-injects `