diff --git a/CHANGELOG.md b/CHANGELOG.md index 04a0a3ec..75c0a8c4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,19 @@ This file documents all notable changes made to ITFlow. +## [25.03.5] + +### Fixed +- Fixed the user listing issue when copying a trip. +- Corrected the display of recurring invoice amounts on the dashboard. +- Fixed the linking of entities with assets and contacts. +- Resolved the issue with displaying the correct mobile country code in the contact listing. +- Set the default date to `9999-12-31` to ensure future items (like invoices) are displayed by default. +- Fixed the display issue where file folders were not showing properly during document creation. +- Migrated from Dragula to SortableJS for a more modern, mobile-friendly solution. +- Added Handlebars icons for drag-and-drop items. +- Changed behavior to open Contact and Asset Details pages directly instead of using a modal. + ## [25.03.4] ### Fixed diff --git a/README.md b/README.md index 4863620d..d5c52ebe 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,7 @@ If you want to improve ITFlow, feel free to fork the repo and create a pull requ We’re incredibly grateful to the organizations and individuals who support the project - a big thank you to: - CompuMatter - F1 for HELP +- JetBrains (PhpStorm) ## License ITFlow is distributed "as is" under the GPL License, WITHOUT WARRANTY OF ANY KIND. See [`LICENSE`](https://github.com/itflow-org/itflow/blob/master/LICENSE) for details. diff --git a/admin_settings_ticket.php b/admin_settings_ticket.php index 2d6d4efd..f91cd4c4 100644 --- a/admin_settings_ticket.php +++ b/admin_settings_ticket.php @@ -72,6 +72,31 @@ require_once "includes/inc_all_admin.php"; + +
+ +
+
+ +
+ +
+
+
+ +
+ value="1" id="ticketOrderingSwitch"> + +
+
+ value="1" id="ticketMovingColumnsSwitch"> + +
+

diff --git a/admin_ticket_template_details.php b/admin_ticket_template_details.php index 03ad6fa0..b8280aed 100644 --- a/admin_ticket_template_details.php +++ b/admin_ticket_template_details.php @@ -30,156 +30,139 @@ $ticket_template_updated_at = nullable_htmlentities($row['ticket_template_update $sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id ORDER BY task_template_order ASC, task_template_id ASC"); ?> - - + -
-
+
+
-
-
-

-
- -
-

-
-
+
+
+

+
+ +
+

+
-

-
-
-
-
-
- +

+
+
- -
- -
- -
-
-
Tasks
-
-
-
- -
-
-
- -
- -
- -
-
-
-
- - - - - - - - -
- - m - - - - -
- -
-
-
+
+
+
-
- - - + ?> + +
+
+ +
+ +
+ + + + + 1 AND user_archived_at IS NULL ORDER BY user_name ASC" + WHERE user_role_id > 1 AND user_archived_at IS NULL ORDER BY user_name ASC" ); while ($row = mysqli_fetch_array($sql_users)) { $user_id_select = intval($row['user_id']); diff --git a/asset_details.php b/asset_details.php index b7a03b5d..066f1eec 100644 --- a/asset_details.php +++ b/asset_details.php @@ -244,7 +244,7 @@ if (isset($_GET['asset_id'])) { data-ajax-id=""> -

+

asset_photo"> @@ -405,7 +405,7 @@ if (isset($_GET['asset_id'])) {
-

Network Interfaces

+

Interfaces

- +
diff --git a/contacts.php b/contacts.php index c6c657e9..1ef1c912 100644 --- a/contacts.php +++ b/contacts.php @@ -319,7 +319,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()")); } else { $contact_phone_display = ""; } - $contact_mobile_country_code = nullable_htmlentities($row['contact_phone_country_code']); + $contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']); $contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code)); if (empty($contact_mobile)) { $contact_mobile_display = ""; @@ -445,11 +445,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
- +
diff --git a/css/itflow_custom.css b/css/itflow_custom.css index 7bb00c94..8b93a921 100644 --- a/css/itflow_custom.css +++ b/css/itflow_custom.css @@ -20,10 +20,11 @@ } } -.grab-cursor { +.drag-handle { cursor: grab; + touch-action: none; + user-select: none; } - -.grab-cursor:active { +.drag-handle:active { cursor: grabbing; -} +} \ No newline at end of file diff --git a/css/tickets_kanban.css b/css/tickets_kanban.css index a03d6773..140c0f9e 100644 --- a/css/tickets_kanban.css +++ b/css/tickets_kanban.css @@ -1,41 +1,83 @@ +/* General Popover Styling */ .popover { max-width: 600px; } + +/* Kanban Board Container */ #kanban-board { display: flex; - box-sizing: border-box; overflow-x: auto; + box-sizing: border-box; min-width: 400px; height: calc(100vh - 210px); } +/* Kanban Column */ .kanban-column { - flex: 1; /* Allows columns to grow equally */ - margin: 0 10px; /* Space between columns */ + flex: 1; min-width: 300px; max-width: 300px; + margin: 0 10px; background: #f4f4f4; - padding: 10px; border: 1px solid #ccc; + border-radius: 4px; + padding: 10px; min-height: calc(100vh - 230px); max-height: calc(100vh - 230px); box-sizing: border-box; + display: flex; + flex-direction: column; } -.kanban-column div { - max-height: calc(100vh - 280px); /* Set your desired max height */ - overflow-y: auto; /* Adds a scrollbar when content exceeds max height */ +/* Column Inner Scrollable Task Area */ +.kanban-status { + flex: 1; + overflow-y: auto; + min-height: 60px; + position: relative; + padding: 5px; + background-color: #f9f9f9; + border-radius: 4px; } +/* Individual Task Cards */ .task { background: #fff; margin: 5px 0; padding: 10px; border: 1px solid #ddd; - user-select: none; /* Prevent text selection */ + border-radius: 4px; + cursor: grab; + user-select: none; } -.drag-handle-class { - touch-action: none; - float: right; +/* Grabbing Cursor State */ +.task:active { + cursor: grabbing; +} + +/* Drag Handle (shown on mobile or with class targeting) */ +.drag-handle-class { + float: right; + touch-action: none; + cursor: grab; +} + +/* Placeholder shown in empty columns */ +.empty-placeholder { + border: 2px dashed #ccc; + background-color: #fcfcfc; + color: #999; + font-style: italic; + padding: 12px; + margin: 10px 0; + text-align: center; + border-radius: 4px; + pointer-events: none; +} + +/* Sortable drop zone feedback (optional visual cue) */ +.kanban-status.sortable-over { + background-color: #eaf6ff; + transition: background-color 0.2s ease; } diff --git a/dashboard.php b/dashboard.php index f4b968ad..58b854bf 100644 --- a/dashboard.php +++ b/dashboard.php @@ -151,7 +151,7 @@ if ($user_config_dashboard_financial_enable == 1) { $row = mysqli_fetch_array($sql_unbilled_tickets); $unbilled_tickets = intval($row['unbilled_tickets']); } else { - $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(recurring_id) AS recurring_invoices_added FROM recurring WHERE YEAR(recurring_created_at) = $year")); + $row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(recurring_invoice_id) AS recurring_invoices_added FROM recurring_invoices WHERE YEAR(recurring_invoice_created_at) = $year")); $recurring_invoices_added = intval($row['recurring_invoices_added']); } diff --git a/functions.php b/functions.php index e114a877..671acedf 100644 --- a/functions.php +++ b/functions.php @@ -1614,10 +1614,14 @@ function getFieldById($table, $id, $field, $escape_method = 'sql') { } // Recursive function to display folder options - Used in folders files and documents -function display_folder_options($parent_folder_id, $client_id, $indent = 0) { +function display_folder_options($parent_folder_id, $client_id, $folder_location = 0, $indent = 0) { global $mysqli; - $sql_folders = mysqli_query($mysqli, "SELECT * FROM folders WHERE parent_folder = $parent_folder_id AND folder_location = 1 AND folder_client_id = $client_id ORDER BY folder_name ASC"); + $folder_location = intval($folder_location); + // 0 = Document Folders + // 1 = File Folders + + $sql_folders = mysqli_query($mysqli, "SELECT * FROM folders WHERE parent_folder = $parent_folder_id AND folder_location = $folder_location AND folder_client_id = $client_id ORDER BY folder_name ASC"); while ($row = mysqli_fetch_array($sql_folders)) { $folder_id = intval($row['folder_id']); $folder_name = nullable_htmlentities($row['folder_name']); @@ -1627,13 +1631,14 @@ function display_folder_options($parent_folder_id, $client_id, $indent = 0) { // Check if this folder is selected $selected = ''; - if ((isset($_GET['folder_id']) && $_GET['folder_id'] == $folder_id) || (isset($_POST['folder']) && $_POST['folder'] == $folder_id)) { + if ((isset($_GET['folder_id']) && intval($_GET['folder_id']) === $folder_id) || + (isset($_POST['folder']) && intval($_POST['folder']) === $folder_id)) { $selected = 'selected'; } echo ""; // Recursively display subfolders - display_folder_options($folder_id, $client_id, $indent + 1); + display_folder_options($folder_id, $client_id, $folder_location, $indent + 1); } } \ No newline at end of file diff --git a/includes/app_version.php b/includes/app_version.php index f7d4a284..30829180 100644 --- a/includes/app_version.php +++ b/includes/app_version.php @@ -5,4 +5,4 @@ * Update this file each time we merge develop into master. Format is YY.MM (add a .v if there is more than one release a month. */ -DEFINE("APP_VERSION", "25.03.4"); +DEFINE("APP_VERSION", "25.03.5"); diff --git a/includes/filter_header.php b/includes/filter_header.php index 077fa95d..08e0cd39 100644 --- a/includes/filter_header.php +++ b/includes/filter_header.php @@ -100,7 +100,7 @@ if ($_GET['canned_date'] == "custom" && !empty($_GET['dtf'])) { $dtt = date('Y-m-d', strtotime("last day of december last year")); } else { $dtf = "NULL"; - $dtt = date('Y-m-d'); + $dtt = '9999-12-31'; } // Archived diff --git a/index.php b/index.php index ab0d6145..fa9c67b1 100644 --- a/index.php +++ b/index.php @@ -14,7 +14,11 @@ if (file_exists("config.php")) {

Blank Page


- + + -