Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
25 changes: 25 additions & 0 deletions admin_settings_ticket.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,31 @@
<input type="email" class="form-control" name="config_ticket_new_ticket_notification_email" placeholder="Address to notify for new tickets, leave blank for none" value="<?php echo nullable_htmlentities($config_ticket_new_ticket_notification_email); ?>">
</div>
</div>

<div class="form-group">
<label>Tickets Default View</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
<select class="form-control" name="config_ticket_default_view">
<option value=0 <?php if ($config_ticket_default_view == 0) { echo "selected"; } ?>>List</option>
<option value=1 <?php if ($config_ticket_default_view == 1) { echo "selected"; } ?>>Compact</option>
<option value=2 <?php if ($config_ticket_default_view == 2) { echo "selected"; } ?>>Kanban</option>
</select>
</div>
</div>
<div class="form-group">
<label>Kanban Settings</label>
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_ordering" <?php if ($config_ticket_ordering == 1) { echo "checked"; } ?> value="1" id="ticketOrderingSwitch">
<label class="custom-control-label" for="ticketOrderingSwitch">Allow ticket ordering within its column<small class="text-secondary">(uncheked will result in ordering it by priority and id)</small></label>
</div>
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_moving_columns" <?php if ($config_ticket_moving_columns == 1) { echo "checked"; } ?> value="1" id="ticketMovingColumnsSwitch">
<label class="custom-control-label" for="ticketMovingColumnsSwitch">Allow moving columns</label>
</div>
</div>

<hr>

Expand Down
251 changes: 117 additions & 134 deletions admin_ticket_template_details.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,156 +30,139 @@
$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");

?>
<link rel="stylesheet" href="plugins/dragula/dragula.min.css">

<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="clients.php">Home</a>
</li>
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_ticket_template.php">Ticket Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
</ol>

<div class="row">
<div class="col-8">

<div class="card card-dark">
<div class="card-header">
<h3 class="card-title mt-2">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body">
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
</div>

<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="clients.php">Home</a>
</li>
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_ticket_template.php">Ticket Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
</ol>

<div class="row">
<div class="col-8">

<div class="card card-dark">
<div class="card-header">
<h3 class="card-title mt-2">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body">
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
</div>
</h3>
<div class="card-tools">
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#editTicketTemplateModal">
<i class="fas fa-edit"></i>
</button>
</div>
</div>
<h5><?php echo $ticket_template_subject; ?></h5>
<div class="card-body prettyContent">
<?php echo $ticket_template_details; ?>
</h3>
<div class="card-tools">
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#editTicketTemplateModal">
<i class="fas fa-edit"></i>
</button>
</div>
</div>

<h5><?php echo $ticket_template_subject; ?></h5>
<div class="card-body prettyContent">
<?php echo $ticket_template_details; ?>
</div>
</div>

<div class="col-4">
</div>

<div class="card card-dark">
<div class="card-header">
<h5 class="card-title"><i class="fa fa-fw fa-tasks mr-2"></i>Tasks</h5>
</div>
<div class="card-body">
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tasks"></i></span>
</div>
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required>
<div class="input-group-append">
<button type="submit" name="add_ticket_template_task" class="btn btn-primary"><i class="fas fa-fw fa-check"></i></button>
</div>
<div class="col-4">

<div class="card card-dark">
<div class="card-header">
<h5 class="card-title"><i class="fa fa-fw fa-tasks mr-2"></i>Tasks</h5>
</div>
<div class="card-body">
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tasks"></i></span>
</div>
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required>
<div class="input-group-append">
<button type="submit" name="add_ticket_template_task" class="btn btn-primary"><i class="fas fa-fw fa-check"></i></button>
</div>
</div>
</form>
<table class="table table-striped table-sm">
<?php
while($row = mysqli_fetch_array($sql_task_templates)){
$task_id = intval($row['task_template_id']);
$task_name = nullable_htmlentities($row['task_template_name']);
$task_completion_estimate = intval($row['task_template_completion_estimate']);
$task_description = nullable_htmlentities($row['task_template_description']);
?>
<tr data-task-id="<?php echo $task_id; ?>">
<td><i class="far fa-fw fa-square text-secondary"></i></td>
<td>
<a href="#" class="grab-cursor">
<span class="text-secondary"><?php echo $task_completion_estimate; ?>m</span>
<span class="text-dark"> - <?php echo $task_name; ?></span>
</a>
</td>
<td class="text-right">
<div class="float-right">
<div class="dropdown dropleft text-center">
<button class="btn btn-link text-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle = "ajax-modal"
data-ajax-url = "ajax/ajax_ticket_template_task_edit.php"
data-ajax-id = "<?php echo $task_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_task_template=<?php echo $task_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash-alt mr-2"></i>Delete
</a>
</div>
</div>
</form>
<table class="table table-sm" id="tasks">
<?php
while($row = mysqli_fetch_array($sql_task_templates)){
$task_id = intval($row['task_template_id']);
$task_name = nullable_htmlentities($row['task_template_name']);
$task_completion_estimate = intval($row['task_template_completion_estimate']);
$task_description = nullable_htmlentities($row['task_template_description']);
?>
<tr data-task-id="<?php echo $task_id; ?>">
<td>
<a href="#" class="drag-handle"><i class="fas fa-bars text-muted mr-1"></i></a>
<span class="text-secondary"><?php echo $task_completion_estimate; ?>m</span>
<span class="text-dark"> - <?php echo $task_name; ?></span>
</td>
<td class="text-right">
<div class="float-right">
<div class="dropdown dropleft text-center">
<button class="btn btn-link text-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle = "ajax-modal"
data-ajax-url = "ajax/ajax_ticket_template_task_edit.php"
data-ajax-id = "<?php echo $task_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_task_template=<?php echo $task_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash-alt mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
}
?>
</table>
</div>
</div>
</td>
</tr>
<?php
}
?>
</table>
</div>

</div>

</div>

<script src="js/pretty_content.js"></script>
<script src="plugins/dragula/dragula.min.js"></script>
<script>
$(document).ready(function() {
var container = $('.table tbody')[0];

dragula([container])
.on('drop', function (el, target, source, sibling) {
// Handle the drop event to update the order in the database
var rows = $(container).children();
var positions = rows.map(function(index, row) {
return {
id: $(row).data('taskId'),
order: index
};
}).get();

// Send the new order to the server
$.ajax({
url: 'ajax.php',
method: 'POST',
data: {
update_task_templates_order: true, // Adjust the parameter name if needed
ticket_template_id: <?php echo $ticket_template_id; ?>,
positions: positions
},
success: function(data) {
// Handle success
},
error: function(error) {
console.error('Error updating order:', error);
}
});
});
});
</script>
</div>

<script src="js/pretty_content.js"></script>

<script src="plugins/SortableJS/Sortable.min.js"></script>
<script>
new Sortable(document.querySelector('table#tasks tbody'), {
handle: '.drag-handle',
animation: 150,
onEnd: function (evt) {
const rows = document.querySelectorAll('table#tasks tbody tr');
const positions = Array.from(rows).map((row, index) => ({
id: row.dataset.taskId,
order: index
}));

$.post('ajax.php', {
update_task_templates_order: true,
ticket_template_id: <?php echo $ticket_template_id; ?>,
positions: positions
});
}
});
</script>

<?php

Expand Down
4 changes: 2 additions & 2 deletions ajax.php
Original file line number Diff line number Diff line change
Expand Up @@ -586,13 +586,13 @@
enforceUserPermission('module_sales', 2);

$positions = $_POST['positions'];
$recurring_id = intval($_POST['recurring_id']);
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);

foreach ($positions as $position) {
$id = intval($position['id']);
$order = intval($position['order']);

mysqli_query($mysqli, "UPDATE invoice_items SET item_order = $order WHERE item_recurring_id = $recurring_id AND item_id = $id");
mysqli_query($mysqli, "UPDATE invoice_items SET item_order = $order WHERE item_recurring_invoice_id = $recurring_invoice_id AND item_id = $id");
}

// return a response
Expand Down
2 changes: 1 addition & 1 deletion ajax/ajax_trip_copy.php
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@

$sql_users = mysqli_query($mysqli, "SELECT users.user_id, user_name FROM users
LEFT JOIN user_settings on users.user_id = user_settings.user_id
WHERE user_role > 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']);
Expand Down
4 changes: 2 additions & 2 deletions asset_details.php
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fas fa-fw fa-edit"></i>
</button>
<h3 class="text-bold"><i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-3"></i><?php echo $asset_name; ?></h3>
<h4 class="text-bold"><i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-3"></i><?php echo $asset_name; ?></h4>
<?php if ($asset_photo) { ?>
<img class="img-fluid img-circle p-3" alt="asset_photo" src="<?php echo "uploads/clients/$client_id/$asset_photo"; ?>">
<?php } ?>
Expand Down Expand Up @@ -405,7 +405,7 @@

<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-ethernet mr-2"></i><?php echo $asset_name; ?> Network Interfaces</h3>
<h3 class="card-title mt-2"><i class="fa fa-fw fa-ethernet mr-2"></i>Interfaces</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAssetInterfaceModal">
Expand Down
Loading