mirror of
https://github.com/itflow-org/itflow
synced 2026-03-21 04:55:39 +00:00
Compare commits
153 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
939b07422d | ||
|
|
88369d480a | ||
|
|
cf083e94e6 | ||
|
|
11e8f5acfc | ||
|
|
77b3a89eb2 | ||
|
|
f572f4265a | ||
|
|
0b66c8e1be | ||
|
|
a8328a3f56 | ||
|
|
8b42b17121 | ||
|
|
db418ce662 | ||
|
|
96fe566e08 | ||
|
|
a00f26d8a4 | ||
|
|
eeef63d1c3 | ||
|
|
0b88ea85ae | ||
|
|
c564118156 | ||
|
|
01a7dc2068 | ||
|
|
bb44ecec3f | ||
|
|
b7b24d7de6 | ||
|
|
dcca93e34f | ||
|
|
4124188505 | ||
|
|
eb5d59623b | ||
|
|
8631c06731 | ||
|
|
40eb40fd86 | ||
|
|
c486682a0e | ||
|
|
336da073f1 | ||
|
|
d2e187a239 | ||
|
|
f69de29353 | ||
|
|
61de8bc792 | ||
|
|
d31f19707b | ||
|
|
811312466f | ||
|
|
5ecfb3e962 | ||
|
|
77be5af4e5 | ||
|
|
c512a716d2 | ||
|
|
14f5630caf | ||
|
|
8532bdc172 | ||
|
|
9d74bf8e19 | ||
|
|
f75445b4d0 | ||
|
|
e04fa1b696 | ||
|
|
e07dfb5f67 | ||
|
|
3d1af05fc2 | ||
|
|
0e38925d74 | ||
|
|
c0f3343412 | ||
|
|
6a368840fa | ||
|
|
5361391b3b | ||
|
|
b80662bb24 | ||
|
|
4c272b6b8d | ||
|
|
96abdef3ad | ||
|
|
0b04bc79e9 | ||
|
|
cefbbdc3a8 | ||
|
|
83ffe05a99 | ||
|
|
b6f73083ef | ||
|
|
693736023e | ||
|
|
fed87c93ab | ||
|
|
f53b77b556 | ||
|
|
b858d82b0b | ||
|
|
ccb2af6d17 | ||
|
|
8d937ac8f5 | ||
|
|
2786fb65ed | ||
|
|
025532f579 | ||
|
|
5bd03be1ad | ||
|
|
40086f1ce0 | ||
|
|
be66ad9a4c | ||
|
|
0df5c01bb7 | ||
|
|
b85fa38b67 | ||
|
|
546246d7c5 | ||
|
|
d5536e78f4 | ||
|
|
908738b7ca | ||
|
|
797e02bffa | ||
|
|
d856685782 | ||
|
|
1400983d8c | ||
|
|
2a43c5d868 | ||
|
|
a67675c649 | ||
|
|
fc344ef636 | ||
|
|
2ffb2be083 | ||
|
|
069772f27d | ||
|
|
241ec50802 | ||
|
|
b943c9cd89 | ||
|
|
80625f8c3f | ||
|
|
58435d3460 | ||
|
|
7a7ac4a47f | ||
|
|
429dfa5ca4 | ||
|
|
e1f212d30d | ||
|
|
670450bcfb | ||
|
|
83e15e9e4a | ||
|
|
b309081d75 | ||
|
|
f1a7b35aa6 | ||
|
|
469c5ef06d | ||
|
|
07cbe561bd | ||
|
|
b69a70cfc3 | ||
|
|
923001928c | ||
|
|
75ed461c67 | ||
|
|
691aebce91 | ||
|
|
846947ff49 | ||
|
|
65e107d154 | ||
|
|
19b809b699 | ||
|
|
60fe02bb47 | ||
|
|
3e708059c6 | ||
|
|
424104bb66 | ||
|
|
62696b9ebe | ||
|
|
87403e8c2d | ||
|
|
7a5a607ff6 | ||
|
|
a195774726 | ||
|
|
8d0da7b55b | ||
|
|
58c315cd09 | ||
|
|
dd6c4602db | ||
|
|
d413e0c8ff | ||
|
|
b356658635 | ||
|
|
d92f0fc49b | ||
|
|
f206a28cf7 | ||
|
|
70cb0ac635 | ||
|
|
a0ece18876 | ||
|
|
4a22b03952 | ||
|
|
5ebf797c90 | ||
|
|
a20759f1f2 | ||
|
|
c273cab36e | ||
|
|
8306a04eda | ||
|
|
f078203136 | ||
|
|
15e89c3c4e | ||
|
|
595c4f1440 | ||
|
|
91a523dc23 | ||
|
|
8567c97c09 | ||
|
|
3621e99c61 | ||
|
|
d99b9cbe68 | ||
|
|
e319768fd3 | ||
|
|
c30ffcf096 | ||
|
|
7286248fef | ||
|
|
dc49f80cc3 | ||
|
|
1ae2da8054 | ||
|
|
090f4cb560 | ||
|
|
0914716b8e | ||
|
|
ab463c1773 | ||
|
|
36af4d11fc | ||
|
|
14d8dc6fa6 | ||
|
|
2032b48ad3 | ||
|
|
2af795f548 | ||
|
|
7b4edb2948 | ||
|
|
17a906fd03 | ||
|
|
af46a1fd96 | ||
|
|
393c0b8c11 | ||
|
|
e92f2f714d | ||
|
|
42606067c0 | ||
|
|
98bb65509d | ||
|
|
a2599e5d43 | ||
|
|
0390b1bc2a | ||
|
|
531f3ec741 | ||
|
|
127afdca0d | ||
|
|
c4df5bf988 | ||
|
|
30234e044d | ||
|
|
1e98ee8916 | ||
|
|
d5665c2577 | ||
|
|
762ec51a19 | ||
|
|
309ad724ec | ||
|
|
a5f7b7fa9c |
94
CHANGELOG.md
94
CHANGELOG.md
@@ -2,6 +2,98 @@
|
||||
|
||||
This file documents all notable changes made to ITFlow.
|
||||
|
||||
## [25.05]
|
||||
|
||||
### Added / Changed
|
||||
- Expanded file upload allow-list to include .bat and .stk file types.
|
||||
- Added full backup/restore functionality. Backup downloads a zip that includes the SQL dump and uploads folder, setup now has option to restore from zip backup.
|
||||
- Migrated Asset and Contact Links to modals to resolve variable overlap issue.
|
||||
- Added Pagination to Notification Modal.
|
||||
- Removed 500 Records Per Page option.
|
||||
- Removed unused old DB checks in the top nav.
|
||||
- Clients can now use the portal to setup Stripe automatic payments themselves for recurring invoices
|
||||
- Automatic payments are now disabled for all recurring invoices if the saved payment method is removed
|
||||
- Added Card Details and Payment added to Client Stripe.
|
||||
- UI / UX updates to guest pay Make use of cards.
|
||||
- Don't show Checkbox columns when ticket is closed, compact ticket list now matches round pills for status and priority.
|
||||
- Ticket UI/UX update allow the ticket toolbar to be a little more mobile-friendly
|
||||
- UI / UX Updates to Expenses - Combine Category and Description into 1 column.
|
||||
- Country information is now displayed in Invoices, Quotes, Recurring Invoices, Clients, Locations, and the client top header.
|
||||
- Added country-based search filters in Locations and Clients sections.
|
||||
- Changed the settings name from Integrations to Identity Providers to make room for future iDPs (e.g. Google).
|
||||
- Bump FullCalendar from 6.1.15 to 6.1.17.
|
||||
- Bump DataTables from 2.2.2 to 2.3.1.
|
||||
- Bump TCPDF from 6.8.2 to 6.9.4.
|
||||
- Bump tinyMCE from 7.7.1 to 7.9.0.
|
||||
- Bump phpMailer from 6.9.2 to 6.10.0.
|
||||
- Bump stripe-php from 16.4.0 to 17.2.1.
|
||||
|
||||
|
||||
### Fixed
|
||||
- "None" option for SMTP encryption now functions correctly.
|
||||
- Debug table row counts now reflect actual counts instead of relying on SHOW TABLE STATUS.
|
||||
- Archived Categories now display properly.
|
||||
- Stripe saved payment methods are now limited to credit/debit cards only.
|
||||
|
||||
## [25.03.6]
|
||||
|
||||
### Fixed
|
||||
- Set default to date to 2035-12-31 as 9999-12-31 and 2999-12-31 broke certain browsers.
|
||||
- Update Client PDF Export, add header added company logo.
|
||||
- Present Larger clearer Warning about updates on update page.
|
||||
- Allow to search by project reference.
|
||||
|
||||
## [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
|
||||
- Ability to remove additional assets from the ticket details screen.
|
||||
- Fix the ability to remove assets from edit ticket not working when only 1 asset exists.
|
||||
- Fix Database Backup corruption.
|
||||
- Client Portal - show ticket number instead of ticket id in ticket listing.
|
||||
- Add Purchase Reference to copy asset.
|
||||
- Add Link to asset details from the global search.
|
||||
- Fix Bulk assign ticket only showing contacts instead of ITFlow users.
|
||||
|
||||
|
||||
## [25.03.3]
|
||||
|
||||
### Fixed
|
||||
- Fix adding ITFlow user.
|
||||
- Do not alert on inactive recurring invoices.
|
||||
- Fix ticket user assignment including bulk assignment.
|
||||
- Fix adding a location phone extension.
|
||||
- Do not default to +1 Country code, instead default to null.
|
||||
- Do not format numbers unless a country code is entered.
|
||||
- Fix editing network location.
|
||||
- Fix ticket redaction on client replies.
|
||||
- Remove more from user activity as it requires admin privledges.
|
||||
- Fix MFA Enforcement page.
|
||||
|
||||
## [25.03.2]
|
||||
|
||||
### Fixed
|
||||
- Revert DB.sql change
|
||||
|
||||
## [25.03.1]
|
||||
|
||||
### Fixed
|
||||
- Phone number missing in various sections.
|
||||
- Match Database.
|
||||
- Client Export Only display licenses users and assets from the selected client only.
|
||||
|
||||
## [25.03]
|
||||
|
||||
### Fixed
|
||||
@@ -221,4 +313,4 @@ This file documents all notable changes made to ITFlow.
|
||||
## [24.12]
|
||||
|
||||
### Added / Changed
|
||||
- Introduced versioned releases for the first time!
|
||||
- Introduced versioned releases for the first time!
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -12,10 +12,8 @@
|
||||
We operate a rolling release model. Any bug fixes will be released into latest version of ITFlow, so you must stay up-to-date.
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| Beta | :x: |
|
||||
| 24.12 | :white_check_mark: |
|
||||
| 25.1 | :white_check_mark: (When released) |
|
||||
|---------| ------------------ |
|
||||
| 25.05 | :white_check_mark: |
|
||||
|
||||
## Reporting a Vulnerability via GitHub Security Advisories
|
||||
|
||||
|
||||
@@ -48,14 +48,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-history mr-2"></i>App Logs</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-4" autocomplete="off">
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search app logs">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search app logs">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -75,7 +75,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<form class="mb-4" autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search audit logs">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
@@ -85,7 +85,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="">- All Clients -</option>
|
||||
|
||||
@@ -105,7 +105,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="user" onchange="this.form.submit()">
|
||||
<option value="">- All Users -</option>
|
||||
|
||||
@@ -125,7 +125,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="type" onchange="this.form.submit()">
|
||||
<option value="">- All Types -</option>
|
||||
|
||||
@@ -144,7 +144,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="form-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="action" onchange="this.form.submit()">
|
||||
<option value="">- All Actions -</option>
|
||||
|
||||
@@ -198,7 +198,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-sm table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_created_at&order=<?php echo $disp; ?>">
|
||||
|
||||
@@ -8,7 +8,7 @@ require_once "includes/inc_all_admin.php";
|
||||
</div>
|
||||
<div class="card-body" style="text-align: center;">
|
||||
<div class="alert alert-secondary">If you are unable to back up the entire VM, you'll need to back up the files & database individually. There is no built-in restore. See the <a href="https://docs.itflow.org/backups" target="_blank">docs here</a>.</div>
|
||||
<a class="btn btn-primary btn-lg p-3" href="post.php?download_database&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download database</a>
|
||||
<a class="btn btn-primary btn-lg p-3" href="post.php?download_backup&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download Backup</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -20,12 +20,12 @@ require_once "includes/inc_all_admin.php";
|
||||
<div class="card-body">
|
||||
<form action="post.php" method="POST">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<div class="row d-flex justify-content-center">
|
||||
<div class="input-group col-4">
|
||||
<div class="input-group-prepend">
|
||||
<input type="password" class="form-control" placeholder="Enter your account password" name="password" autocomplete="new-password" required>
|
||||
<div class="d-flex justify-content-center">
|
||||
<div class="input-group col-sm-4">
|
||||
<input type="password" class="form-control" placeholder="Enter your account password" name="password" autocomplete="new-password" required>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary" type="submit" name="backup_master_key"><i class="fas fa-key"></i></button>
|
||||
</div>
|
||||
<button class="btn btn-primary" type="submit" name="backup_master_key"><i class="fas fa-fw fa-key mr-2"></i>Get Master Key</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -27,10 +27,6 @@ $sql = mysqli_query(
|
||||
);
|
||||
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
if (isset($_GET['archived'])) {
|
||||
$category = "Archived";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
@@ -98,7 +94,7 @@ if (isset($_GET['archived'])) {
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Ticket</a>
|
||||
<a href="?archived=1"
|
||||
<a href="?<?php echo $url_query_strings_sort ?>&archived=1"
|
||||
class="btn <?php if (isset($_GET['archived'])) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
@@ -150,7 +146,7 @@ if (isset($_GET['archived'])) {
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php
|
||||
if ($category == "Archived") {
|
||||
if ($archived) {
|
||||
?>
|
||||
<a class="dropdown-item text-success confirm-link"
|
||||
href="post.php?unarchive_category=<?php echo $category_id; ?>">
|
||||
|
||||
400
admin_debug.php
400
admin_debug.php
@@ -296,7 +296,13 @@ if ($tablesResult) {
|
||||
|
||||
while ($table = $tablesResult->fetch_assoc()) {
|
||||
$tableName = $table['Name'];
|
||||
$tableRows = $table['Rows'];
|
||||
|
||||
// Accurate row count
|
||||
$countResult = $mysqli->query("SELECT COUNT(*) AS cnt FROM `$tableName`");
|
||||
$countRow = $countResult->fetch_assoc();
|
||||
$tableRows = $countRow['cnt'];
|
||||
$countResult->free();
|
||||
|
||||
$dataLength = $table['Data_length'];
|
||||
$indexLength = $table['Index_length'];
|
||||
$tableSize = ($dataLength + $indexLength) / (1024 * 1024); // Size in MB
|
||||
@@ -336,11 +342,6 @@ if ($tablesResult) {
|
||||
'name' => 'Total database size (MB)',
|
||||
'value' => round($totalSize, 2) . ' MB',
|
||||
];
|
||||
} else {
|
||||
$databaseStats[] = [
|
||||
'name' => 'Database connection error',
|
||||
'value' => $mysqli->error,
|
||||
];
|
||||
}
|
||||
|
||||
// Section: Database Structure Comparison
|
||||
@@ -518,24 +519,26 @@ $mysqli->close();
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<table class="table table-bordered mb-3">
|
||||
<tr>
|
||||
<th>ITFlow release version</th>
|
||||
<th><?php echo APP_VERSION; ?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current DB Version</td>
|
||||
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Code Commit</td>
|
||||
<td><?php echo $commitHash; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Branch</td>
|
||||
<td><?php echo $gitBranch; ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered mb-3">
|
||||
<tr>
|
||||
<th>ITFlow release version</th>
|
||||
<th><?php echo APP_VERSION; ?></th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current DB Version</td>
|
||||
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Code Commit</td>
|
||||
<td><?php echo $commitHash; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Current Branch</td>
|
||||
<td><?php echo $gitBranch; ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- System Information Table -->
|
||||
<h3>System Information</h3>
|
||||
@@ -552,200 +555,209 @@ $mysqli->close();
|
||||
|
||||
<!-- PHP Extensions and Configuration Table -->
|
||||
<h3 class="mt-3">PHP Extensions and Configuration</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<!-- PHP Extensions Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Extensions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpExtensions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<!-- PHP Extensions Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Extensions</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<!-- PHP Configuration Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Configuration</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpConfig as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpExtensions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<!-- PHP Configuration Section -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">PHP Configuration</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Shell Commands</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($shellCommands as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($phpConfig as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Shell Commands</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">SSL Checks</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($sslChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($shellCommands as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">SSL Checks</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Domain Checks</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($domainChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($sslChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">Domain Checks</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($domainChecks as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
|
||||
<!-- File Permissions Table -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">File Permissions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($filePermissions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
<!-- File Permissions Table -->
|
||||
<thead>
|
||||
<tr class="table-secondary">
|
||||
<th colspan="3">File Permissions</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($filePermissions as $check): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($check['name']); ?></td>
|
||||
<td class="text-center">
|
||||
<?php if ($check['passed']): ?>
|
||||
<i class="fas fa-check" style="color:green"></i>
|
||||
<?php else: ?>
|
||||
<i class="fas fa-times" style="color:red"></i>
|
||||
<?php endif; ?>
|
||||
</td>
|
||||
<td><?= htmlspecialchars($check['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Database Structure Comparison Table -->
|
||||
<h3 class="mt-3">Database Structure Comparison</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php if (!empty($dbComparison)): ?>
|
||||
<?php foreach ($dbComparison as $issue): ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php if (!empty($dbComparison)): ?>
|
||||
<?php foreach ($dbComparison as $issue): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($issue['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($issue['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
|
||||
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
<?php else: ?>
|
||||
<tr>
|
||||
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
|
||||
</tr>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<?php endif; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Uploads Directory Stats Table -->
|
||||
<h3 class="mt-3">Uploads Directory Stats</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($uploadsStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($uploadsStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Database Stats Table -->
|
||||
<h3 class="mt-3">Database Stats</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($databaseStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<tbody>
|
||||
<?php foreach ($databaseStats as $stat): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($stat['name']); ?></td>
|
||||
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Table Stats Table -->
|
||||
<h3 class="mt-3">Table Stats</h3>
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Table Name</th>
|
||||
<th>Fields / Rows</th>
|
||||
<th>Size (MB)</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($tableDetails as $table): ?>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-sm table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($table['name']); ?></td>
|
||||
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
|
||||
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
|
||||
<th>Table Name</th>
|
||||
<th>Fields / Rows</th>
|
||||
<th>Size (MB)</th>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php foreach ($tableDetails as $table): ?>
|
||||
<tr>
|
||||
<td><?= htmlspecialchars($table['name']); ?></td>
|
||||
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
|
||||
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -4,13 +4,29 @@ require_once "includes/inc_all_admin.php";
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-3">
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-plug mr-2"></i>Integration Settings</h3>
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-fingerprint mr-2"></i>Identity Providers</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<h4>Client Portal SSO via Microsoft Entra</h4>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Identity Provider <small class='text-secondary'>(Currently only works with Microsft Entra)</small></label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-fingerprint"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" readonly>
|
||||
<option <?php if (empty($config_azure_client_id)) { echo "selected"; } ?>>Disabled</option>
|
||||
<option <?php if ($config_azure_client_id) { echo "selected"; } ?>>Microsoft Entra</option>
|
||||
<option>Google (WIP)</option>
|
||||
<option>Custom SSO (WIP)</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>MS Entra OAuth App (Client) ID</label>
|
||||
<div class="input-group">
|
||||
@@ -33,11 +49,10 @@ require_once "includes/inc_all_admin.php";
|
||||
|
||||
<hr>
|
||||
|
||||
<button type="submit" name="edit_integrations_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
<button type="submit" name="edit_identity_provider" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "includes/footer.php";
|
||||
|
||||
@@ -50,7 +50,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_name&order=<?php echo $disp; ?>">
|
||||
|
||||
@@ -113,13 +113,13 @@ $company_initials = nullable_htmlentities(initials($company_name));
|
||||
|
||||
<label>Phone</label>
|
||||
<div class="form-row">
|
||||
<div class="col-9">
|
||||
<div class="col-md-9">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="+<?php echo $company_phone_country_code; ?>" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo $company_phone_country_code; ?>" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" value="<?php echo $company_phone; ?>" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -295,7 +295,7 @@ require_once "includes/inc_all_admin.php";
|
||||
<option value="4"><?php echo nullable_htmlentities($config_ticket_from_name); ?> (<?php echo nullable_htmlentities($config_ticket_from_email); ?>)</option>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
|
||||
</select>
|
||||
<input type="email" class="form-control " name="email_to" placeholder="Email address to send to">
|
||||
<div class="input-group-append">
|
||||
@@ -319,7 +319,7 @@ require_once "includes/inc_all_admin.php";
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<div class="input-group-append">
|
||||
<button type="submit" name="test_email_imap" class="btn btn-success"><i class="fas fa-fw fa-inbox mr-2"></i>Test</button>
|
||||
<button type="submit" name="test_email_imap" class="btn btn-success" disabled><i class="fas fa-fw fa-inbox mr-2"></i>Test (WIP)</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -18,158 +18,159 @@ require_once "includes/inc_all_admin.php";
|
||||
<label class="custom-control-label" for="enableCronSwitch">Enable Cron (recommended) <small>(several cron scripts must also be added to cron with correct schedules, <a href="https://docs.itflow.org/cron">docs</a>)</small></label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Notification</th>
|
||||
<th>App Notify</th>
|
||||
<th>Tech Email Notify</th>
|
||||
<th>Client Email Notify</th>
|
||||
<th>Create Ticket</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colspan=5>Expirations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_enable_alert_domain_expire" id="customCheck1" <?php if ($config_enable_alert_domain_expire == 1) { echo "checked"; } ?> value="1">
|
||||
<label class="custom-control-label" for="customCheck1"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Billing</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Reminders</div>
|
||||
<small class="text-muted">
|
||||
(This will automatically dispatch a reminder email for the invoice to the primary contact's email every 30 days following the invoice's due date.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_send_invoice_reminders" <?php if ($config_send_invoice_reminders == 1) { echo "checked"; } ?> value="1" id="sendInvoiceRemindersSwitch">
|
||||
<label class="custom-control-label" for="sendInvoiceRemindersSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-redo-alt mr-2"></i>Send Recurring Invoice</div>
|
||||
<small class="text-muted">
|
||||
(This will notify all primary and billing contacts of a client that a new invoice was generated from recurring invoices)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_recurring_auto_send_invoice" <?php if ($config_recurring_auto_send_invoice == 1) { echo "checked"; } ?> value="1" id="sendRecurringSwitch">
|
||||
<label class="custom-control-label" for="sendRecurringSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Operational</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-bell mr-2"></i>Send clients general notification emails</div>
|
||||
<small class="text-secondary">(Should clients receive automatic emails when tickets are raised/closed?)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_ticket_client_general_notifications" <?php if($config_ticket_client_general_notifications == 1){ echo "checked"; } ?> value="1" id="ticketNotificationSwitch">
|
||||
<label class="custom-control-label" for="ticketNotificationSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-link mr-2"></i>Shared Item View</div>
|
||||
<small class="text-secondary">(Notify when Shared items are viewed)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-clock mr-2"></i>Cron Execution</div>
|
||||
<small class="text-secondary">(Notify when the nightly cron job ran)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-download mr-2"></i>ITFlow Updates</div>
|
||||
<small class="text-secondary">(Notify when ITFlow has an update)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Notification</th>
|
||||
<th>App Notify</th>
|
||||
<th>Tech Email Notify</th>
|
||||
<th>Client Email Notify</th>
|
||||
<th>Create Ticket</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<th colspan=5>Expirations</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_enable_alert_domain_expire" id="customCheck1" <?php if ($config_enable_alert_domain_expire == 1) { echo "checked"; } ?> value="1">
|
||||
<label class="custom-control-label" for="customCheck1"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
|
||||
<small class="text-muted">
|
||||
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Billing</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Reminders</div>
|
||||
<small class="text-muted">
|
||||
(This will automatically dispatch a reminder email for the invoice to the primary contact's email every 30 days following the invoice's due date.)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_send_invoice_reminders" <?php if ($config_send_invoice_reminders == 1) { echo "checked"; } ?> value="1" id="sendInvoiceRemindersSwitch">
|
||||
<label class="custom-control-label" for="sendInvoiceRemindersSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-redo-alt mr-2"></i>Send Recurring Invoice</div>
|
||||
<small class="text-muted">
|
||||
(This will notify all primary and billing contacts of a client that a new invoice was generated from recurring invoices)
|
||||
</small>
|
||||
</th>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_recurring_auto_send_invoice" <?php if ($config_recurring_auto_send_invoice == 1) { echo "checked"; } ?> value="1" id="sendRecurringSwitch">
|
||||
<label class="custom-control-label" for="sendRecurringSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th colspan=5>Operational</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-bell mr-2"></i>Send clients general notification emails</div>
|
||||
<small class="text-secondary">(Should clients receive automatic emails when tickets are raised/closed?)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
<div class="custom-control custom-checkbox text-center">
|
||||
<input type="checkbox" class="custom-control-input" name="config_ticket_client_general_notifications" <?php if($config_ticket_client_general_notifications == 1){ echo "checked"; } ?> value="1" id="ticketNotificationSwitch">
|
||||
<label class="custom-control-label" for="ticketNotificationSwitch"></label>
|
||||
</div>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-link mr-2"></i>Shared Item View</div>
|
||||
<small class="text-secondary">(Notify when Shared items are viewed)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-clock mr-2"></i>Cron Execution</div>
|
||||
<small class="text-secondary">(Notify when the nightly cron job ran)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>
|
||||
<div><i class="fas fa-fw fa-download mr-2"></i>ITFlow Updates</div>
|
||||
<small class="text-secondary">(Notify when ITFlow has an update)</small>
|
||||
</th>
|
||||
<td></td>
|
||||
<td></td>
|
||||
<td>
|
||||
</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
|
||||
@@ -11,56 +11,63 @@ $stripe_clients_sql = mysqli_query($mysqli, "SELECT * FROM client_stripe LEFT JO
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<table class="table border border-dark">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Client</th>
|
||||
<th>Stripe Customer ID</th>
|
||||
<th>Stripe Payment ID</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($stripe_clients_sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$stripe_id = nullable_htmlentities($row['stripe_id']);
|
||||
$stripe_pm = nullable_htmlentities($row['stripe_pm']);
|
||||
|
||||
?>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table border border-dark">
|
||||
<thead class="thead-dark text-nowrap">
|
||||
<tr>
|
||||
<td><?php echo "$client_name ($client_id)" ?></td>
|
||||
<td><?php echo $stripe_id; ?></td>
|
||||
<td><?php echo $stripe_pm ?></td>
|
||||
<td>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if (!empty($stripe_pm)) { ?>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?stripe_remove_pm&client_id=<?php echo $client_id ?>&pm=<?php echo $stripe_pm ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-credit-card mr-2"></i>Delete payment method
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a data-toggle="tooltip" data-placement="left" title="May result in duplicate customer records in Stripe" class="dropdown-item text-danger confirm-link" href="post.php?stripe_reset_customer&client_id=<?php echo $client_id ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Reset Stripe
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<th>Client</th>
|
||||
<th>Stripe Customer ID</th>
|
||||
<th>Stripe Payment ID</th>
|
||||
<th>Payment Details</th>
|
||||
<th>Created</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php } ?>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($stripe_clients_sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$stripe_id = nullable_htmlentities($row['stripe_id']);
|
||||
$stripe_pm = nullable_htmlentities($row['stripe_pm']);
|
||||
$stripe_pm_details = nullable_htmlentities($row['stripe_pm_details']);
|
||||
$stripe_pm_created_at = nullable_htmlentities($row['stripe_pm_created_at']);
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo "$client_name ($client_id)"; ?></td>
|
||||
<td><?php echo $stripe_id; ?></td>
|
||||
<td><?php echo $stripe_pm; ?></td>
|
||||
<td><?php echo $stripe_pm_details; ?></td>
|
||||
<td><?php echo $stripe_pm_created_at; ?></td>
|
||||
<td>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if (!empty($stripe_pm)) { ?>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?stripe_remove_pm&client_id=<?php echo $client_id ?>&pm=<?php echo $stripe_pm ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-credit-card mr-2"></i>Delete payment method
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<a data-toggle="tooltip" data-placement="left" title="May result in duplicate customer records in Stripe" class="dropdown-item text-danger confirm-link" href="post.php?stripe_reset_customer&client_id=<?php echo $client_id ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Reset Stripe
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
@@ -72,6 +72,31 @@ require_once "includes/inc_all_admin.php";
|
||||
<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>
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
|
||||
// Default Column Sortby Filter
|
||||
$sort = "ticket_status_name";
|
||||
$sort = "ticket_status_order";
|
||||
$order = "ASC";
|
||||
|
||||
require_once "includes/inc_all_admin.php";
|
||||
@@ -79,7 +79,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
if ($ticket_status_active) {
|
||||
$ticket_status_display = "<div class='text-success text-bold'>Active</div>";
|
||||
} else {
|
||||
$ticket_status_display = "<div class='text-secondary'>Disabled</div>";
|
||||
$ticket_status_display = "<div class='text-secondary'>Inactive</div>";
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -97,7 +97,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<span class='badge badge-pill text-light p-2' style="background-color: <?php echo $ticket_status_color; ?>"><?php echo $ticket_status_name; ?></span>
|
||||
<td><?php echo $ticket_status_display; ?></td>
|
||||
<td>
|
||||
<?php if ( $ticket_status_id > 5 ) { ?>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
@@ -106,13 +105,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<a class="dropdown-item" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_custom_ticket_status_edit.php" data-ajax-id="<?php echo $ticket_status_id; ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_status=<?php echo $ticket_status_id; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php if (!$ticket_status_active) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_status=<?php echo $ticket_status_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token']; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ $sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates WH
|
||||
$row = mysqli_fetch_array($sql_ticket_templates);
|
||||
|
||||
$ticket_template_name = nullable_htmlentities($row['ticket_template_name']);
|
||||
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
|
||||
//$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
|
||||
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
|
||||
$ticket_template_details = $purifier->purify($row['ticket_template_details']);
|
||||
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
|
||||
@@ -30,156 +30,135 @@ $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");
|
||||
|
||||
?>
|
||||
<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>
|
||||
<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="row">
|
||||
<div class="col-9">
|
||||
|
||||
<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>
|
||||
<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>
|
||||
|
||||
</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>
|
||||
</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>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
<h5><?php echo $ticket_template_subject; ?></h5>
|
||||
<div class="card-body prettyContent">
|
||||
<?php echo $ticket_template_details; ?>
|
||||
</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];
|
||||
<div class="col-3">
|
||||
|
||||
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);
|
||||
<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 input-group-sm">
|
||||
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required maxlength="200">
|
||||
<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>
|
||||
</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-2"></i></a>
|
||||
<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-light text-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
<i class="fas 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>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
?>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</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
|
||||
|
||||
|
||||
@@ -32,8 +32,11 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
<?php } ?>
|
||||
|
||||
<?php if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) { ?>
|
||||
<div class="alert alert-warning">
|
||||
<strong>Ensure you have a current <a href="https://docs.itflow.org/backups">app & database backup</a> before updating!</strong>
|
||||
<div class="alert alert-danger">
|
||||
<h1 class="font-weight-bold text-center">⚠️ DANGER ⚠️</h1>
|
||||
<h2 class="font-weight-bold text-center">Do NOT run updates without first taking a backup</h2>
|
||||
<p>VM Snapshots are highly recommended over other methods - see the <a href="https://docs.itflow.org/backups" class="alert-link" target="_blank">docs</a>. Review the <a href="https://github.com/itflow-org/itflow/blob/master/CHANGELOG.md" class="alert-link" target="_blank">changelog</a> for breaking changes that may require manual remediation.</p>
|
||||
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
|
||||
</div>
|
||||
<br>
|
||||
<a class="btn btn-dark btn-lg my-4" href="post.php?update_db"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update Database</h5></a>
|
||||
@@ -46,9 +49,17 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
|
||||
<?php } else {
|
||||
if (!empty($git_log)) { ?>
|
||||
<div class="alert alert-danger">
|
||||
<h1 class="font-weight-bold text-center">⚠️ DANGER ⚠️</h1>
|
||||
<h2 class="font-weight-bold text-center">Do NOT run updates without first taking a backup</h2>
|
||||
<p>VM Snapshots are highly recommended over other methods - see the <a href="https://docs.itflow.org/backups" class="alert-link" target="_blank">docs</a>. Review the <a href="https://github.com/itflow-org/itflow/blob/master/CHANGELOG.md" class="alert-link" target="_blank">changelog</a> for breaking changes that may require manual remediation.</p>
|
||||
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-primary btn-lg my-4" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
|
||||
<a class="btn btn-danger btn-lg" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
|
||||
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?no"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>TEST</h5></a>
|
||||
|
||||
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
|
||||
<a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
|
||||
|
||||
<?php } else { ?>
|
||||
<p><strong>Application Release Version:<br><strong class="text-dark"><?php echo APP_VERSION; ?></strong></p>
|
||||
@@ -56,6 +67,17 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
<p class="text-secondary">Code Commit:<br><strong class="text-dark"><?php echo $current_version; ?></strong></p>
|
||||
<p class="text-muted">You are up to date!<br>Everything is going to be alright</p>
|
||||
<i class="far fa-3x text-dark fa-smile-wink"></i><br>
|
||||
|
||||
<?php if (rand(1,10) == 1) { ?>
|
||||
<br>
|
||||
<div class="alert alert-info alert-dismissible fade show" role="alert">
|
||||
You're up to date, but when was the last time you checked your ITFlow backup works?
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<?php }
|
||||
}
|
||||
|
||||
|
||||
23
ajax.php
23
ajax.php
@@ -294,6 +294,7 @@ if (isset($_GET['get_active_clients'])) {
|
||||
$mysqli,
|
||||
"SELECT client_id, client_name FROM clients
|
||||
WHERE client_archived_at IS NULL
|
||||
$access_permission_query
|
||||
ORDER BY client_accessed_at DESC"
|
||||
);
|
||||
|
||||
@@ -315,7 +316,9 @@ if (isset($_GET['get_client_contacts'])) {
|
||||
$contact_sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT contact_id, contact_name, contact_primary, contact_important, contact_technical FROM contacts
|
||||
LEFT JOIN clients on contact_client_id = client_id
|
||||
WHERE contacts.contact_archived_at IS NULL AND contact_client_id = $client_id
|
||||
$access_permission_query
|
||||
ORDER BY contact_primary DESC, contact_technical DESC, contact_important DESC, contact_name"
|
||||
);
|
||||
|
||||
@@ -383,7 +386,7 @@ if (isset($_POST['update_kanban_status_position'])) {
|
||||
if (isset($_POST['update_kanban_ticket'])) {
|
||||
// Update ticket kanban order and status
|
||||
enforceUserPermission('module_support', 2);
|
||||
|
||||
|
||||
// all tickets on the column
|
||||
$positions = $_POST['positions'];
|
||||
|
||||
@@ -406,7 +409,7 @@ if (isset($_POST['update_kanban_ticket'])) {
|
||||
// if ticket was not moved, just uptdate the order on kanban
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_order = $kanban WHERE ticket_id = $ticket_id");
|
||||
customAction('ticket_update', $ticket_id);
|
||||
} else {
|
||||
} else {
|
||||
// If the ticket was moved from a resolved status to another status, we need to update ticket_resolved_at
|
||||
if ($oldStatus === $statuses['Resolved']) {
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_order = $kanban, ticket_status = $status, ticket_resolved_at = NULL WHERE ticket_id = $ticket_id");
|
||||
@@ -490,7 +493,7 @@ if (isset($_POST['update_kanban_ticket'])) {
|
||||
addToMailQueue($data);
|
||||
}
|
||||
//End Mail IF
|
||||
|
||||
|
||||
} else {
|
||||
// If the ticket was moved from any status to another status
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_order = $kanban, ticket_status = $status WHERE ticket_id = $ticket_id");
|
||||
@@ -512,7 +515,7 @@ if (isset($_POST['update_ticket_tasks_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$ticket_id = intval($_POST['ticket_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -531,7 +534,7 @@ if (isset($_POST['update_task_templates_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$ticket_template_id = intval($_POST['ticket_template_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -550,7 +553,7 @@ if (isset($_POST['update_quote_items_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$quote_id = intval($_POST['quote_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -569,7 +572,7 @@ if (isset($_POST['update_invoice_items_order'])) {
|
||||
$positions = $_POST['positions'];
|
||||
$invoice_id = intval($_POST['invoice_id']);
|
||||
|
||||
foreach ($positions as $position) {
|
||||
foreach ($positions as $position) {
|
||||
$id = intval($position['id']);
|
||||
$order = intval($position['order']);
|
||||
|
||||
@@ -586,13 +589,13 @@ if (isset($_POST['update_recurring_invoice_items_order'])) {
|
||||
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) {
|
||||
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
|
||||
|
||||
@@ -364,6 +364,16 @@ ob_start();
|
||||
</div>
|
||||
|
||||
<?php if ($asset_type !== 'Virtual Machine') { ?>
|
||||
<div class="form-group">
|
||||
<label>Purchase Reference</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number" >
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Purchase Date</label>
|
||||
<div class="input-group">
|
||||
|
||||
69
ajax/ajax_asset_link_credential.php
Normal file
69
ajax/ajax_asset_link_credential.php
Normal file
@@ -0,0 +1,69 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="credential_id">
|
||||
<option value="">- Select a Credential -</option>
|
||||
<?php
|
||||
$sql_credentials_select = mysqli_query($mysqli, "
|
||||
SELECT credentials.credential_id, credentials.credential_name
|
||||
FROM credentials
|
||||
LEFT JOIN assets ON credentials.credential_asset_id = assets.asset_id
|
||||
AND credentials.credential_asset_id = $asset_id
|
||||
WHERE credentials.credential_client_id = $client_id
|
||||
AND credentials.credential_asset_id = 0
|
||||
AND credentials.credential_archived_at IS NULL
|
||||
ORDER BY credentials.credential_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_credentials_select)) {
|
||||
$credential_id = intval($row['credential_id']);
|
||||
$credential_name = nullable_htmlentities($row['credential_name']);
|
||||
?>
|
||||
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
70
ajax/ajax_asset_link_document.php
Normal file
70
ajax/ajax_asset_link_document.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="document_id">
|
||||
<option value="">- Select a Document -</option>
|
||||
<?php
|
||||
$sql_documents_select = mysqli_query($mysqli, "
|
||||
SELECT documents.document_id, documents.document_name
|
||||
FROM documents
|
||||
LEFT JOIN asset_documents
|
||||
ON documents.document_id = asset_documents.document_id
|
||||
AND asset_documents.asset_id = $asset_id
|
||||
WHERE documents.document_client_id = $client_id
|
||||
AND documents.document_archived_at IS NULL
|
||||
AND asset_documents.asset_id IS NULL
|
||||
ORDER BY documents.document_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_documents_select)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = nullable_htmlentities($row['document_name']);
|
||||
?>
|
||||
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
73
ajax/ajax_asset_link_file.php
Normal file
73
ajax/ajax_asset_link_file.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="file_id">
|
||||
<option value="">- Select a File -</option>
|
||||
<?php
|
||||
$sql_files_select = mysqli_query($mysqli, "
|
||||
SELECT files.file_id, files.file_name, folders.folder_name
|
||||
FROM files
|
||||
LEFT JOIN asset_files
|
||||
ON files.file_id = asset_files.file_id
|
||||
AND asset_files.asset_id = $asset_id
|
||||
LEFT JOIN folders
|
||||
ON folders.folder_id = files.file_folder_id
|
||||
WHERE files.file_client_id = $client_id
|
||||
AND asset_files.asset_id IS NULL
|
||||
ORDER BY folders.folder_name ASC, files.file_name ASC
|
||||
");
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_files_select)) {
|
||||
$file_id = intval($row['file_id']);
|
||||
$file_name = nullable_htmlentities($row['file_name']);
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
?>
|
||||
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
68
ajax/ajax_asset_link_service.php
Normal file
68
ajax/ajax_asset_link_service.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="service_id">
|
||||
<option value="">- Select a Service -</option>
|
||||
<?php
|
||||
$sql_services_select = mysqli_query($mysqli, "
|
||||
SELECT services.service_id, services.service_name
|
||||
FROM services
|
||||
LEFT JOIN service_assets
|
||||
ON services.service_id = service_assets.service_id
|
||||
AND service_assets.asset_id = $asset_id
|
||||
WHERE services.service_client_id = $client_id
|
||||
AND service_assets.asset_id IS NULL
|
||||
ORDER BY services.service_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_services_select)) {
|
||||
$service_id = intval($row['service_id']);
|
||||
$service_name = nullable_htmlentities($row['service_name']);
|
||||
?>
|
||||
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_service_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
73
ajax/ajax_asset_link_software.php
Normal file
73
ajax/ajax_asset_link_software.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$asset_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
WHERE asset_id = $asset_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
$client_id = intval($row['asset_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="software_id">
|
||||
<option value="">- Select a Device Software License -</option>
|
||||
<?php
|
||||
$sql_software_select = mysqli_query($mysqli, "
|
||||
SELECT software.software_id, software.software_name
|
||||
FROM software
|
||||
LEFT JOIN software_assets
|
||||
ON software.software_id = software_assets.software_id
|
||||
AND software_assets.asset_id = $asset_id
|
||||
WHERE software.software_client_id = $client_id
|
||||
AND software.software_archived_at IS NULL
|
||||
AND software.software_license_type = 'Device'
|
||||
AND software_assets.asset_id IS NULL
|
||||
ORDER BY software.software_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_software_select)) {
|
||||
$software_id = intval($row['software_id']);
|
||||
$software_name = nullable_htmlentities($row['software_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_software_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
@@ -22,7 +22,7 @@ $contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_
|
||||
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
|
||||
$contact_extension = nullable_htmlentities($row['contact_extension']);
|
||||
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_mobile_country_code));
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_photo = nullable_htmlentities($row['contact_photo']);
|
||||
$contact_pin = nullable_htmlentities($row['contact_pin']);
|
||||
|
||||
@@ -19,7 +19,7 @@ $contact_extension = nullable_htmlentities($row['contact_extension']);
|
||||
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
|
||||
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
|
||||
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_mobile_country_code));
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_pin = nullable_htmlentities($row['contact_pin']);
|
||||
$contact_photo = nullable_htmlentities($row['contact_photo']);
|
||||
@@ -121,7 +121,7 @@ ob_start();
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "+$contact_phone_country_code"; ?>" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "$contact_phone_country_code"; ?>" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" value="<?php echo $contact_phone; ?>" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
@@ -141,7 +141,7 @@ ob_start();
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="mobile_country_code" value="<?php echo "+$contact_mobile_country_code"; ?>" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="mobile_country_code" value="<?php echo "$contact_mobile_country_code"; ?>" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="mobile" value="<?php echo $contact_mobile; ?>" placeholder="Phone Number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
67
ajax/ajax_contact_link_asset.php
Normal file
67
ajax/ajax_contact_link_asset.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-desktop mr-2"></i>Link Asset to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="asset_id">
|
||||
<option value="">- Select an Asset -</option>
|
||||
<?php
|
||||
$sql_assets_select = mysqli_query($mysqli, "
|
||||
SELECT asset_id, asset_name
|
||||
FROM assets
|
||||
WHERE asset_client_id = $client_id
|
||||
AND asset_contact_id = 0
|
||||
AND asset_archived_at IS NULL
|
||||
ORDER BY asset_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_assets_select)) {
|
||||
$asset_id = intval($row['asset_id']);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
?>
|
||||
<option value="<?php echo $asset_id ?>"><?php echo $asset_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
67
ajax/ajax_contact_link_credential.php
Normal file
67
ajax/ajax_contact_link_credential.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="credential_id">
|
||||
<option value="">- Select a Credential -</option>
|
||||
<?php
|
||||
$sql_credentials_select = mysqli_query($mysqli, "
|
||||
SELECT credential_id, credential_name
|
||||
FROM credentials
|
||||
WHERE credential_client_id = $client_id
|
||||
AND credential_contact_id = 0
|
||||
AND credential_archived_at IS NULL
|
||||
ORDER BY credential_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_credentials_select)) {
|
||||
$credential_id = intval($row['credential_id']);
|
||||
$credential_name = nullable_htmlentities($row['credential_name']);
|
||||
?>
|
||||
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
70
ajax/ajax_contact_link_document.php
Normal file
70
ajax/ajax_contact_link_document.php
Normal file
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="document_id">
|
||||
<option value="">- Select a Document -</option>
|
||||
<?php
|
||||
$sql_documents_select = mysqli_query($mysqli, "
|
||||
SELECT documents.document_id, documents.document_name
|
||||
FROM documents
|
||||
LEFT JOIN contact_documents
|
||||
ON documents.document_id = contact_documents.document_id
|
||||
AND contact_documents.contact_id = $contact_id
|
||||
WHERE documents.document_client_id = $client_id
|
||||
AND documents.document_archived_at IS NULL
|
||||
AND contact_documents.contact_id IS NULL
|
||||
ORDER BY documents.document_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_documents_select)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = nullable_htmlentities($row['document_name']);
|
||||
?>
|
||||
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
72
ajax/ajax_contact_link_file.php
Normal file
72
ajax/ajax_contact_link_file.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="file_id">
|
||||
<option value="">- Select a File -</option>
|
||||
<?php
|
||||
$sql_files_select = mysqli_query($mysqli, "
|
||||
SELECT files.file_id, files.file_name, folders.folder_name
|
||||
FROM files
|
||||
LEFT JOIN contact_files
|
||||
ON files.file_id = contact_files.file_id
|
||||
AND contact_files.contact_id = $contact_id
|
||||
LEFT JOIN folders
|
||||
ON folders.folder_id = files.file_folder_id
|
||||
WHERE files.file_client_id = $client_id
|
||||
AND contact_files.contact_id IS NULL
|
||||
ORDER BY folders.folder_name ASC, files.file_name ASC
|
||||
");
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_files_select)) {
|
||||
$file_id = intval($row['file_id']);
|
||||
$file_name = nullable_htmlentities($row['file_name']);
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
?>
|
||||
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
68
ajax/ajax_contact_link_service.php
Normal file
68
ajax/ajax_contact_link_service.php
Normal file
@@ -0,0 +1,68 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="service_id">
|
||||
<option value="">- Select a Service -</option>
|
||||
<?php
|
||||
$sql_services_select = mysqli_query($mysqli, "
|
||||
SELECT services.service_id, services.service_name
|
||||
FROM services
|
||||
LEFT JOIN service_contacts
|
||||
ON services.service_id = service_contacts.service_id
|
||||
AND service_contacts.contact_id = $contact_id
|
||||
WHERE services.service_client_id = $client_id
|
||||
AND service_contacts.contact_id IS NULL
|
||||
ORDER BY services.service_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_services_select)) {
|
||||
$service_id = intval($row['service_id']);
|
||||
$service_name = nullable_htmlentities($row['service_name']);
|
||||
?>
|
||||
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_service_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
71
ajax/ajax_contact_link_software.php
Normal file
71
ajax/ajax_contact_link_software.php
Normal file
@@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
require_once '../includes/ajax_header.php';
|
||||
|
||||
$contact_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
|
||||
WHERE contact_id = $contact_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
$client_id = intval($row['contact_client_id']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="software_id">
|
||||
<option value="">- Select a User Software License -</option>
|
||||
<?php
|
||||
$sql_software_select = mysqli_query($mysqli, "
|
||||
SELECT software.software_id, software.software_name
|
||||
FROM software
|
||||
LEFT JOIN software_contacts
|
||||
ON software.software_id = software_contacts.software_id
|
||||
AND software_contacts.contact_id = $contact_id
|
||||
WHERE software.software_client_id = $client_id
|
||||
AND software.software_archived_at IS NULL
|
||||
AND software.software_license_type = 'User'
|
||||
AND software_contacts.contact_id IS NULL
|
||||
ORDER BY software.software_name ASC
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_software_select)) {
|
||||
$software_id = intval($row['software_id']);
|
||||
$software_name = nullable_htmlentities($row['software_name']);
|
||||
?>
|
||||
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_software_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../includes/ajax_footer.php";
|
||||
?>
|
||||
@@ -8,6 +8,7 @@ $sql = mysqli_query($mysqli, "SELECT * FROM ticket_statuses WHERE ticket_status_
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
|
||||
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
|
||||
$ticket_status_order = intval($row['ticket_status_order']);
|
||||
$ticket_status_active = intval($row['ticket_status_active']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
@@ -30,7 +31,7 @@ ob_start();
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $ticket_status_name; ?>" required>
|
||||
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $ticket_status_name; ?>" required <?php if ($ticket_status_id <= 5) { echo "readonly"; } ?>>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,6 +45,16 @@ ob_start();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="order" placeholder="Leave blank for no order" value="<?php echo $ticket_status_order; ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Status <strong class="text-danger">*</strong></label>
|
||||
<div class="input-group">
|
||||
@@ -52,7 +63,7 @@ ob_start();
|
||||
</div>
|
||||
<select class="form-control select2" name="status" required>
|
||||
<option <?php if ($ticket_status_active == 1) { echo "selected"; } ?> value="1">Active</option>
|
||||
<option <?php if ($ticket_status_active == 0) { echo "selected"; } ?> value="0">Disabled</option>
|
||||
<option <?php if ($ticket_status_active == 0) { echo "selected"; } ?> value="0" <?php if ($ticket_status_id <= 5) { echo "disabled"; } ?>>Inactive</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -209,7 +209,7 @@ ob_start();
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "+$location_phone_country_code"; ?>" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo $location_phone_country_code; ?>" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" value="<?php echo $location_phone; ?>" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
@@ -229,7 +229,7 @@ ob_start();
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="fax_country_code" value="<?php echo "+$location_fax_country_code"; ?>" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="fax_country_code" value="<?php echo $location_fax_country_code; ?>" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="fax" value="<?php echo $location_fax; ?>" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -90,7 +90,7 @@ ob_start();
|
||||
$location_id = intval($row['location_id']);
|
||||
$location_name = nullable_htmlentities($row['location_name']);
|
||||
?>
|
||||
<option value="<?php echo $location_id; ?>" <?php if ($location_id = $network_location_id) { echo "selected"; } ?>>
|
||||
<option value="<?php echo $location_id; ?>" <?php if ($location_id == $network_location_id) { echo "selected"; } ?>>
|
||||
<?php echo $location_name; ?>
|
||||
</option>
|
||||
<?php
|
||||
|
||||
@@ -25,46 +25,56 @@ ob_start();
|
||||
|
||||
<div class="modal-body bg-white">
|
||||
<?php if ($num_notifications) { ?>
|
||||
<table class="table table-sm table-hover table-borderless">
|
||||
|
||||
|
||||
<?php while ($row = mysqli_fetch_array($sql)) {
|
||||
<?php while ($row = mysqli_fetch_array($sql)) {
|
||||
|
||||
$notification_id = intval($row["notification_id"]);
|
||||
$notification_type = nullable_htmlentities($row["notification_type"]);
|
||||
$notification_details = nullable_htmlentities($row["notification"]);
|
||||
$notification_action = nullable_htmlentities(
|
||||
$row["notification_action"]
|
||||
);
|
||||
$notification_timestamp_formated = date(
|
||||
"M d g:ia",
|
||||
strtotime($row["notification_timestamp"])
|
||||
);
|
||||
$notification_client_id = intval($row["notification_client_id"]);
|
||||
if (empty($notification_action)) {
|
||||
$notification_action = "#";
|
||||
$notification_id = intval($row["notification_id"]);
|
||||
$notification_type = nullable_htmlentities($row["notification_type"]);
|
||||
$notification_details = nullable_htmlentities($row["notification"]);
|
||||
$notification_action = nullable_htmlentities(
|
||||
$row["notification_action"]
|
||||
);
|
||||
$notification_timestamp_formated = date(
|
||||
"M d g:ia",
|
||||
strtotime($row["notification_timestamp"])
|
||||
);
|
||||
$notification_client_id = intval($row["notification_client_id"]);
|
||||
if (empty($notification_action)) {
|
||||
$notification_action = "#";
|
||||
}
|
||||
?>
|
||||
|
||||
<tr class="notification-item">
|
||||
<th>
|
||||
<a class="text-dark" href="<?php echo $notification_action; ?>">
|
||||
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
|
||||
<small class="text-muted float-right">
|
||||
<?php echo $notification_timestamp_formated; ?>
|
||||
</small>
|
||||
<br>
|
||||
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
<a class="text-dark dropdown-item px-1" href="<?php echo $notification_action; ?>">
|
||||
<div>
|
||||
<span class="text-bold">
|
||||
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
|
||||
</span>
|
||||
<small class="text-muted float-right">
|
||||
<?php echo $notification_timestamp_formated; ?>
|
||||
</small>
|
||||
</table>
|
||||
<div class="text-center mt-2">
|
||||
<button id="prev-btn" class="btn btn-sm btn-outline-secondary mr-2"><i class="fas fa-caret-left"></i></button>
|
||||
<button id="next-btn" class="btn btn-sm btn-outline-secondary"><i class="fas fa-caret-right"></i></button>
|
||||
</div>
|
||||
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
|
||||
</a>
|
||||
|
||||
<?php
|
||||
}} else { ?>
|
||||
<div class="text-center text-secondary py-5">
|
||||
<?php } else { ?>
|
||||
<div class="text-center text-secondary pt-3">
|
||||
<i class='far fa-6x fa-bell-slash'></i>
|
||||
<h3 class="mt-3">No Notifications</h3>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="modal-footer bg-white justify-content-end">
|
||||
<div class="modal-footer bg-white">
|
||||
<?php if ($num_notifications) { ?>
|
||||
|
||||
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION[
|
||||
@@ -85,4 +95,41 @@ ob_start();
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
var perPage = 8;
|
||||
var $items = $(".notification-item");
|
||||
var totalItems = $items.length;
|
||||
var totalPages = Math.ceil(totalItems / perPage);
|
||||
var currentPage = 0;
|
||||
|
||||
function showPage(page) {
|
||||
$items.hide().slice(page * perPage, (page + 1) * perPage).show();
|
||||
$("#prev-btn").prop("disabled", page === 0);
|
||||
$("#next-btn").prop("disabled", page >= totalPages - 1);
|
||||
$("#page-indicator").text(`Page ${page + 1} of ${totalPages} (${totalItems} total)`);
|
||||
}
|
||||
|
||||
$("#prev-btn").on("click", function () {
|
||||
if (currentPage > 0) {
|
||||
currentPage--;
|
||||
showPage(currentPage);
|
||||
}
|
||||
});
|
||||
|
||||
$("#next-btn").on("click", function () {
|
||||
if (currentPage < totalPages - 1) {
|
||||
currentPage++;
|
||||
showPage(currentPage);
|
||||
}
|
||||
});
|
||||
|
||||
if (totalItems <= perPage) {
|
||||
$("#prev-btn, #next-btn, #page-indicator").hide();
|
||||
}
|
||||
|
||||
showPage(currentPage);
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php require_once "../includes/ajax_footer.php";
|
||||
|
||||
@@ -85,6 +85,25 @@ ob_start();
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Client</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-users"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="client_id">
|
||||
<option value="0">- No Client -</option>
|
||||
<?php
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$select_client_id = intval($row['client_id']);
|
||||
$select_client_name = nullable_htmlentities($row['client_name']);
|
||||
?>
|
||||
<option value="<?php echo $select_client_id; ?>" <?php if ($client_id == $select_client_id) { echo "selected"; } ?>><?php echo $select_client_name; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="edit_project" class="btn btn-primary text-bold">
|
||||
|
||||
@@ -11,9 +11,6 @@ $sql = mysqli_query($mysqli, "SELECT * FROM ticket_replies
|
||||
);
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$ticket_reply_type = nullable_htmlentities($row['ticket_reply_type']);
|
||||
$ticket_reply_time_worked = date_create($row['ticket_reply_time_worked']);
|
||||
$ticket_reply_time_worked_formatted = date_format($ticket_reply_time_worked, 'H:i:s');
|
||||
$ticket_reply = nullable_htmlentities($row['ticket_reply']);
|
||||
$client_id = intval($row['ticket_client_id']);
|
||||
|
||||
@@ -31,10 +28,6 @@ ob_start();
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="ticket_reply_id" value="<?php echo $ticket_reply_id; ?>">
|
||||
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
|
||||
<input type="hidden" name="ticket_reply_type" value="<?php echo $ticket_reply_type; ?>">
|
||||
<?php if (!empty($ticket_reply_time_worked)) { ?>
|
||||
<input type="hidden" name="time" value="<?php echo $ticket_reply_time_worked_formatted; ?>">
|
||||
<?php } ?>
|
||||
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
@@ -44,7 +37,7 @@ ob_start();
|
||||
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="edit_ticket_reply" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
<button type="submit" name="redact_ticket_reply" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -10,7 +10,7 @@ $row = mysqli_fetch_array($sql);
|
||||
$task_template_name = nullable_htmlentities($row['task_template_name']);
|
||||
$task_template_order = intval($row['task_template_order']);
|
||||
$task_template_completion_estimate = intval($row['task_template_completion_estimate']);
|
||||
$task_template_description = nullable_htmlentities($row['task_template_description']);
|
||||
//$task_template_description = nullable_htmlentities($row['task_template_description']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
ob_start();
|
||||
|
||||
@@ -115,7 +115,7 @@ ob_start();
|
||||
|
||||
$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']);
|
||||
|
||||
@@ -127,7 +127,7 @@ ob_start();
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "+$vendor_phone_country_code"; ?>" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo $vendor_phone_country_code; ?>" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" value="<?php echo $vendor_phone; ?>" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -39,7 +39,7 @@ if (!empty($subject)) {
|
||||
|
||||
// Insert ticket
|
||||
$url_key = randomString(156);
|
||||
$insert_sql = mysqli_query($mysqli,"INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $billable, ticket_vendor_ticket_number = '$vendor_ticket_number', ticket_vendor_id = $vendor_id, ticket_created_by = 0, ticket_assigned_to = $assigned_to, ticket_contact_id = $contact, ticket_url_key = '$url_key', ticket_client_id = $client_id");
|
||||
$insert_sql = mysqli_query($mysqli,"INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'API', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $billable, ticket_vendor_ticket_number = '$vendor_ticket_number', ticket_vendor_id = $vendor_id, ticket_created_by = 0, ticket_assigned_to = $assigned_to, ticket_contact_id = $contact, ticket_url_key = '$url_key', ticket_client_id = $client_id");
|
||||
|
||||
// Check insert & get insert ID
|
||||
if ($insert_sql) {
|
||||
|
||||
@@ -94,7 +94,7 @@ if (isset($_GET['asset_id'])) {
|
||||
$ticket_count = mysqli_num_rows($sql_related_tickets);
|
||||
|
||||
// Related Recurring Tickets Query
|
||||
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
|
||||
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT recurring_tickets.* FROM recurring_tickets
|
||||
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
|
||||
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
|
||||
GROUP BY recurring_tickets.recurring_ticket_id
|
||||
@@ -244,7 +244,7 @@ if (isset($_GET['asset_id'])) {
|
||||
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 } ?>
|
||||
@@ -378,34 +378,47 @@ if (isset($_GET['asset_id'])) {
|
||||
<div class="dropdown dropleft">
|
||||
<button type="button" class="btn btn-outline-primary" data-toggle="dropdown"><i class="fas fa-link mr-2"></i>Link</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkSoftwareModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_software.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-cube mr-2"></i>License
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkCredentialModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_credential.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-key mr-2"></i>Credential
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkServiceModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_service.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-stream mr-2"></i>Service
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkDocumentModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_document.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-folder mr-2"></i>Document
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkFileModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_asset_link_file.php"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<i class="fa fa-fw fa-paperclip mr-2"></i>File
|
||||
</a>
|
||||
|
||||
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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">
|
||||
@@ -1193,10 +1206,4 @@ require_once "modals/credential_add_modal.php";
|
||||
require_once "modals/client_document_add_modal.php";
|
||||
require_once "modals/client_file_upload_modal.php";
|
||||
|
||||
require_once "modals/asset_link_software_modal.php";
|
||||
require_once "modals/asset_link_credential_modal.php";
|
||||
require_once "modals/asset_link_service_modal.php";
|
||||
require_once "modals/asset_link_document_modal.php";
|
||||
require_once "modals/asset_link_file_modal.php";
|
||||
|
||||
require_once "includes/footer.php";
|
||||
|
||||
14
assets.php
14
assets.php
@@ -205,7 +205,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
<?php if ($client_url) { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="location" onchange="this.form.submit()">
|
||||
<option value="">- All Locations -</option>
|
||||
|
||||
@@ -233,7 +233,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
|
||||
|
||||
@@ -338,7 +338,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table border table-hover">
|
||||
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?>">
|
||||
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<td class="bg-light pr-0">
|
||||
<div class="form-check">
|
||||
@@ -519,7 +519,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
if ($contact_name) {
|
||||
$contact_name_display = "<a href='#'
|
||||
data-toggle='ajax-modal'
|
||||
data-modal-size='lg'
|
||||
data-modal-size='xl'
|
||||
data-ajax-url='ajax/ajax_contact_details.php'
|
||||
data-ajax-id='$asset_contact_id'>
|
||||
$contact_name $contact_archive_display
|
||||
@@ -550,11 +550,7 @@ if (mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-modal-size="lg"
|
||||
data-ajax-url="ajax/ajax_asset_details.php?<?php echo $client_url; ?>"
|
||||
data-ajax-id="<?php echo $asset_id; ?>">
|
||||
<a class="text-dark" href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">
|
||||
<div class="media">
|
||||
<i class="fa fa-fw fa-2x fa-<?php echo $device_icon; ?> mr-3 mt-1"></i>
|
||||
<div class="media-body">
|
||||
|
||||
@@ -56,6 +56,7 @@ header("X-Frame-Options: DENY"); // Legacy
|
||||
</a>
|
||||
<div class="dropdown-menu" aria-labelledby="navbarDropdown1">
|
||||
<a class="dropdown-item" href="invoices.php">Invoices</a>
|
||||
<a class="dropdown-item" href="recurring_invoices.php">Recurring Invoices</a>
|
||||
<a class="dropdown-item" href="quotes.php">Quotes</a>
|
||||
<a class="dropdown-item" href="autopay.php">Auto Payment</a>
|
||||
</div>
|
||||
|
||||
@@ -38,7 +38,7 @@ if (isset($_POST['add_ticket'])) {
|
||||
$new_config_ticket_next_number = $config_ticket_next_number + 1;
|
||||
mysqli_query($mysqli, "UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
|
||||
|
||||
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_category = $category, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $config_ticket_default_billable, ticket_created_by = 0, ticket_contact_id = $session_contact_id, ticket_url_key = '$url_key', ticket_client_id = $session_client_id");
|
||||
mysqli_query($mysqli, "INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'Portal', ticket_category = $category, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $config_ticket_default_billable, ticket_created_by = $session_user_id, ticket_contact_id = $session_contact_id, ticket_url_key = '$url_key', ticket_client_id = $session_client_id");
|
||||
$ticket_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Notify agent DL of the new ticket, if populated with a valid email
|
||||
@@ -424,7 +424,7 @@ if (isset($_POST['edit_contact'])) {
|
||||
logAction("Contact", "Edit", "Client contact $session_contact_name edited contact $contact_name in the client portal", $session_client_id, $contact_id);
|
||||
|
||||
$_SESSION['alert_message'] = "Contact $contact_name updated";
|
||||
|
||||
|
||||
header('Location: contacts.php');
|
||||
|
||||
customAction('contact_update', $contact_id);
|
||||
@@ -597,10 +597,22 @@ if (isset($_GET['stripe_save_card'])) {
|
||||
|
||||
// Get some card/payment method details for the email/logging
|
||||
$payment_method_details = $stripe->paymentMethods->retrieve($payment_method);
|
||||
$card_info = sanitizeInput($payment_method_details->card->display_brand) . " " . sanitizeInput($payment_method_details->card->last4);
|
||||
$card_type = sanitizeInput($payment_method_details->card->brand);
|
||||
$last4 = sanitizeInput($payment_method_details->card->last4);
|
||||
$expiry_month = sanitizeInput($payment_method_details->card->exp_month);
|
||||
$expiry_year = sanitizeInput($payment_method_details->card->exp_year);
|
||||
|
||||
// Format the payment details string (Visa - 4324 | Exp 12/25)
|
||||
$stripe_pm_details = "$card_type - $last4 | Exp $expiry_month/$expiry_year";
|
||||
|
||||
// Save the formatted payment details into stripe_pm_details
|
||||
$update_query = "
|
||||
UPDATE client_stripe
|
||||
SET stripe_pm_details = '$stripe_pm_details'
|
||||
WHERE client_id = $session_client_id LIMIT 1";
|
||||
mysqli_query($mysqli, $update_query);
|
||||
|
||||
// Send email confirmation
|
||||
|
||||
// Company Details & Settings
|
||||
$sql_settings = mysqli_query($mysqli, "SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
|
||||
$row = mysqli_fetch_array($sql_settings);
|
||||
@@ -617,7 +629,7 @@ if (isset($_GET['stripe_save_card'])) {
|
||||
|
||||
if (!empty($config_smtp_host)) {
|
||||
$subject = "Payment method saved";
|
||||
$body = "Hello $session_contact_name,<br><br>We’re writing to confirm that your payment details have been securely stored with Stripe, our trusted payment processor.<br><br>By agreeing to save your payment information, you have authorized us to automatically bill your card ($card_info) for any future invoices. The payment details you’ve provided are securely stored with Stripe and will be used solely for invoices. We do not have access to your full card details.<br><br>You may update or remove your payment information at any time using the portal.<br><br>Thank you for your business!<br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
|
||||
$body = "Hello $session_contact_name,<br><br>We’re writing to confirm that your payment details have been securely stored with Stripe, our trusted payment processor.<br><br>By agreeing to save your payment information, you have authorized us to automatically bill your card ($stripe_pm_details) for any future invoices. The payment details you’ve provided are securely stored with Stripe and will be used solely for invoices. We do not have access to your full card details.<br><br>You may update or remove your payment information at any time using the portal.<br><br>Thank you for your business!<br><br>--<br>$company_name - Billing Department<br>$config_invoice_from_email<br>$company_phone";
|
||||
|
||||
$data = [
|
||||
[
|
||||
@@ -635,12 +647,11 @@ if (isset($_GET['stripe_save_card'])) {
|
||||
}
|
||||
|
||||
// Logging
|
||||
logAction("Stripe", "Update", "$session_contact_name saved payment method ($card_info) for future automatic payments (PM: $payment_method)", $session_client_id, $session_client_id);
|
||||
logAction("Stripe", "Update", "$session_contact_name saved payment method ($stripe_pm_details) for future automatic payments (PM: $payment_method)", $session_client_id, $session_client_id);
|
||||
|
||||
// Redirect
|
||||
$_SESSION['alert_message'] = "Payment method saved - thank you";
|
||||
header('Location: autopay.php');
|
||||
|
||||
}
|
||||
|
||||
if (isset($_GET['stripe_remove_pm'])) {
|
||||
@@ -677,11 +688,65 @@ if (isset($_GET['stripe_remove_pm'])) {
|
||||
}
|
||||
|
||||
// Remove payment method from ITFlow
|
||||
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = NULL WHERE client_id = $session_client_id LIMIT 1");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE client_stripe SET stripe_pm = NULL, stripe_pm_details = NULL WHERE client_id = $session_client_id LIMIT 1");
|
||||
|
||||
// Remove Auto Pay on recurring invoices that are stripe
|
||||
$sql_recurring_invoices = mysqli_query($mysqli, "SELECT recurring_invoice_id FROM recurring_invoices WHERE recurring_invoice_client_id = $session_client_id");
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_recurring_invoices)) {
|
||||
$recurring_invoice_id = intval($row['recurring_invoice_id']);
|
||||
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe' AND recurring_payment_recurring_invoice_id = $recurring_invoice_id");
|
||||
}
|
||||
|
||||
// Logging & Redirect
|
||||
logAction("Stripe", "Update", "$session_contact_name deleted saved Stripe payment method (PM: $payment_method)", $session_client_id, $session_client_id);
|
||||
|
||||
$_SESSION['alert_message'] = "Payment method removed";
|
||||
header('Location: autopay.php');
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['add_recurring_payment'])) {
|
||||
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
|
||||
// Get Recurring Info for logging and alerting
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
$recurring_invoice_amount = floatval($row['recurring_invoice_amount']);
|
||||
$recurring_invoice_currency_code = sanitizeInput($row['recurring_invoice_currency_code']);
|
||||
|
||||
mysqli_query($mysqli,"INSERT INTO recurring_payments SET recurring_payment_currency_code = '$recurring_invoice_currency_code', recurring_payment_account_id = $config_stripe_account, recurring_payment_method = 'Stripe', recurring_payment_recurring_invoice_id = $recurring_invoice_id");
|
||||
|
||||
// Get Payment ID for reference
|
||||
$recurring_payment_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Logging
|
||||
logAction("Recurring Invoice", "Auto Payment", "$session_name created Auto Pay for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number in the amount of " . numfmt_format_currency($currency_format, $recurring_invoice_amount, $recurring_invoice_currency_code), $session_client_id, $recurring_invoice_id);
|
||||
|
||||
|
||||
$_SESSION['alert_message'] = "Automatic Payment enabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number";
|
||||
|
||||
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
||||
}
|
||||
|
||||
if (isset($_POST['delete_recurring_payment'])) {
|
||||
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
|
||||
|
||||
// Get the invoice total and details
|
||||
$sql = mysqli_query($mysqli,"SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id");
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$recurring_invoice_prefix = sanitizeInput($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
|
||||
mysqli_query($mysqli,"DELETE FROM recurring_payments WHERE recurring_payment_recurring_invoice_id = $recurring_invoice_id");
|
||||
|
||||
// Logging
|
||||
logAction("Recurring Invoice", "Auto Payment", "$session_name removed auto Pay from Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number", $session_client_id, $recurring_invoice_id);
|
||||
|
||||
$_SESSION['alert_message'] = "Automatic Payment disabled for Recurring Invoice $recurring_invoice_prefix$recurring_invoice_number";
|
||||
|
||||
header("Location: " . $_SERVER["HTTP_REFERER"]);
|
||||
|
||||
}
|
||||
|
||||
120
client/recurring_invoices.php
Normal file
120
client/recurring_invoices.php
Normal file
@@ -0,0 +1,120 @@
|
||||
<?php
|
||||
/*
|
||||
* Client Portal
|
||||
* Invoices for PTC
|
||||
*/
|
||||
|
||||
header("Content-Security-Policy: default-src 'self'");
|
||||
|
||||
require_once "includes/inc_all.php";
|
||||
|
||||
|
||||
if ($session_contact_primary == 0 && !$session_contact_is_billing_contact) {
|
||||
header("Location: post.php?logout");
|
||||
exit();
|
||||
}
|
||||
|
||||
// Get client's StripeID from database
|
||||
$stripe_client_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT * FROM client_stripe WHERE client_id = $session_client_id LIMIT 1"));
|
||||
if ($stripe_client_details) {
|
||||
$stripe_pm = sanitizeInput($stripe_client_details['stripe_pm']);
|
||||
}
|
||||
|
||||
$recurring_invoices_sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices
|
||||
LEFT JOIN recurring_payments ON recurring_payment_recurring_invoice_id = recurring_invoice_id
|
||||
WHERE recurring_invoice_client_id = $session_client_id
|
||||
AND recurring_invoice_status = 1
|
||||
ORDER BY recurring_invoice_next_date DESC"
|
||||
);
|
||||
|
||||
?>
|
||||
|
||||
<h3>Recurring Invoices</h3>
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-10">
|
||||
|
||||
<table class="table tabled-bordered border border-dark">
|
||||
<thead class="thead-dark">
|
||||
<tr>
|
||||
<th>Scope</th>
|
||||
<th>Amount</th>
|
||||
<th>Next Bill Date</th>
|
||||
<th>Frequency</th>
|
||||
<?php if ($config_stripe_enable) { ?>
|
||||
<th>Auto Pay</th>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($recurring_invoices_sql)) {
|
||||
$recurring_invoice_id = intval($row['recurring_invoice_id']);
|
||||
$recurring_invoice_prefix = nullable_htmlentities($row['recurring_invoice_prefix']);
|
||||
$recurring_invoice_number = intval($row['recurring_invoice_number']);
|
||||
$recurring_invoice_scope = nullable_htmlentities($row['recurring_invoice_scope']);
|
||||
$recurring_invoice_status = nullable_htmlentities($row['recurring_invoice_status']);
|
||||
$recurring_invoice_next_date = nullable_htmlentities($row['recurring_invoice_next_date']);
|
||||
$recurring_invoice_frequency = nullable_htmlentities($row['recurring_invoice_frequency']);
|
||||
$recurring_invoice_amount = floatval($row['recurring_invoice_amount']);
|
||||
$recurring_payment_id = intval($row['recurring_payment_id']);
|
||||
$recurring_payment_recurring_invoice_id = intval($row['recurring_payment_recurring_invoice_id']);
|
||||
if ($config_stripe_enable) {
|
||||
if ($recurring_payment_recurring_invoice_id) {
|
||||
$auto_pay_display = "
|
||||
Yes
|
||||
<a href='post.php?delete_recurring_payment=$recurring_payment_id' title='Remove'>
|
||||
<i class='fas fa-fw fa-times-circle'></i>
|
||||
</a>
|
||||
";
|
||||
} else {
|
||||
$auto_pay_display = "
|
||||
<a href='#' data-toggle='modal' data-target='#addRecurringPaymentModal$recurring_invoice_id'>
|
||||
Create
|
||||
</a>
|
||||
";
|
||||
//require "recurring_payment_add_modal.php";
|
||||
}
|
||||
}
|
||||
|
||||
if (empty($recurring_invoice_scope)) {
|
||||
$recurring_invoice_scope_display = "-";
|
||||
} else {
|
||||
$recurring_invoice_scope_display = $recurring_invoice_scope;
|
||||
}
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $recurring_invoice_scope_display; ?></td>
|
||||
<td><?php echo numfmt_format_currency($currency_format, $recurring_invoice_amount, $session_company_currency); ?></td>
|
||||
<td><?php echo $recurring_invoice_next_date; ?></td>
|
||||
<td><?php echo ucwords($recurring_invoice_frequency); ?>ly</td>
|
||||
<?php if ($config_stripe_enable) { ?>
|
||||
<td>
|
||||
<?php if ($stripe_pm) { ?>
|
||||
<form class="form" action="post.php" method="post">
|
||||
<input type="hidden" name="recurring_invoice_id" value="<?php echo $recurring_invoice_id; ?>">
|
||||
<?php if ($recurring_payment_recurring_invoice_id) { ?>
|
||||
<button type="submit" name="delete_recurring_payment" class="btn btn-outline-dark"><i class="fas fa-times mr-2"></i>Disable</button>
|
||||
<?php } else { ?>
|
||||
<button type="submit" name="add_recurring_payment" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Enable</button>
|
||||
<?php } ?>
|
||||
</form>
|
||||
<?php } else { ?>
|
||||
<a href="autopay.php">Add Card Details First</a>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<?php } ?>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "includes/footer.php";
|
||||
@@ -62,7 +62,7 @@ $all_tickets = mysqli_query($mysqli, "SELECT ticket_id, ticket_prefix, ticket_nu
|
||||
$ticket_contact_name = nullable_htmlentities($row['contact_name']);
|
||||
|
||||
echo "<tr>";
|
||||
echo "<td> <a href='ticket.php?id=$ticket_id'> $ticket_prefix$ticket_id</a></td>";
|
||||
echo "<td> <a href='ticket.php?id=$ticket_id'> $ticket_prefix$ticket_number</a></td>";
|
||||
echo "<td> <a href='ticket.php?id=$ticket_id'> $ticket_subject</a></td>";
|
||||
echo "<td>$ticket_contact_name</td>";
|
||||
echo "<td>$ticket_status</td>";
|
||||
|
||||
@@ -9,9 +9,6 @@ require_once "includes/inc_all_client.php";
|
||||
// Perms
|
||||
enforceUserPermission('module_support');
|
||||
|
||||
// Rebuild URL
|
||||
$url_query_strings_sort = http_build_query($get_copy);
|
||||
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM racks
|
||||
@@ -323,7 +320,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
} else {
|
||||
// No device in this row
|
||||
?>
|
||||
<td class="text-center">No device</td>
|
||||
<td class="text-center text-secondary">--</td>
|
||||
<td></td>
|
||||
<?php
|
||||
}
|
||||
|
||||
10
clients.php
10
clients.php
@@ -62,7 +62,7 @@ $sql = mysqli_query(
|
||||
WHERE (client_name LIKE '%$q%' OR client_abbreviation LIKE '%$q%' OR client_type LIKE '%$q%' OR client_referral LIKE '%$q%'
|
||||
OR contact_email LIKE '%$q%' OR contact_name LIKE '%$q%' OR contact_phone LIKE '%$phone_query%'
|
||||
OR contact_mobile LIKE '%$phone_query%' OR location_address LIKE '%$q%'
|
||||
OR location_city LIKE '%$q%' OR location_state LIKE '%$q%' OR location_zip LIKE '%$q%'
|
||||
OR location_city LIKE '%$q%' OR location_state LIKE '%$q%' OR location_zip LIKE '%$q%' OR location_country LIKE '%$q%'
|
||||
OR tag_name LIKE '%$q%' OR client_tax_id_number LIKE '%$q%')
|
||||
AND client_$archive_query
|
||||
AND DATE(client_created_at) BETWEEN '$dtf' AND '$dtt'
|
||||
@@ -111,7 +111,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<input type="hidden" name="archived" value="<?php echo $archived; ?>">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-sm-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search <?php if($leads_filter == 0){ echo "clients"; } else { echo "leads"; } ?>" autofocus>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
@@ -126,7 +126,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<a href="?leads=1" class="btn btn-<?php if ($leads_filter == 1){ echo "primary"; } else { echo "default"; } ?>"><i class="fa fa-fw fa-bullhorn mr-2"></i>Leads</a>
|
||||
</div>
|
||||
|
||||
<div class="btn-group mr-2">
|
||||
<div class="btn-group">
|
||||
<a href="?<?php echo $url_query_strings_sort ?>&archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
|
||||
class="btn btn-<?php if ($archived == 1) { echo "primary"; } else { echo "default"; } ?>">
|
||||
<i class="fa fa-fw fa-archive mr-2"></i>Archived
|
||||
@@ -248,7 +248,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-hover table-borderless">
|
||||
<thead class="<?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="<?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
|
||||
@@ -286,7 +286,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
if (empty($location_address) && empty($location_city) && empty($location_state) && empty($location_zip)) {
|
||||
$location_address_display = "-";
|
||||
} else {
|
||||
$location_address_display = "$location_address<br>$location_city $location_state $location_zip";
|
||||
$location_address_display = "<i class='fa fa-fw fa-map-marker-alt text-secondary mr-2'></i>$location_address<br><i class='fa fa-fw mr-2'></i>$location_city $location_state $location_zip<br><i class='fa fa-fw mr-2'></i><small>$location_country</small>";
|
||||
}
|
||||
$contact_id = intval($row['contact_id']);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
|
||||
@@ -32,7 +32,7 @@ if (isset($_GET['contact_id'])) {
|
||||
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
|
||||
$contact_extension = nullable_htmlentities($row['contact_extension']);
|
||||
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_mobile_country_code));
|
||||
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_photo = nullable_htmlentities($row['contact_photo']);
|
||||
$contact_pin = nullable_htmlentities($row['contact_pin']);
|
||||
@@ -294,31 +294,47 @@ if (isset($_GET['contact_id'])) {
|
||||
<div class="dropdown dropleft">
|
||||
<button type="button" class="btn btn-outline-primary" data-toggle="dropdown"><i class="fas fa-link mr-2"></i>Link</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkAssetModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_asset.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-desktop mr-2"></i>Asset
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkSoftwareModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_software.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-cube mr-2"></i>License
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkCredentialModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_credential.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-key mr-2"></i>Credential
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkServiceModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_service.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-stream mr-2"></i>Service
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkDocumentModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_document.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-folder mr-2"></i>Document
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkFileModal">
|
||||
<a class="dropdown-item text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_contact_link_file.php"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<i class="fa fa-fw fa-paperclip mr-2"></i>File
|
||||
</a>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1192,11 +1208,4 @@ require_once "modals/credential_add_modal.php";
|
||||
require_once "modals/client_document_add_modal.php";
|
||||
require_once "modals/client_file_upload_modal.php";
|
||||
|
||||
require_once "modals/contact_link_asset_modal.php";
|
||||
require_once "modals/contact_link_software_modal.php";
|
||||
require_once "modals/contact_link_credential_modal.php";
|
||||
require_once "modals/contact_link_service_modal.php";
|
||||
require_once "modals/contact_link_document_modal.php";
|
||||
require_once "modals/contact_link_file_modal.php";
|
||||
|
||||
require_once "includes/footer.php";
|
||||
|
||||
24
contacts.php
24
contacts.php
@@ -110,7 +110,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
|
||||
|
||||
<?php
|
||||
@@ -137,7 +137,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
<?php if ($client_url) { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="location" onchange="this.form.submit()">
|
||||
<option value="">- All Locations -</option>
|
||||
|
||||
@@ -165,7 +165,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
|
||||
|
||||
@@ -319,7 +319,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
} else {
|
||||
$contact_phone_display = "<div><i class='fas fa-fw fa-phone mr-2'></i><a href='tel:$contact_phone'>$contact_phone$contact_extension_display</a></div>";
|
||||
}
|
||||
$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 = "";
|
||||
@@ -374,7 +374,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$sql_related_assets = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_contact_id = $contact_id ORDER BY asset_id DESC");
|
||||
$asset_count = mysqli_num_rows($sql_related_assets);
|
||||
if ($asset_count) {
|
||||
$asset_count_display = "<span class='mr-2 badge badge-pill badge-dark p-2' title='$asset_count Assets'><i class='fas fa-fw fa-desktop mr-2'></i>$asset_count</span>";
|
||||
$asset_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-dark p-2' title='$asset_count Assets'><i class='fas fa-fw fa-desktop mr-2'></i>$asset_count</span>";
|
||||
} else {
|
||||
$asset_count_display = '';
|
||||
}
|
||||
@@ -383,7 +383,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$sql_related_credentials = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_contact_id = $contact_id ORDER BY credential_id DESC");
|
||||
$credential_count = mysqli_num_rows($sql_related_credentials);
|
||||
if ($credential_count) {
|
||||
$credential_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$credential_count Credentials'><i class='fas fa-fw fa-key mr-2'></i>$credential_count</span>";
|
||||
$credential_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$credential_count Credentials'><i class='fas fa-fw fa-key mr-2'></i>$credential_count</span>";
|
||||
} else {
|
||||
$credential_count_display = '';
|
||||
}
|
||||
@@ -392,7 +392,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$sql_related_software = mysqli_query($mysqli, "SELECT * FROM software, software_contacts WHERE software.software_id = software_contacts.software_id AND software_contacts.contact_id = $contact_id");
|
||||
$software_count = mysqli_num_rows($sql_related_software);
|
||||
if ($software_count) {
|
||||
$software_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$software_count Licenses'><i class='fas fa-fw fa-cube mr-2'></i>$software_count</span>";
|
||||
$software_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$software_count Licenses'><i class='fas fa-fw fa-cube mr-2'></i>$software_count</span>";
|
||||
} else {
|
||||
$software_count_display = '';
|
||||
}
|
||||
@@ -401,7 +401,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_contact_id = $contact_id");
|
||||
$ticket_count = mysqli_num_rows($sql_related_tickets);
|
||||
if ($ticket_count) {
|
||||
$ticket_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$ticket_count Tickets'><i class='fas fa-fw fa-life-ring mr-2'></i>$ticket_count</span>";
|
||||
$ticket_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$ticket_count Tickets'><i class='fas fa-fw fa-life-ring mr-2'></i>$ticket_count</span>";
|
||||
} else {
|
||||
$ticket_count_display = '';
|
||||
}
|
||||
@@ -410,7 +410,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$sql_related_documents = mysqli_query($mysqli, "SELECT * FROM documents, contact_documents WHERE documents.document_id = contact_documents.document_id AND contact_documents.contact_id = $contact_id");
|
||||
$document_count = mysqli_num_rows($sql_related_documents);
|
||||
if ($document_count) {
|
||||
$document_count_display = "<span class='mr-2 badge badge-pill badge-secondary p-2' title='$document_count Documents'><i class='fas fa-fw fa-file-alt mr-2'></i>$document_count</span>";
|
||||
$document_count_display = "<span class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$document_count Documents'><i class='fas fa-fw fa-file-alt mr-2'></i>$document_count</span>";
|
||||
} else {
|
||||
$document_count_display = '';
|
||||
}
|
||||
@@ -445,11 +445,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-dark" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-modal-size="lg"
|
||||
data-ajax-url="ajax/ajax_contact_details.php?<?php echo $client_url; ?>"
|
||||
data-ajax-id="<?php echo $contact_id; ?>">
|
||||
<a class="text-dark" href="contact_details.php?client_id=<?php echo $client_id; ?>&contact_id=<?php echo $contact_id; ?>">
|
||||
<div class="media">
|
||||
<?php if ($contact_photo) { ?>
|
||||
<span class="fa-stack fa-2x mr-3 text-center">
|
||||
|
||||
@@ -124,7 +124,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
|
||||
|
||||
<?php
|
||||
@@ -151,7 +151,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
<?php if ($client_url) { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="location" onchange="this.form.submit()">
|
||||
<option value="">- All Asset Locations -</option>
|
||||
|
||||
@@ -171,7 +171,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
|
||||
|
||||
@@ -242,7 +242,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
@@ -335,7 +335,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$credential_tags_display = implode('', $credential_tag_name_display_array);
|
||||
|
||||
if ($credential_contact_id) {
|
||||
$credential_contact_display = "<a href='#' class='mr-2 badge badge-pill badge-dark p-2' title='$contact_name'
|
||||
$credential_contact_display = "<a href='#' class='mr-2 mb-1 badge badge-pill badge-dark p-2' title='$contact_name'
|
||||
data-toggle='ajax-modal'
|
||||
data-modal-size='lg'
|
||||
data-ajax-url='ajax/ajax_contact_details.php'
|
||||
@@ -346,7 +346,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
}
|
||||
|
||||
if ($credential_asset_id) {
|
||||
$credential_asset_display = "<a href='#' class='mr-2 badge badge-pill badge-secondary p-2' title='$asset_name' data-toggle='ajax-modal'
|
||||
$credential_asset_display = "<a href='#' class='mr-2 mb-1 badge badge-pill badge-secondary p-2' title='$asset_name' data-toggle='ajax-modal'
|
||||
data-modal-size='lg'
|
||||
data-ajax-url='ajax/ajax_asset_details.php'
|
||||
data-ajax-id='$credential_asset_id'>
|
||||
@@ -412,11 +412,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</a>
|
||||
</td>
|
||||
<td><?php echo $credential_username_display; ?></td>
|
||||
<td>
|
||||
<td class="text-nowrap"><?php echo $credential_username_display; ?></td>
|
||||
<td class="text-nowrap">
|
||||
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" type="button" data-clipboard-text="<?php echo $credential_password; ?>"><i class="far fa-copy text-secondary"></i></button>
|
||||
</td>
|
||||
<td><?php echo $otp_display; ?></td>
|
||||
<td class="text-nowrap"><?php echo $otp_display; ?></td>
|
||||
<td><?php echo $credential_uri_display; ?></td>
|
||||
<td>
|
||||
<?php echo "$credential_contact_display$credential_asset_display"; ?>
|
||||
|
||||
@@ -20,10 +20,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.grab-cursor {
|
||||
cursor: grab;
|
||||
.drag-handle {
|
||||
cursor: grab !important;
|
||||
}
|
||||
|
||||
.grab-cursor:active {
|
||||
cursor: grabbing;
|
||||
}
|
||||
.drag-handle:active {
|
||||
cursor: grabbing !important;
|
||||
}
|
||||
15
css/quote_dropdowns_fix.css
Normal file
15
css/quote_dropdowns_fix.css
Normal file
@@ -0,0 +1,15 @@
|
||||
/*!
|
||||
* AdminLTE 3.2.0 Specific Dropdown Fix
|
||||
* Targets .fix-quote-dropdown only
|
||||
* Prevents alignment bugs in split button dropdowns going too far left
|
||||
* (ChatGPT)
|
||||
*/
|
||||
|
||||
.fix-quote-dropdown .dropdown-menu {
|
||||
left: auto !important;
|
||||
right: 0 !important;
|
||||
top: calc(100% + 0.25rem) !important;
|
||||
transform: none !important;
|
||||
min-width: max-content;
|
||||
z-index: 1050;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ $sql_years_select = mysqli_query($mysqli, "
|
||||
<input type="hidden" name="enable_technical" value="0">
|
||||
|
||||
<label for="year" class="mr-sm-2">Select Year:</label>
|
||||
<select id="year" onchange="this.form.submit()" class="form-control mr-sm-3 col-sm-2" name="year">
|
||||
<select id="year" onchange="this.form.submit()" class="form-control mr-sm-3 col-sm-2 mb-3 mb-sm-0" name="year">
|
||||
<?php while ($row = mysqli_fetch_array($sql_years_select)) {
|
||||
$year_select = $row['all_years'];
|
||||
if (empty($year_select)) {
|
||||
@@ -55,7 +55,7 @@ $sql_years_select = mysqli_query($mysqli, "
|
||||
</select>
|
||||
|
||||
<?php if ($session_user_role == 1 || ($session_user_role == 3 && $config_module_enable_accounting == 1)) { ?>
|
||||
<div class="custom-control custom-switch mr-sm-3">
|
||||
<div class="custom-control custom-switch mr-3">
|
||||
<input type="checkbox" onchange="this.form.submit()" class="custom-control-input" id="customSwitch1" name="enable_financial" value="1" <?php if ($user_config_dashboard_financial_enable == 1) { echo "checked"; } ?>>
|
||||
<label class="custom-control-label" for="customSwitch1">Financial</label>
|
||||
</div>
|
||||
@@ -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']);
|
||||
}
|
||||
|
||||
|
||||
@@ -3424,10 +3424,52 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.2'");
|
||||
}
|
||||
|
||||
// if (CURRENT_DATABASE_VERSION == '2.1.2') {
|
||||
// // Insert queries here required to update to DB version 2.1.3
|
||||
if (CURRENT_DATABASE_VERSION == '2.1.2') {
|
||||
|
||||
// Update country_code to NULL for `contacts` table
|
||||
mysqli_query($mysqli, "ALTER TABLE `contacts` MODIFY `contact_phone_country_code` VARCHAR(10) DEFAULT NULL");
|
||||
mysqli_query($mysqli, "ALTER TABLE `contacts` MODIFY `contact_mobile_country_code` VARCHAR(10) DEFAULT NULL");
|
||||
|
||||
// Update country_code to NULL for `locations` table
|
||||
mysqli_query($mysqli, "ALTER TABLE `locations` MODIFY `location_phone_country_code` VARCHAR(10) DEFAULT NULL");
|
||||
mysqli_query($mysqli, "ALTER TABLE `locations` MODIFY `location_fax_country_code` VARCHAR(10) DEFAULT NULL");
|
||||
|
||||
// Update country_code to NULL for `vendors` table
|
||||
mysqli_query($mysqli, "ALTER TABLE `vendors` MODIFY `vendor_phone_country_code` VARCHAR(10) DEFAULT NULL");
|
||||
|
||||
// Update country_code to NULL for `companies` table
|
||||
mysqli_query($mysqli, "ALTER TABLE `companies` MODIFY `company_phone_country_code` VARCHAR(10) DEFAULT NULL");
|
||||
|
||||
// Set country_code to NULL for `contacts` table
|
||||
mysqli_query($mysqli, "UPDATE `contacts` SET `contact_phone_country_code` = NULL");
|
||||
mysqli_query($mysqli, "UPDATE `contacts` SET `contact_mobile_country_code` = NULL");
|
||||
|
||||
// Set country_code to NULL for `locations` table
|
||||
mysqli_query($mysqli, "UPDATE `locations` SET `location_phone_country_code` = NULL");
|
||||
mysqli_query($mysqli, "UPDATE `locations` SET `location_fax_country_code` = NULL");
|
||||
|
||||
// Set country_code to NULL for `vendors` table
|
||||
mysqli_query($mysqli, "UPDATE `vendors` SET `vendor_phone_country_code` = NULL");
|
||||
|
||||
// Set country_code to NULL for `companies` table
|
||||
mysqli_query($mysqli, "UPDATE `companies` SET `company_phone_country_code` = NULL");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.3'");
|
||||
}
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '2.1.3') {
|
||||
mysqli_query($mysqli, "ALTER TABLE `client_stripe` ADD `stripe_pm_details` VARCHAR(200) DEFAULT NULL AFTER `stripe_pm`");
|
||||
mysqli_query($mysqli, "ALTER TABLE `client_stripe` ADD `stripe_pm_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP AFTER `stripe_pm_details`");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.4'");
|
||||
}
|
||||
|
||||
|
||||
|
||||
// if (CURRENT_DATABASE_VERSION == '2.1.4') {
|
||||
// // Insert queries here required to update to DB version 2.1.5
|
||||
// // Then, update the database to the next sequential version
|
||||
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.3'");
|
||||
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.1.5'");
|
||||
// }
|
||||
|
||||
} else {
|
||||
|
||||
16
db.sql
16
db.sql
@@ -482,6 +482,8 @@ CREATE TABLE `client_stripe` (
|
||||
`client_id` int(11) NOT NULL,
|
||||
`stripe_id` varchar(255) NOT NULL,
|
||||
`stripe_pm` varchar(255) DEFAULT NULL,
|
||||
`stripe_pm_details` varchar(200) DEFAULT NULL,
|
||||
`stripe_pm_created_at` datetime NOT NULL DEFAULT current_timestamp(),
|
||||
PRIMARY KEY (`client_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -546,7 +548,7 @@ CREATE TABLE `companies` (
|
||||
`company_state` varchar(200) DEFAULT NULL,
|
||||
`company_zip` varchar(200) DEFAULT NULL,
|
||||
`company_country` varchar(200) DEFAULT NULL,
|
||||
`company_phone_country_code` varchar(10) DEFAULT '1',
|
||||
`company_phone_country_code` varchar(10) DEFAULT NULL,
|
||||
`company_phone` varchar(200) DEFAULT NULL,
|
||||
`company_email` varchar(200) DEFAULT NULL,
|
||||
`company_website` varchar(200) DEFAULT NULL,
|
||||
@@ -680,10 +682,10 @@ CREATE TABLE `contacts` (
|
||||
`contact_name` varchar(200) NOT NULL,
|
||||
`contact_title` varchar(200) DEFAULT NULL,
|
||||
`contact_email` varchar(200) DEFAULT NULL,
|
||||
`contact_phone_country_code` varchar(10) DEFAULT '1',
|
||||
`contact_phone_country_code` varchar(10) DEFAULT NULL,
|
||||
`contact_phone` varchar(200) DEFAULT NULL,
|
||||
`contact_extension` varchar(200) DEFAULT NULL,
|
||||
`contact_mobile_country_code` varchar(10) DEFAULT '1',
|
||||
`contact_mobile_country_code` varchar(10) DEFAULT NULL,
|
||||
`contact_mobile` varchar(200) DEFAULT NULL,
|
||||
`contact_photo` varchar(200) DEFAULT NULL,
|
||||
`contact_pin` varchar(255) DEFAULT NULL,
|
||||
@@ -1115,10 +1117,10 @@ CREATE TABLE `locations` (
|
||||
`location_city` varchar(200) DEFAULT NULL,
|
||||
`location_state` varchar(200) DEFAULT NULL,
|
||||
`location_zip` varchar(200) DEFAULT NULL,
|
||||
`location_phone_country_code` varchar(10) DEFAULT '1',
|
||||
`location_phone_country_code` varchar(10) DEFAULT NULL,
|
||||
`location_phone` varchar(200) DEFAULT NULL,
|
||||
`location_phone_extension` varchar(10) DEFAULT NULL,
|
||||
`location_fax_country_code` varchar(10) DEFAULT '1',
|
||||
`location_fax_country_code` varchar(10) DEFAULT NULL,
|
||||
`location_fax` varchar(200) DEFAULT NULL,
|
||||
`location_hours` varchar(200) DEFAULT NULL,
|
||||
`location_photo` varchar(200) DEFAULT NULL,
|
||||
@@ -2468,7 +2470,7 @@ CREATE TABLE `vendors` (
|
||||
`vendor_name` varchar(200) NOT NULL,
|
||||
`vendor_description` varchar(200) DEFAULT NULL,
|
||||
`vendor_contact_name` varchar(200) DEFAULT NULL,
|
||||
`vendor_phone_country_code` varchar(10) DEFAULT '1',
|
||||
`vendor_phone_country_code` varchar(10) DEFAULT NULL,
|
||||
`vendor_phone` varchar(200) DEFAULT NULL,
|
||||
`vendor_extension` varchar(200) DEFAULT NULL,
|
||||
`vendor_email` varchar(200) DEFAULT NULL,
|
||||
@@ -2498,4 +2500,4 @@ CREATE TABLE `vendors` (
|
||||
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
|
||||
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
|
||||
|
||||
-- Dump completed on 2025-03-26 11:13:46
|
||||
-- Dump completed on 2025-05-24 13:23:21
|
||||
|
||||
@@ -92,7 +92,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="col-md-2"></div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
|
||||
|
||||
@@ -162,7 +162,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
|
||||
<?php } ?>
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
|
||||
19
expenses.php
19
expenses.php
@@ -228,19 +228,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
Date <?php if ($sort == 'expense_date') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_name&order=<?php echo $disp; ?>">
|
||||
Vendor <?php if ($sort == 'vendor_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=category_name&order=<?php echo $disp; ?>">
|
||||
Category <?php if ($sort == 'category_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
/
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=expense_description&order=<?php echo $disp; ?>">
|
||||
Description <?php if ($sort == 'expense_description') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=expense_description&order=<?php echo $disp; ?>">
|
||||
Description <?php if ($sort == 'expense_description') { echo $order_icon; } ?>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_name&order=<?php echo $disp; ?>">
|
||||
Vendor <?php if ($sort == 'vendor_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-right">
|
||||
@@ -313,9 +312,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<?php echo $expense_date; ?>
|
||||
</a>
|
||||
</td>
|
||||
<td>
|
||||
<?php echo $category_name; ?>
|
||||
<div class="text-secondary"><small><?php echo truncate($expense_description, 60); ?></small></div>
|
||||
</td>
|
||||
<td><?php echo $vendor_name; ?></td>
|
||||
<td><?php echo $category_name; ?></td>
|
||||
<td><?php echo truncate($expense_description, 50); ?></td>
|
||||
<td class="text-bold text-right"><?php echo numfmt_format_currency($currency_format, $expense_amount, $expense_currency_code); ?></td>
|
||||
<td><?php echo $account_name; ?></td>
|
||||
<td><?php echo $client_name_display; ?></td>
|
||||
|
||||
124
functions.php
124
functions.php
@@ -194,140 +194,161 @@ function truncate($text, $chars) {
|
||||
}
|
||||
|
||||
function formatPhoneNumber($phoneNumber, $country_code = '', $show_country_code = false) {
|
||||
|
||||
// Remove all non-digit characters
|
||||
$digits = preg_replace('/\D/', '', $phoneNumber);
|
||||
$formatted = '';
|
||||
|
||||
// If no digits at all, fallback early
|
||||
if (strlen($digits) === 0) {
|
||||
return $phoneNumber;
|
||||
}
|
||||
|
||||
// Helper function to safely check the first digit
|
||||
$startsWith = function($str, $char) {
|
||||
return isset($str[0]) && $str[0] === $char;
|
||||
};
|
||||
|
||||
switch ($country_code) {
|
||||
case '1': // USA/Canada — (123) 456-7890
|
||||
case '1': // USA/Canada
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = '(' . substr($digits, 0, 3) . ') ' . substr($digits, 3, 3) . '-' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
case '44': // UK — 07123 456 789
|
||||
if ($digits[0] === '0') $digits = substr($digits, 1);
|
||||
case '44': // UK
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = '0' . substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '61': // Australia — 0412 345 678
|
||||
if ($digits[0] === '0') $digits = substr($digits, 1);
|
||||
case '61': // Australia
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = '0' . substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '91': // India — 91234 56789
|
||||
case '91': // India
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = substr($digits, 0, 5) . ' ' . substr($digits, 5);
|
||||
}
|
||||
break;
|
||||
|
||||
case '81': // Japan — 03-1234-5678
|
||||
if ($digits[0] === '0') $digits = substr($digits, 1);
|
||||
case '81': // Japan
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) >= 9 && strlen($digits) <= 10) {
|
||||
$formatted = '0' . substr($digits, 0, 2) . '-' . substr($digits, 2, 4) . '-' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
case '49': // Germany — 030 12345678
|
||||
if ($digits[0] === '0') $digits = substr($digits, 1);
|
||||
case '49': // Germany
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) >= 10) {
|
||||
$formatted = '0' . substr($digits, 0, 3) . ' ' . substr($digits, 3);
|
||||
}
|
||||
break;
|
||||
|
||||
case '33': // France — 01 23 45 67 89
|
||||
if ($digits[0] === '0') $digits = substr($digits, 1);
|
||||
case '33': // France
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = '0' . implode(' ', str_split($digits, 2));
|
||||
}
|
||||
break;
|
||||
|
||||
case '34': // Spain — 612 345 678
|
||||
case '34': // Spain
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
case '39': // Italy — 312 345 6789
|
||||
if ($digits[0] === '0') $digits = substr($digits, 1);
|
||||
case '39': // Italy
|
||||
if ($startsWith($digits, '0')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
$formatted = '0' . implode(' ', str_split($digits, 3));
|
||||
break;
|
||||
|
||||
case '55': // Brazil — (11) 91234-5678
|
||||
case '55': // Brazil
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = '(' . substr($digits, 0, 2) . ') ' . substr($digits, 2, 5) . '-' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '7': // Russia — 8 (912) 345-67-89
|
||||
if ($digits[0] === '8') $digits = substr($digits, 1);
|
||||
case '7': // Russia
|
||||
if ($startsWith($digits, '8')) {
|
||||
$digits = substr($digits, 1);
|
||||
}
|
||||
if (strlen($digits) === 10) {
|
||||
$formatted = '8 (' . substr($digits, 0, 3) . ') ' . substr($digits, 3, 3) . '-' . substr($digits, 6, 2) . '-' . substr($digits, 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case '86': // China — 138 0013 8000
|
||||
case '86': // China
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 4) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '82': // South Korea — 010-1234-5678
|
||||
case '82': // South Korea
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 3) . '-' . substr($digits, 3, 4) . '-' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '62': // Indonesia — 0812 3456 7890
|
||||
if ($digits[0] !== '0') $digits = '0' . $digits;
|
||||
case '62': // Indonesia
|
||||
if (!$startsWith($digits, '0')) {
|
||||
$digits = '0' . $digits;
|
||||
}
|
||||
if (strlen($digits) === 12) {
|
||||
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 4) . ' ' . substr($digits, 8);
|
||||
}
|
||||
break;
|
||||
|
||||
case '63': // Philippines — 0912 345 6789
|
||||
case '63': // Philippines
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '234': // Nigeria — 0801 234 5678
|
||||
if ($digits[0] !== '0') $digits = '0' . $digits;
|
||||
case '234': // Nigeria
|
||||
if (!$startsWith($digits, '0')) {
|
||||
$digits = '0' . $digits;
|
||||
}
|
||||
if (strlen($digits) === 11) {
|
||||
$formatted = substr($digits, 0, 4) . ' ' . substr($digits, 4, 3) . ' ' . substr($digits, 7);
|
||||
}
|
||||
break;
|
||||
|
||||
case '27': // South Africa — 082 123 4567
|
||||
case '27': // South Africa
|
||||
if (strlen($digits) >= 9 && strlen($digits) <= 10) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
case '971': // UAE — 050 123 4567
|
||||
case '971': // UAE
|
||||
if (strlen($digits) === 9) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// If no match, do nothing here and use fallback below
|
||||
// fallback — do nothing, use raw digits later
|
||||
break;
|
||||
}
|
||||
|
||||
// Fallback if formatting failed
|
||||
if (!$formatted && strlen($digits) >= 7) {
|
||||
$formatted = substr($digits, 0, 3) . ' ' . substr($digits, 3, 3) . ' ' . substr($digits, 6);
|
||||
}
|
||||
|
||||
// Still no formatting? Use raw digits
|
||||
if (!$formatted) {
|
||||
$formatted = $digits ?: $phoneNumber; // Use original input if digits are empty
|
||||
$formatted = $digits ?: $phoneNumber;
|
||||
}
|
||||
|
||||
return $show_country_code && $country_code ? "+$country_code $formatted" : $formatted;
|
||||
@@ -684,7 +705,17 @@ function sendSingleEmail($config_smtp_host, $config_smtp_username, $config_smtp_
|
||||
$mail->SMTPAuth = $smtp_auth; // Enable SMTP authentication
|
||||
$mail->Username = $config_smtp_username; // SMTP username
|
||||
$mail->Password = $config_smtp_password; // SMTP password
|
||||
$mail->SMTPSecure = $config_smtp_encryption; // Enable TLS encryption, `ssl` also accepted
|
||||
if ($config_smtp_encryption == 'None') {
|
||||
$mail->SMTPOptions = array(
|
||||
'ssl' => array(
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
));
|
||||
$mail->SMTPSecure = false;
|
||||
$mail->SMTPAutoTLS = false;
|
||||
} else {
|
||||
$mail->SMTPSecure = $config_smtp_encryption; // Enable TLS encryption, `ssl` also accepted
|
||||
}
|
||||
$mail->Port = $config_smtp_port; // TCP port to connect to
|
||||
|
||||
//Recipients
|
||||
@@ -1466,7 +1497,7 @@ function appNotify($type, $details, $action = null, $client_id = 0, $entity_id =
|
||||
$sql = mysqli_query($mysqli, "SELECT user_id FROM users
|
||||
WHERE user_type = 1 AND user_status = 1 AND user_archived_at IS NULL
|
||||
");
|
||||
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$user_id = intval($row['user_id']);
|
||||
|
||||
@@ -1514,7 +1545,7 @@ function getFallback($data) {
|
||||
* @param int $id The record's id.
|
||||
* @param string $field The field (column) to retrieve.
|
||||
* @param string $escape_method The escape method: 'sql' (default, auto-detects int), 'html', 'json', or 'int'.
|
||||
*
|
||||
*
|
||||
* @return mixed The escaped field value, or null if not found or invalid input.
|
||||
*/
|
||||
function getFieldById($table, $id, $field, $escape_method = 'sql') {
|
||||
@@ -1593,10 +1624,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']);
|
||||
@@ -1606,13 +1641,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 "<option value=\"$folder_id\" $selected>$indentation$folder_name</option>";
|
||||
|
||||
// Recursively display subfolders
|
||||
display_folder_options($folder_id, $client_id, $indent + 1);
|
||||
display_folder_options($folder_id, $client_id, $folder_location, $indent + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,7 +721,6 @@ if (isset($_GET['query'])) {
|
||||
} else {
|
||||
$asset_serial_display = $asset_serial;
|
||||
}
|
||||
$asset_mac = nullable_htmlentities($row['asset_mac']);
|
||||
$asset_uri = nullable_htmlentities($row['asset_uri']);
|
||||
$asset_status = nullable_htmlentities($row['asset_status']);
|
||||
$asset_created_at = nullable_htmlentities($row['asset_created_at']);
|
||||
@@ -746,9 +745,9 @@ if (isset($_GET['query'])) {
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-2"></i><?php echo $asset_name; ?>
|
||||
<i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-2"></i><a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>"><?php echo $asset_name; ?></a>
|
||||
<?php if(!empty($asset_uri)){ ?>
|
||||
<a href="<?php echo $asset_uri; ?>" target="_blank"><i class="fas fa-fw fa-external-link-alt ml-2"></i></a>
|
||||
<a href="<?php echo $asset_uri; ?>" target="_blank"><i class="fas fa-fw fa-external-link-alt ml-2"></i></a>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td><?php echo $asset_type; ?></td>
|
||||
|
||||
@@ -97,9 +97,7 @@ if (isset($_GET['stripe_create_pi'])) {
|
||||
'itflow_invoice_number' => $invoice_prefix . $invoice_number,
|
||||
'itflow_invoice_id' => $invoice_id,
|
||||
],
|
||||
'automatic_payment_methods' => [
|
||||
'enabled' => true,
|
||||
],
|
||||
'payment_method_types' => ['card'],
|
||||
]);
|
||||
|
||||
$output = [
|
||||
|
||||
@@ -97,71 +97,85 @@ if (isset($_GET['invoice_id'], $_GET['url_key']) && !isset($_GET['payment_intent
|
||||
|
||||
<!-- Show invoice details -->
|
||||
<div class="col-sm">
|
||||
<h3>Payment for Invoice: <?php echo $invoice_prefix . $invoice_number ?></h3>
|
||||
<br>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Product</th>
|
||||
<th class="text-center">Qty</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
$item_total = 0;
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_invoice_items)) {
|
||||
$item_name = nullable_htmlentities($row['item_name']);
|
||||
$item_quantity = floatval($row['item_quantity']);
|
||||
$item_total = floatval($row['item_total']);
|
||||
?>
|
||||
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Payment for Invoice: <strong><?php echo "$invoice_prefix$invoice_number"; ?></strong></h3>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><?php echo $item_name; ?></td>
|
||||
<td class="text-center"><?php echo $item_quantity; ?></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $item_total, $invoice_currency_code); ?></td>
|
||||
<th>Product</th>
|
||||
<th class="text-center">Qty</th>
|
||||
<th class="text-right">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
<?php } ?>
|
||||
$item_total = 0;
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_invoice_items)) {
|
||||
$item_name = nullable_htmlentities($row['item_name']);
|
||||
$item_quantity = floatval($row['item_quantity']);
|
||||
$item_total = floatval($row['item_total']);
|
||||
?>
|
||||
|
||||
<tr>
|
||||
<td><?php echo $item_name; ?></td>
|
||||
<td class="text-center"><?php echo $item_quantity; ?></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $item_total, $invoice_currency_code); ?></td>
|
||||
</tr>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
<?php } ?>
|
||||
<?php if ($invoice_discount > 0) { ?>
|
||||
<tr class="text-right">
|
||||
<td colspan="2">Discount</td>
|
||||
<td>
|
||||
<?php echo numfmt_format_currency($currency_format, $invoice_discount, $invoice_currency_code); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
<?php if (intval($amount_paid) > 0) { ?>
|
||||
<tr class="text-right">
|
||||
<td colspan="2">Paid</td>
|
||||
<td>
|
||||
<?php echo numfmt_format_currency($currency_format, $amount_paid, $invoice_currency_code); ?>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<i><?php if ($invoice_discount > 0){ echo "Discount: " . numfmt_format_currency($currency_format, $invoice_discount, $invoice_currency_code); } ?>
|
||||
</i>
|
||||
<br>
|
||||
<i><?php if (intval($amount_paid) > 0) { ?> Already paid: <?php echo numfmt_format_currency($currency_format, $amount_paid, $invoice_currency_code); } ?></i>
|
||||
</div>
|
||||
<!-- End invoice details-->
|
||||
|
||||
<!-- Show Stripe payment form -->
|
||||
<div class="col-sm offset-sm-1">
|
||||
<h1>Payment Total:</h1>
|
||||
<form id="payment-form">
|
||||
<h1><?php echo numfmt_format_currency($currency_format, $balance_to_pay, $invoice_currency_code); ?></h1>
|
||||
<input type="hidden" id="stripe_publishable_key" value="<?php echo $config_stripe_publishable ?>">
|
||||
<input type="hidden" id="invoice_id" value="<?php echo $invoice_id ?>">
|
||||
<input type="hidden" id="url_key" value="<?php echo $invoice_url_key ?>">
|
||||
<br>
|
||||
<div id="link-authentication-element">
|
||||
<!--Stripe.js injects the Link Authentication Element-->
|
||||
<div class="card">
|
||||
<div class="card-header">
|
||||
<h3 class="card-title">Payment Total: <strong><?php echo numfmt_format_currency($currency_format, $balance_to_pay, $invoice_currency_code); ?></strong></h3>
|
||||
</div>
|
||||
<div id="payment-element">
|
||||
<!--Stripe.js injects the Payment Element-->
|
||||
<div class="card-body">
|
||||
<form id="payment-form">
|
||||
<input type="hidden" id="stripe_publishable_key" value="<?php echo $config_stripe_publishable ?>">
|
||||
<input type="hidden" id="invoice_id" value="<?php echo $invoice_id ?>">
|
||||
<input type="hidden" id="url_key" value="<?php echo $invoice_url_key ?>">
|
||||
<div id="payment-element">
|
||||
<!--Stripe.js injects the Payment Element-->
|
||||
</div>
|
||||
<br>
|
||||
<button type="submit" id="submit" class="btn btn-primary btn-lg btn-block text-bold" hidden="hidden">
|
||||
<div class="spinner hidden" id="spinner"></div>
|
||||
<span id="button-text"><i class="fas fa-check mr-2"></i>Pay Invoice</span>
|
||||
</button>
|
||||
<div id="payment-message" class="hidden"></div>
|
||||
</form>
|
||||
</div>
|
||||
<br>
|
||||
<button type="submit" id="submit" class="btn btn-primary btn-lg btn-block text-bold" hidden="hidden">
|
||||
<div class="spinner hidden" id="spinner"></div>
|
||||
<span id="button-text"><i class="fas fa-check mr-2"></i>Pay Invoice</span>
|
||||
</button>
|
||||
<div id="payment-message" class="hidden"></div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<!-- End Stripe payment form -->
|
||||
|
||||
|
||||
@@ -50,6 +50,7 @@ $location_address = nullable_htmlentities($row['location_address']);
|
||||
$location_city = nullable_htmlentities($row['location_city']);
|
||||
$location_state = nullable_htmlentities($row['location_state']);
|
||||
$location_zip = nullable_htmlentities($row['location_zip']);
|
||||
$location_country = nullable_htmlentities($row['location_country']);
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
|
||||
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
|
||||
@@ -71,6 +72,7 @@ $company_address = nullable_htmlentities($row['company_address']);
|
||||
$company_city = nullable_htmlentities($row['company_city']);
|
||||
$company_state = nullable_htmlentities($row['company_state']);
|
||||
$company_zip = nullable_htmlentities($row['company_zip']);
|
||||
$company_country = nullable_htmlentities($row['company_country']);
|
||||
$company_phone_country_code = nullable_htmlentities($row['company_phone_country_code']);
|
||||
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
|
||||
$company_email = nullable_htmlentities($row['company_email']);
|
||||
@@ -198,6 +200,7 @@ if ($balance > 0) {
|
||||
<li><h4><strong><?php echo $company_name; ?></strong></h4></li>
|
||||
<li><?php echo $company_address; ?></li>
|
||||
<li><?php echo "$company_city $company_state $company_zip"; ?></li>
|
||||
<li><small><?php echo $company_country; ?></small></li>
|
||||
<li><?php echo $company_phone; ?></li>
|
||||
<li><?php echo $company_email; ?></li>
|
||||
</ul>
|
||||
@@ -209,6 +212,7 @@ if ($balance > 0) {
|
||||
<li><h4><strong><?php echo $client_name; ?></strong></h4></li>
|
||||
<li><?php echo $location_address; ?></li>
|
||||
<li><?php echo "$location_city $location_state $location_zip"; ?></li>
|
||||
<li><small><?php echo $location_country; ?></small></li>
|
||||
<li><?php echo "$contact_phone $contact_extension"; ?></li>
|
||||
<li><?php echo $contact_mobile; ?></li>
|
||||
<li><?php echo $contact_email; ?></li>
|
||||
@@ -407,11 +411,11 @@ if ($balance > 0) {
|
||||
{
|
||||
columns: [
|
||||
{
|
||||
text: <?php echo json_encode(html_entity_decode("$company_address \n $company_city $company_state $company_zip \n $company_phone \n $company_website")) ?>,
|
||||
text: <?php echo json_encode(html_entity_decode("$company_address \n $company_city $company_state $company_zip \n $company_country \n $company_phone \n $company_website")) ?>,
|
||||
style: 'invoiceBillingAddress'
|
||||
},
|
||||
{
|
||||
text: <?php echo json_encode(html_entity_decode("$location_address \n $location_city $location_state $location_zip \n $contact_email \n $contact_phone")) ?>,
|
||||
text: <?php echo json_encode(html_entity_decode("$location_address \n $location_city $location_state $location_zip \n $location_country \n $contact_email \n $contact_phone")) ?>,
|
||||
style: 'invoiceBillingAddressClient'
|
||||
},
|
||||
]
|
||||
|
||||
@@ -51,6 +51,7 @@ $location_address = nullable_htmlentities($row['location_address']);
|
||||
$location_city = nullable_htmlentities($row['location_city']);
|
||||
$location_state = nullable_htmlentities($row['location_state']);
|
||||
$location_zip = nullable_htmlentities($row['location_zip']);
|
||||
$location_country = nullable_htmlentities($row['location_country']);
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
|
||||
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
|
||||
@@ -71,6 +72,7 @@ $company_address = nullable_htmlentities($row['company_address']);
|
||||
$company_city = nullable_htmlentities($row['company_city']);
|
||||
$company_state = nullable_htmlentities($row['company_state']);
|
||||
$company_zip = nullable_htmlentities($row['company_zip']);
|
||||
$company_country = nullable_htmlentities($row['company_country']);
|
||||
$company_phone_country_code = nullable_htmlentities($row['company_phone_country_code']);
|
||||
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
|
||||
$company_email = nullable_htmlentities($row['company_email']);
|
||||
@@ -136,6 +138,7 @@ if ($quote_status == "Draft" || $quote_status == "Sent" || $quote_status == "Vie
|
||||
<li><h4><strong><?php echo $company_name; ?></strong></h4></li>
|
||||
<li><?php echo $company_address; ?></li>
|
||||
<li><?php echo "$company_city $company_state $company_zip"; ?></li>
|
||||
<li><small><?php echo $company_country; ?></small></li>
|
||||
<li><?php echo $company_phone; ?></li>
|
||||
<li><?php echo $company_email; ?></li>
|
||||
</ul>
|
||||
@@ -148,6 +151,7 @@ if ($quote_status == "Draft" || $quote_status == "Sent" || $quote_status == "Vie
|
||||
<li><h4><strong><?php echo $client_name; ?></strong></h4></li>
|
||||
<li><?php echo $location_address; ?></li>
|
||||
<li><?php echo "$location_city $location_state $location_zip"; ?></li>
|
||||
<li><small><?php echo $location_country; ?></small></li>
|
||||
<li><?php echo "$contact_phone $contact_extension"; ?></li>
|
||||
<li><?php echo $contact_mobile; ?></li>
|
||||
<li><?php echo $contact_email; ?></li>
|
||||
@@ -345,11 +349,11 @@ if ($quote_status == "Draft" || $quote_status == "Sent" || $quote_status == "Vie
|
||||
{
|
||||
columns: [
|
||||
{
|
||||
text: <?php echo json_encode(html_entity_decode("$company_address \n $company_city $company_state $company_zip \n $company_phone \n $company_website")) ?>,
|
||||
text: <?php echo json_encode(html_entity_decode("$company_address \n $company_city $company_state $company_zip \n $company_country \n $company_phone \n $company_website")) ?>,
|
||||
style: 'invoiceBillingAddress'
|
||||
},
|
||||
{
|
||||
text: <?php echo json_encode(html_entity_decode("$location_address \n $location_city $location_state $location_zip \n $contact_email \n $contact_phone")) ?>,
|
||||
text: <?php echo json_encode(html_entity_decode("$location_address \n $location_city $location_state $location_zip \n $location_country \n $contact_email \n $contact_phone")) ?>,
|
||||
style: 'invoiceBillingAddressClient'
|
||||
},
|
||||
]
|
||||
|
||||
@@ -145,7 +145,7 @@
|
||||
</li>
|
||||
|
||||
<!-- SETTINGS Section -->
|
||||
<li class="nav-item has-treeview mt-2 <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['admin_settings_company.php', 'admin_settings_localization.php', 'admin_settings_theme.php', 'admin_settings_security.php', 'admin_settings_mail.php', 'admin_settings_notification.php', 'admin_settings_default.php', 'admin_settings_invoice.php', 'admin_settings_quote.php', 'admin_settings_online_payment.php', 'admin_settings_online_payment_clients.php', 'admin_settings_project.php', 'admin_settings_ticket.php', 'admin_settings_ai.php', 'admin_settings_integration.php', 'admin_settings_telemetry.php', 'admin_settings_module.php']) ? 'menu-open' : ''); ?>">
|
||||
<li class="nav-item has-treeview mt-2 <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['admin_settings_company.php', 'admin_settings_localization.php', 'admin_settings_theme.php', 'admin_settings_security.php', 'admin_settings_mail.php', 'admin_settings_notification.php', 'admin_settings_default.php', 'admin_settings_invoice.php', 'admin_settings_quote.php', 'admin_settings_online_payment.php', 'admin_settings_online_payment_clients.php', 'admin_settings_project.php', 'admin_settings_ticket.php', 'admin_settings_ai.php', 'admin_identity_provider.php', 'admin_settings_telemetry.php', 'admin_settings_module.php']) ? 'menu-open' : ''); ?>">
|
||||
<a href="#" class="nav-link">
|
||||
<p>
|
||||
SETTINGS
|
||||
@@ -246,9 +246,9 @@
|
||||
<!-- Currently the only integration is the client portal SSO -->
|
||||
<?php if ($config_client_portal_enable) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="admin_settings_integration.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_integration.php' ? 'active' : ''); ?>">
|
||||
<i class="nav-icon fas fa-plug"></i>
|
||||
<p>Integrations</p>
|
||||
<a href="admin_identity_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_identity_provider.php' ? 'active' : ''); ?>">
|
||||
<i class="nav-icon fas fa-fingerprint"></i>
|
||||
<p>Identity Provider</p>
|
||||
</a>
|
||||
</li>
|
||||
<?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");
|
||||
DEFINE("APP_VERSION", "25.05");
|
||||
|
||||
@@ -153,18 +153,20 @@
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="credentials.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "credentials.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-key"></i>
|
||||
<p>
|
||||
Credentials
|
||||
<?php
|
||||
if ($num_credentials > 0) { ?>
|
||||
<span class="right badge text-light"><?php echo $num_credentials; ?></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<?php if (lookupUserPermission("module_credential") >= 1) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="credentials.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "credentials.php") { echo "active"; } ?>">
|
||||
<i class="nav-icon fas fa-key"></i>
|
||||
<p>
|
||||
Credentials
|
||||
<?php
|
||||
if ($num_credentials > 0) { ?>
|
||||
<span class="right badge text-light"><?php echo $num_credentials; ?></span>
|
||||
<?php } ?>
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
<?php } ?>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="networks.php?client_id=<?php echo $client_id; ?>" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "networks.php") { echo "active"; } ?>">
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
* It is used in conjunction with database_updates.php
|
||||
*/
|
||||
|
||||
DEFINE("LATEST_DATABASE_VERSION", "2.1.2");
|
||||
DEFINE("LATEST_DATABASE_VERSION", "2.1.4");
|
||||
|
||||
@@ -26,7 +26,6 @@ if ($total_found_rows > 5) {
|
||||
<option <?php if ($user_config_records_per_page == 20) { echo "selected"; } ?> >20</option>
|
||||
<option <?php if ($user_config_records_per_page == 50) { echo "selected"; } ?> >50</option>
|
||||
<option <?php if ($user_config_records_per_page == 100) { echo "selected"; } ?> >100</option>
|
||||
<option <?php if ($user_config_records_per_page == 500) { echo "selected"; } ?> >500</option>
|
||||
</select>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
@@ -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 = '2035-12-31';
|
||||
}
|
||||
|
||||
// Archived
|
||||
|
||||
@@ -121,6 +121,8 @@ $config_log_retention = intval($row['config_log_retention']);
|
||||
// Locale
|
||||
$config_currency_format = "US_en";
|
||||
$config_timezone = $row['config_timezone'];
|
||||
$config_date_format = "Y-m-d";
|
||||
$config_time_format = "H:i";
|
||||
|
||||
// Theme
|
||||
$config_theme = $row['config_theme'];
|
||||
|
||||
@@ -59,7 +59,12 @@
|
||||
<div>
|
||||
<a href="//maps.<?php echo $session_map_source; ?>.com/?q=<?php echo "$location_address $location_zip"; ?>" target="_blank">
|
||||
<i class="fa fa-fw fa-map-marker-alt text-secondary ml-1 mr-2"></i><?php echo $location_address; ?>
|
||||
<div><i class="fa fa-fw ml-1 mr-2"></i><?php echo "$location_city $location_state $location_zip"; ?></div>
|
||||
<div>
|
||||
<i class="fa fa-fw ml-1 mr-2"></i><?php echo "$location_city $location_state $location_zip"; ?>
|
||||
</div>
|
||||
<div>
|
||||
<i class="fa fa-fw ml-1 mr-2"></i><small><?php echo $location_country; ?></small>
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
<?php }
|
||||
|
||||
@@ -28,37 +28,33 @@
|
||||
<!-- Right navbar links -->
|
||||
<ul class="navbar-nav ml-auto">
|
||||
|
||||
<?php if(CURRENT_DATABASE_VERSION > '1.4.5' ) { // Check DB Version REMOVE on Decemeber 1st 2024 -Johnny ?>
|
||||
<!--Custom Nav Link -->
|
||||
<?php
|
||||
$sql_custom_links = mysqli_query($mysqli, "SELECT * FROM custom_links WHERE custom_link_location = 2 AND custom_link_archived_at IS NULL
|
||||
ORDER BY custom_link_order ASC, custom_link_name ASC"
|
||||
);
|
||||
|
||||
<!--Custom Nav Link -->
|
||||
<?php
|
||||
$sql_custom_links = mysqli_query($mysqli, "SELECT * FROM custom_links WHERE custom_link_location = 2 AND custom_link_archived_at IS NULL
|
||||
ORDER BY custom_link_order ASC, custom_link_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_custom_links)) {
|
||||
$custom_link_name = nullable_htmlentities($row['custom_link_name']);
|
||||
$custom_link_uri = nullable_htmlentities($row['custom_link_uri']);
|
||||
$custom_link_icon = nullable_htmlentities($row['custom_link_icon']);
|
||||
$custom_link_new_tab = intval($row['custom_link_new_tab']);
|
||||
if ($custom_link_new_tab == 1) {
|
||||
$target = "target='_blank' rel='noopener noreferrer'";
|
||||
} else {
|
||||
$target = "";
|
||||
}
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_custom_links)) {
|
||||
$custom_link_name = nullable_htmlentities($row['custom_link_name']);
|
||||
$custom_link_uri = nullable_htmlentities($row['custom_link_uri']);
|
||||
$custom_link_icon = nullable_htmlentities($row['custom_link_icon']);
|
||||
$custom_link_new_tab = intval($row['custom_link_new_tab']);
|
||||
if ($custom_link_new_tab == 1) {
|
||||
$target = "target='_blank' rel='noopener noreferrer'";
|
||||
} else {
|
||||
$target = "";
|
||||
}
|
||||
?>
|
||||
|
||||
?>
|
||||
<li class="nav-item" title="<?php echo $custom_link_name; ?>">
|
||||
<a href="<?php echo $custom_link_uri; ?>" <?php echo $target; ?> class="nav-link">
|
||||
<i class="fas fa-<?php echo $custom_link_icon; ?> nav-icon"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<li class="nav-item" title="<?php echo $custom_link_name; ?>">
|
||||
<a href="<?php echo $custom_link_uri; ?>" <?php echo $target; ?> class="nav-link">
|
||||
<i class="fas fa-<?php echo $custom_link_icon; ?> nav-icon"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
<!-- End Custom Nav Links -->
|
||||
|
||||
<?php } // End DB Check ?>
|
||||
<?php } ?>
|
||||
<!-- End Custom Nav Links -->
|
||||
|
||||
<!-- New Notifications Dropdown -->
|
||||
<?php
|
||||
|
||||
@@ -14,7 +14,11 @@ if (file_exists("config.php")) {
|
||||
<!-- Page Content -->
|
||||
<h1>Blank Page</h1>
|
||||
<hr>
|
||||
<?php
|
||||
<?php
|
||||
|
||||
if (isset($config_start_page)) { ?>
|
||||
<meta http-equiv="refresh" content="0;url=<?php echo $config_start_page; ?>">
|
||||
<?php }
|
||||
|
||||
require_once "includes/footer.php";
|
||||
|
||||
|
||||
124
invoice.php
124
invoice.php
@@ -53,6 +53,7 @@ if (isset($_GET['invoice_id'])) {
|
||||
$location_city = nullable_htmlentities($row['location_city']);
|
||||
$location_state = nullable_htmlentities($row['location_state']);
|
||||
$location_zip = nullable_htmlentities($row['location_zip']);
|
||||
$location_country = nullable_htmlentities($row['location_country']);
|
||||
$contact_email = nullable_htmlentities($row['contact_email']);
|
||||
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
|
||||
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
|
||||
@@ -165,7 +166,6 @@ if (isset($_GET['invoice_id'])) {
|
||||
|
||||
|
||||
?>
|
||||
<link rel="stylesheet" href="plugins/dragula/dragula.min.css">
|
||||
|
||||
<ol class="breadcrumb d-print-none">
|
||||
<?php if (isset($_GET['client_id'])) { ?>
|
||||
@@ -193,25 +193,26 @@ if (isset($_GET['invoice_id'])) {
|
||||
|
||||
<div class="card-header d-print-none">
|
||||
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-8">
|
||||
<?php if (lookupUserPermission("module_sales") >= 2) { ?>
|
||||
<?php if ($invoice_status == 'Draft') { ?>
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if (!empty($config_smtp_host) && !empty($contact_email)) { ?>
|
||||
<a class="dropdown-item" href="post.php?email_invoice=<?php echo $invoice_id; ?>">
|
||||
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send Email
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<?php } ?>
|
||||
<a class="dropdown-item" href="post.php?mark_invoice_sent=<?php echo $invoice_id; ?>">
|
||||
<i class="fas fa-fw fa-check mr-2"></i>Mark Sent
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if (!empty($config_smtp_host) && !empty($contact_email)) { ?>
|
||||
<a class="dropdown-item" href="post.php?email_invoice=<?php echo $invoice_id; ?>">
|
||||
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send Email
|
||||
</a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<?php } ?>
|
||||
<a class="dropdown-item" href="post.php?mark_invoice_sent=<?php echo $invoice_id; ?>">
|
||||
<i class="fas fa-fw fa-check mr-2"></i>Mark Sent
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<?php if ($invoice_status !== 'Paid' && $invoice_status !== 'Cancelled' && $invoice_status !== 'Draft' && $invoice_amount != 0) { ?>
|
||||
<a class="btn btn-success" href="#" data-toggle="modal" data-target="#addPaymentModal">
|
||||
@@ -229,7 +230,7 @@ if (isset($_GET['invoice_id'])) {
|
||||
Mark Non-Billable
|
||||
</a>
|
||||
<?php } ?>
|
||||
|
||||
<?php } // End lookup Perm ?>
|
||||
</div>
|
||||
|
||||
<div class="col-4">
|
||||
@@ -283,6 +284,7 @@ if (isset($_GET['invoice_id'])) {
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -308,6 +310,7 @@ if (isset($_GET['invoice_id'])) {
|
||||
<li><h4><strong><?php echo $company_name; ?></strong></h4></li>
|
||||
<li><?php echo $company_address; ?></li>
|
||||
<li><?php echo "$company_city $company_state $company_zip"; ?></li>
|
||||
<li><small><?php echo $company_country; ?></small></li>
|
||||
<li><?php echo $company_phone; ?></li>
|
||||
<li><?php echo $company_email; ?></li>
|
||||
<li><?php echo $company_website; ?></li>
|
||||
@@ -318,6 +321,7 @@ if (isset($_GET['invoice_id'])) {
|
||||
<li><h4><strong><?php echo $client_name; ?></strong></h4></li>
|
||||
<li><?php echo $location_address; ?></li>
|
||||
<li><?php echo "$location_city $location_state $location_zip"; ?></li>
|
||||
<li><small><?php echo $location_country; ?></small></li>
|
||||
<li><?php echo "$contact_phone $contact_extension"; ?></li>
|
||||
<li><?php echo $contact_mobile; ?></li>
|
||||
<li><?php echo $contact_email; ?></li>
|
||||
@@ -381,26 +385,33 @@ if (isset($_GET['invoice_id'])) {
|
||||
<tr data-item-id="<?php echo $item_id; ?>">
|
||||
<td class="d-print-none">
|
||||
<?php if ($invoice_status !== "Paid" && $invoice_status !== "Cancelled") { ?>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-light" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-v"></i>
|
||||
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-sm btn-link drag-handle">
|
||||
<i class="fas fa-bars text-muted"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_item_edit.php"
|
||||
data-ajax-id="<?php echo $item_id; ?>"
|
||||
>
|
||||
<i class="fa 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_invoice_item=<?php echo $item_id; ?>"><i class="fa fa-fw fa-trash mr-2"></i>Delete</a>
|
||||
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-sm btn-light" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-v"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#"
|
||||
data-toggle="ajax-modal"
|
||||
data-ajax-url="ajax/ajax_item_edit.php"
|
||||
data-ajax-id="<?php echo $item_id; ?>"
|
||||
>
|
||||
<i class="fa 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_invoice_item=<?php echo $item_id; ?>"><i class="fa fa-fw fa-trash mr-2"></i>Delete</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<?php } ?>
|
||||
</td>
|
||||
<td class="grab-cursor"><?php echo $item_name; ?></td>
|
||||
<td><?php echo $item_name; ?></td>
|
||||
<td><?php echo nl2br($item_description); ?></td>
|
||||
<td class="text-center"><?php echo number_format($item_quantity, 2); ?></td>
|
||||
<td class="text-right"><?php echo numfmt_format_currency($currency_format, $item_price, $invoice_currency_code); ?></td>
|
||||
@@ -410,7 +421,7 @@ if (isset($_GET['invoice_id'])) {
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
<tr class="d-print-none" <?php if ($invoice_status == "Paid" || $invoice_status == "Cancelled") { echo "hidden"; } ?>>
|
||||
<tr class="d-print-none" <?php if ($invoice_status == "Paid" || $invoice_status == "Cancelled" || lookupUserPermission("module_sales") <= 1) { echo "hidden"; } ?>>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="invoice_id" value="<?php echo $invoice_id; ?>">
|
||||
<input type="hidden" name="item_order" value="<?php echo mysqli_num_rows($sql_invoice_items) + 1; ?>">
|
||||
@@ -772,11 +783,11 @@ require_once "includes/footer.php";
|
||||
{
|
||||
columns: [
|
||||
{
|
||||
text: <?php echo json_encode(html_entity_decode("$company_address \n $company_city $company_state $company_zip \n $company_phone \n $company_website")) ?>,
|
||||
text: <?php echo json_encode(html_entity_decode("$company_address \n $company_city $company_state $company_zip \n $company_country \n $company_phone \n $company_website")) ?>,
|
||||
style: 'invoiceBillingAddress'
|
||||
},
|
||||
{
|
||||
text: <?php echo json_encode(html_entity_decode("$location_address \n $location_city $location_state $location_zip \n $contact_email \n $contact_phone")) ?>,
|
||||
text: <?php echo json_encode(html_entity_decode("$location_address \n $location_city $location_state $location_zip \n $location_country \n $contact_email \n $contact_phone")) ?>,
|
||||
style: 'invoiceBillingAddressClient'
|
||||
},
|
||||
]
|
||||
@@ -1178,38 +1189,23 @@ require_once "includes/footer.php";
|
||||
}
|
||||
</script>
|
||||
|
||||
<script src="plugins/dragula/dragula.min.js"></script>
|
||||
<script src="plugins/SortableJS/Sortable.min.js"></script>
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
var container = $('table#items tbody')[0];
|
||||
new Sortable(document.querySelector('table#items tbody'), {
|
||||
handle: '.drag-handle',
|
||||
animation: 150,
|
||||
onEnd: function (evt) {
|
||||
const rows = document.querySelectorAll('table#items tbody tr');
|
||||
const positions = Array.from(rows).map((row, index) => ({
|
||||
id: row.dataset.itemId,
|
||||
order: index
|
||||
}));
|
||||
|
||||
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('itemId'),
|
||||
order: index
|
||||
};
|
||||
}).get();
|
||||
|
||||
// Send the new order to the server
|
||||
$.ajax({
|
||||
url: 'ajax.php',
|
||||
method: 'POST',
|
||||
data: {
|
||||
update_invoice_items_order: true,
|
||||
invoice_id: <?php echo $invoice_id; ?>,
|
||||
positions: positions
|
||||
},
|
||||
success: function(data) {
|
||||
// Handle success
|
||||
},
|
||||
error: function(error) {
|
||||
console.error('Error updating order:', error);
|
||||
}
|
||||
});
|
||||
$.post('ajax.php', {
|
||||
update_invoice_items_order: true,
|
||||
invoice_id: <?php echo $invoice_id; ?>,
|
||||
positions: positions
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -172,7 +172,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<?php } ?>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {echo stripslashes(nullable_htmlentities($q));} ?>" placeholder="Search Invoices">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
|
||||
@@ -228,7 +228,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=invoice_number&order=<?php echo $disp ?>">
|
||||
|
||||
@@ -23,9 +23,6 @@ async function initialize() {
|
||||
|
||||
elements = stripe.elements({ clientSecret });
|
||||
|
||||
const linkAuthenticationElement = elements.create("linkAuthentication");
|
||||
linkAuthenticationElement.mount("#link-authentication-element");
|
||||
|
||||
const paymentElementOptions = {
|
||||
layout: "tabs",
|
||||
};
|
||||
|
||||
@@ -1,146 +1,126 @@
|
||||
$(document).ready(function() {
|
||||
console.log('CONFIG_TICKET_MOVING_COLUMNS: ' + CONFIG_TICKET_MOVING_COLUMNS);
|
||||
console.log('CONFIG_TICKET_ORDERING: ' + CONFIG_TICKET_ORDERING);
|
||||
$(document).ready(function () {
|
||||
console.log('CONFIG_TICKET_MOVING_COLUMNS:', CONFIG_TICKET_MOVING_COLUMNS);
|
||||
console.log('CONFIG_TICKET_ORDERING:', CONFIG_TICKET_ORDERING);
|
||||
|
||||
// Function to detect touch devices
|
||||
function isTouchDevice() {
|
||||
return 'ontouchstart' in window || navigator.maxTouchPoints;
|
||||
}
|
||||
|
||||
// Initialize Dragula for the Kanban board
|
||||
let boardDrake = dragula([
|
||||
document.querySelector('#kanban-board')
|
||||
], {
|
||||
moves: function(el, container, handle) {
|
||||
return handle.classList.contains('panel-title');
|
||||
},
|
||||
accepts: function(el, target, source, sibling) {
|
||||
return CONFIG_TICKET_MOVING_COLUMNS === 1;
|
||||
}
|
||||
});
|
||||
|
||||
// Log the event of moving the column panel-title
|
||||
boardDrake.on('drag', function(el) {
|
||||
//console.log('Dragging column:', el.querySelector('.panel-title').innerText);
|
||||
});
|
||||
|
||||
boardDrake.on('drop', function(el, target, source, sibling) {
|
||||
//console.log('Dropped column:', el.querySelector('.panel-title').innerText);
|
||||
|
||||
// Get all columns and their positions
|
||||
let columns = document.querySelectorAll('#kanban-board .kanban-column');
|
||||
let columnPositions = [];
|
||||
|
||||
columns.forEach(function(column, index) {
|
||||
let statusId = $(column).data('status-id'); // Assuming you have a data attribute for status ID
|
||||
columnPositions.push({
|
||||
status_id: statusId,
|
||||
// -------------------------------
|
||||
// Drag: Kanban Columns (Statuses)
|
||||
// -------------------------------
|
||||
new Sortable(document.querySelector('#kanban-board'), {
|
||||
animation: 150,
|
||||
handle: '.panel-title',
|
||||
draggable: '.kanban-column',
|
||||
onEnd: function () {
|
||||
const columnPositions = Array.from(document.querySelectorAll('#kanban-board .kanban-column')).map((col, index) => ({
|
||||
status_id: $(col).data('status-id'),
|
||||
status_kanban: index
|
||||
});
|
||||
});
|
||||
}));
|
||||
|
||||
// Send AJAX request to update all column positions
|
||||
$.ajax({
|
||||
url: 'ajax.php',
|
||||
type: 'POST',
|
||||
data: {
|
||||
update_kanban_status_position: true,
|
||||
positions: columnPositions
|
||||
},
|
||||
success: function(response) {
|
||||
console.log('Ticket status kanban orders updated successfully.');
|
||||
// Optionally, you can refresh the page or update the UI here
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error updating ticket status kanban orders:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Initialize Dragula for the Kanban Cards
|
||||
let drake = dragula([
|
||||
...document.querySelectorAll('#status')
|
||||
], {
|
||||
moves: function(el, container, handle) {
|
||||
if (isTouchDevice()) {
|
||||
return handle.classList.contains('drag-handle-class');
|
||||
} else {
|
||||
return true; // Allow dragging on the entire task element for desktop
|
||||
if (CONFIG_TICKET_MOVING_COLUMNS === 1) {
|
||||
$.post('ajax.php', {
|
||||
update_kanban_status_position: true,
|
||||
positions: columnPositions
|
||||
}).done(() => {
|
||||
console.log('Ticket status kanban orders updated.');
|
||||
}).fail((xhr) => {
|
||||
console.error('Error updating status order:', xhr.responseText);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// -------------------------------
|
||||
// Drag: Tasks within Columns
|
||||
// -------------------------------
|
||||
document.querySelectorAll('.kanban-status').forEach(statusCol => {
|
||||
new Sortable(statusCol, {
|
||||
group: 'tickets',
|
||||
animation: 150,
|
||||
handle: isTouchDevice() ? '.drag-handle-class' : undefined,
|
||||
onStart: () => hidePlaceholders(),
|
||||
onEnd: function (evt) {
|
||||
const target = evt.to;
|
||||
const movedEl = evt.item;
|
||||
|
||||
// Disallow reordering in same column if config says so
|
||||
if (CONFIG_TICKET_ORDERING === 0 && evt.from === evt.to) {
|
||||
evt.from.insertBefore(movedEl, evt.from.children[evt.oldIndex]);
|
||||
showPlaceholders();
|
||||
return;
|
||||
}
|
||||
|
||||
const columnId = $(target).data('status-id');
|
||||
|
||||
const positions = Array.from(target.querySelectorAll('.task')).map((card, index) => {
|
||||
const ticketId = $(card).data('ticket-id');
|
||||
const oldStatus = ticketId === $(movedEl).data('ticket-id')
|
||||
? $(movedEl).data('ticket-status-id')
|
||||
: false;
|
||||
|
||||
$(card).data('ticket-status-id', columnId); // update DOM
|
||||
|
||||
return {
|
||||
ticket_id: ticketId,
|
||||
ticket_order: index,
|
||||
ticket_oldStatus: oldStatus,
|
||||
ticket_status: columnId
|
||||
};
|
||||
});
|
||||
|
||||
$.post('ajax.php', {
|
||||
update_kanban_ticket: true,
|
||||
positions: positions
|
||||
}).done(() => {
|
||||
console.log('Updated kanban ticket positions.');
|
||||
}).fail((xhr) => {
|
||||
console.error('Error updating ticket positions:', xhr.responseText);
|
||||
});
|
||||
|
||||
// Refresh placeholders after update
|
||||
showPlaceholders();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// -------------------------------
|
||||
// 📱 Touch Support: Show drag handle on mobile
|
||||
// -------------------------------
|
||||
if (isTouchDevice()) {
|
||||
const moveList = document.querySelectorAll('.task');
|
||||
moveList.forEach(task => {
|
||||
task.querySelector('.drag-handle-class').style.display = 'inline';
|
||||
$('.drag-handle-class').css('display', 'inline');
|
||||
}
|
||||
|
||||
// -------------------------------
|
||||
// Placeholder Management
|
||||
// -------------------------------
|
||||
function showPlaceholders() {
|
||||
document.querySelectorAll('.kanban-status').forEach(status => {
|
||||
const placeholderClass = 'empty-placeholder';
|
||||
|
||||
// Remove existing placeholder
|
||||
const existing = status.querySelector(`.${placeholderClass}`);
|
||||
if (existing) existing.remove();
|
||||
|
||||
// Only show if there are no tasks
|
||||
if (status.querySelectorAll('.task').length === 0) {
|
||||
const placeholder = document.createElement('div');
|
||||
placeholder.className = `${placeholderClass} text-muted text-center p-2`;
|
||||
placeholder.innerText = 'Drop ticket here';
|
||||
placeholder.style.pointerEvents = 'none';
|
||||
status.appendChild(placeholder);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
drake.on('drag', function(el) {
|
||||
el.style.cursor = 'grabbing';
|
||||
});
|
||||
|
||||
drake.on('dragend', function(el) {
|
||||
el.style.cursor = 'grab';
|
||||
});
|
||||
// Add event listener for the drop event
|
||||
drake.on('drop', function (el, target, source, sibling) {
|
||||
// Log the target ID to the console
|
||||
//console.log('Dropped into:', target.getAttribute('data-column-name'));
|
||||
function hidePlaceholders() {
|
||||
document.querySelectorAll('.empty-placeholder').forEach(el => el.remove());
|
||||
}
|
||||
|
||||
if (CONFIG_TICKET_ORDERING === 0 && source == target) {
|
||||
drake.cancel(true); // Move the card back to its original position
|
||||
return;
|
||||
}
|
||||
|
||||
// Get all cards in the target column and their positions
|
||||
let cards = $(target).children('.task');
|
||||
let positions = [];
|
||||
// Run once on load
|
||||
showPlaceholders();
|
||||
|
||||
//id of current status / column
|
||||
let columnId = $(target).data('status-id');
|
||||
|
||||
let movedTicketId = $(el).data('ticket-id');
|
||||
let movedTicketStatusId = $(el).data('ticket-status-id');
|
||||
|
||||
cards.each(function(index, card) {
|
||||
let ticketId = $(card).data('ticket-id');
|
||||
let statusId = $(card).data('ticket-status-id');
|
||||
|
||||
let oldStatus = false;
|
||||
if (ticketId == movedTicketId) {
|
||||
oldStatus = movedTicketStatusId;
|
||||
}
|
||||
|
||||
//update the status id of the card if needed
|
||||
if (statusId != columnId) {
|
||||
$(card).data('ticket-status-id', columnId);
|
||||
statusId = columnId;
|
||||
}
|
||||
positions.push({
|
||||
ticket_id: ticketId,
|
||||
ticket_order: index,
|
||||
ticket_oldStatus: oldStatus,
|
||||
ticket_status: statusId ?? null// Get the new status ID from the target column
|
||||
});
|
||||
});
|
||||
|
||||
//console.log(positions);
|
||||
// Send AJAX request to update all ticket kanban orders and statuses
|
||||
$.ajax({
|
||||
url: 'ajax.php',
|
||||
type: 'POST',
|
||||
data: {
|
||||
update_kanban_ticket: true,
|
||||
positions: positions
|
||||
},
|
||||
success: function(response) {
|
||||
//console.log('Ticket kanban orders and statuses updated successfully.');
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
console.error('Error updating ticket kanban orders and statuses:', error);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
// -------------------------------
|
||||
// Utility: Detect touch device
|
||||
// -------------------------------
|
||||
function isTouchDevice() {
|
||||
return 'ontouchstart' in window || navigator.maxTouchPoints > 0;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -47,7 +47,7 @@ $sql = mysqli_query(
|
||||
LEFT JOIN tags ON tags.tag_id = location_tags.tag_id
|
||||
WHERE location_$archive_query
|
||||
$tag_query
|
||||
AND (location_name LIKE '%$q%' OR location_description LIKE '%$q%' OR location_address LIKE '%$q%' OR location_phone LIKE '%$phone_query%' OR tag_name LIKE '%$q%' OR client_name LIKE '%$q%')
|
||||
AND (location_name LIKE '%$q%' OR location_description LIKE '%$q%' OR location_address LIKE '%$q%' OR location_city LIKE '%$q%' OR location_state LIKE '%$q%' OR location_zip LIKE '%$q%' OR location_country LIKE '%$q%' OR location_phone LIKE '%$phone_query%' OR tag_name LIKE '%$q%' OR client_name LIKE '%$q%')
|
||||
$access_permission_query
|
||||
$client_query
|
||||
GROUP BY location_id
|
||||
@@ -99,7 +99,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<div class="col-md-3">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
|
||||
<?php
|
||||
$sql_tags_filter = mysqli_query($mysqli, "
|
||||
@@ -126,7 +126,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="col-md-2"></div>
|
||||
<?php } else { ?>
|
||||
<div class="col-md-2">
|
||||
<div class="input-group">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select class="form-control select2" name="client" onchange="this.form.submit()">
|
||||
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
|
||||
|
||||
@@ -333,7 +333,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</a>
|
||||
</td>
|
||||
<td><a href="//maps.<?php echo $session_map_source; ?>.com?q=<?php echo "$location_address $location_zip"; ?>" target="_blank"><?php echo $location_address; ?><br><?php echo "$location_city $location_state $location_zip"; ?></a></td>
|
||||
<td><a href="//maps.<?php echo $session_map_source; ?>.com?q=<?php echo "$location_address $location_zip"; ?>" target="_blank"><?php echo $location_address; ?><br><?php echo "$location_city $location_state $location_zip<br><small>$location_country</small>"; ?></a></td>
|
||||
<td>
|
||||
<?php echo $location_phone_display; ?>
|
||||
<?php echo $location_fax_display; ?>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
require_once "config.php";
|
||||
require_once "functions.php";
|
||||
require_once "check_login.php";
|
||||
require_once "includes/check_login.php";
|
||||
require_once 'plugins/totp/totp.php'; //TOTP MFA Lib
|
||||
|
||||
// Get Company Logo
|
||||
|
||||
@@ -75,20 +75,23 @@
|
||||
|
||||
<div class="tab-pane fade" id="pills-support">
|
||||
|
||||
<label>Support Phone</label>
|
||||
<label>Support Phone / <span class="text-secondary">Extension</span></label>
|
||||
<div class="form-row">
|
||||
<div class="col-8">
|
||||
<div class="col-9">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200">
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<input type="text" class="form-control" name="extension" placeholder="Prompts" maxlength="200">
|
||||
<div class="col-3">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="extension" placeholder="ext." maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<div class="modal" id="linkCredentialModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="credential_id">
|
||||
<option value="">- Select a Credential -</option>
|
||||
<?php
|
||||
|
||||
$sql_credentials_select = mysqli_query($mysqli, "SELECT credential_id, credential_name FROM credentials
|
||||
WHERE credential_client_id = $client_id
|
||||
AND credential_asset_id != $contact_id
|
||||
AND credential_asset_id = 0
|
||||
AND credential_archived_at IS NULL
|
||||
ORDER BY credential_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_credentials_select)) {
|
||||
$credential_id = intval($row['credential_id']);
|
||||
$credential_name = nullable_htmlentities($row['credential_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,57 +0,0 @@
|
||||
<div class="modal" id="linkDocumentModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="document_id">
|
||||
<option value="">- Select a Document -</option>
|
||||
<?php
|
||||
// Check if there are any associated documents
|
||||
if ($linked_documents) {
|
||||
$excluded_document_ids = implode(",", $linked_documents);
|
||||
$exclude_condition = "AND document_id NOT IN ($excluded_document_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed documents
|
||||
}
|
||||
|
||||
$sql_documents_select = mysqli_query($mysqli, "SELECT * FROM documents
|
||||
WHERE document_client_id = $client_id
|
||||
AND document_archived_at IS NULL
|
||||
$exclude_condition
|
||||
ORDER BY document_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_documents_select)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = nullable_htmlentities($row['document_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,59 +0,0 @@
|
||||
<div class="modal" id="linkFileModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="file_id">
|
||||
<option value="">- Select a File -</option>
|
||||
<?php
|
||||
// Check if there are any associated files
|
||||
if (!empty($linked_files)) {
|
||||
$excluded_file_ids = implode(",", $linked_files);
|
||||
$exclude_condition = "AND file_id NOT IN ($excluded_file_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed vendors
|
||||
}
|
||||
|
||||
$sql_files_select = mysqli_query($mysqli, "SELECT * FROM files
|
||||
LEFT JOIN folders ON folder_id = file_folder_id
|
||||
WHERE file_client_id = $client_id
|
||||
$exclude_condition
|
||||
ORDER BY folder_name ASC, file_name ASC"
|
||||
);
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_files_select)) {
|
||||
$file_id = intval($row['file_id']);
|
||||
$file_name = nullable_htmlentities($row['file_name']);
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_asset_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,56 +0,0 @@
|
||||
<div class="modal" id="linkServiceModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="service_id">
|
||||
<option value="">- Select a Service -</option>
|
||||
<?php
|
||||
// Check if there are any associated services
|
||||
if (!empty($linked_services)) {
|
||||
$excluded_service_ids = implode(",", $linked_services);
|
||||
$exclude_condition = "AND service_id NOT IN ($excluded_service_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed services
|
||||
}
|
||||
|
||||
$sql_services_select = mysqli_query($mysqli, "SELECT * FROM services
|
||||
WHERE service_client_id = $client_id
|
||||
$exclude_condition
|
||||
ORDER BY service_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_services_select)) {
|
||||
$service_id = intval($row['service_id']);
|
||||
$service_name = nullable_htmlentities($row['service_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_service_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,58 +0,0 @@
|
||||
<div class="modal" id="linkSoftwareModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $asset_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="software_id">
|
||||
<option value="">- Select a Device Software License -</option>
|
||||
<?php
|
||||
// Check if there are any associated sofctware
|
||||
if (!empty($linked_software)) {
|
||||
$excluded_software_ids = implode(",", $linked_software);
|
||||
$exclude_condition = "AND software_id NOT IN ($excluded_software_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed software
|
||||
}
|
||||
|
||||
$sql_software_select = mysqli_query($mysqli, "SELECT * FROM software
|
||||
WHERE software_client_id = $client_id
|
||||
AND software_archived_at IS NULL
|
||||
AND software_license_type = 'Device'
|
||||
$exclude_condition
|
||||
ORDER BY software_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_software_select)) {
|
||||
$software_id = intval($row['software_id']);
|
||||
$software_name = nullable_htmlentities($row['software_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_software_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -208,7 +208,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="location_phone_country_code" value="+1" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="location_phone_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="location_phone" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
@@ -228,7 +228,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="location_fax_country_code" value="+1" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="location_fax_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="location_fax" placeholder="Fax Number">
|
||||
</div>
|
||||
</div>
|
||||
@@ -267,7 +267,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="contact_phone_country_code" value="+1" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="contact_phone_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="contact_phone" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
@@ -287,7 +287,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="contact_mobile_country_code" value="+1" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="contact_mobile_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="contact_mobile" placeholder="Mobile Phone Number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -37,14 +37,14 @@
|
||||
<option value="0">/</option>
|
||||
<?php
|
||||
// Start displaying folder options from the root (parent_folder = 0)
|
||||
display_folder_options(0, $client_id);
|
||||
display_folder_options(0, $client_id, 1);
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="file" class="form-control-file" name="file[]" multiple id="fileInput" accept=".jpg, .jpeg, .gif, .png, .webp, .pdf, .txt, .md, .doc, .docx, .odt, .csv, .xls, .xlsx, .ods, .pptx, .odp, .zip, .tar, .gz, .xml, .msg, .json, .wav, .mp3, .ogg, .mov, .mp4, .av1, .ovpn, .cfg, .ps1, .vsdx, .drawio, .pfx, .unf, .key">
|
||||
<input type="file" class="form-control-file" name="file[]" multiple id="fileInput" accept=".jpg, .jpeg, .gif, .png, .webp, .pdf, .txt, .md, .doc, .docx, .odt, .csv, .xls, .xlsx, .ods, .pptx, .odp, .zip, .tar, .gz, .xml, .msg, .json, .wav, .mp3, .ogg, .mov, .mp4, .av1, .ovpn, .cfg, .ps1, .vsdx, .drawio, .pfx, .unf, .key, .stk, .bat">
|
||||
</div>
|
||||
<small class="text-secondary">Up to 20 files can be uploaded at once by holding down CTRL and selecting files</small>
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" value="+1" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
@@ -121,7 +121,7 @@
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="mobile_country_code" value="+1" placeholder="Code" maxlength="4">
|
||||
<input type="tel" class="form-control col-2" name="mobile_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="mobile" placeholder="Mobile Phone Number">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,51 +0,0 @@
|
||||
<div class="modal" id="linkAssetModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-desktop mr-2"></i>Link Asset to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="asset_id">
|
||||
<option value="">- Select an Asset -</option>
|
||||
<?php
|
||||
|
||||
$sql_assets_select = mysqli_query($mysqli, "SELECT asset_id, asset_name FROM assets
|
||||
WHERE asset_client_id = $client_id
|
||||
AND asset_contact_id != $contact_id
|
||||
AND asset_contact_id = 0
|
||||
AND asset_archived_at IS NULL
|
||||
ORDER BY asset_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_assets_select)) {
|
||||
$asset_id = intval($row['asset_id']);
|
||||
$asset_name = nullable_htmlentities($row['asset_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $asset_id ?>"><?php echo $asset_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,51 +0,0 @@
|
||||
<div class="modal" id="linkCredentialModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="credential_id">
|
||||
<option value="">- Select a Credential -</option>
|
||||
<?php
|
||||
|
||||
$sql_credentials_select = mysqli_query($mysqli, "SELECT credential_id, credential_name FROM credentials
|
||||
WHERE credential_client_id = $client_id
|
||||
AND credential_contact_id != $contact_id
|
||||
AND credential_contact_id = 0
|
||||
AND credential_archived_at IS NULL
|
||||
ORDER BY credential_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_credentials_select)) {
|
||||
$credential_id = intval($row['credential_id']);
|
||||
$credential_name = nullable_htmlentities($row['credential_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,57 +0,0 @@
|
||||
<div class="modal" id="linkDocumentModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="document_id">
|
||||
<option value="">- Select a Document -</option>
|
||||
<?php
|
||||
// Check if there are any associated documents
|
||||
if ($linked_documents) {
|
||||
$excluded_document_ids = implode(",", $linked_documents);
|
||||
$exclude_condition = "AND document_id NOT IN ($excluded_document_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed documents
|
||||
}
|
||||
|
||||
$sql_documents_select = mysqli_query($mysqli, "SELECT * FROM documents
|
||||
WHERE document_client_id = $client_id
|
||||
AND document_archived_at IS NULL
|
||||
$exclude_condition
|
||||
ORDER BY document_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_documents_select)) {
|
||||
$document_id = intval($row['document_id']);
|
||||
$document_name = nullable_htmlentities($row['document_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,59 +0,0 @@
|
||||
<div class="modal" id="linkFileModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="file_id">
|
||||
<option value="">- Select a File -</option>
|
||||
<?php
|
||||
// Check if there are any associated files
|
||||
if (!empty($linked_files)) {
|
||||
$excluded_file_ids = implode(",", $linked_files);
|
||||
$exclude_condition = "AND file_id NOT IN ($excluded_file_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed vendors
|
||||
}
|
||||
|
||||
$sql_files_select = mysqli_query($mysqli, "SELECT * FROM files
|
||||
LEFT JOIN folders ON folder_id = file_folder_id
|
||||
WHERE file_client_id = $client_id
|
||||
$exclude_condition
|
||||
ORDER BY folder_name ASC, file_name ASC"
|
||||
);
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_files_select)) {
|
||||
$file_id = intval($row['file_id']);
|
||||
$file_name = nullable_htmlentities($row['file_name']);
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_contact_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,56 +0,0 @@
|
||||
<div class="modal" id="linkServiceModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="service_id">
|
||||
<option value="">- Select a Service -</option>
|
||||
<?php
|
||||
// Check if there are any associated services
|
||||
if (!empty($linked_services)) {
|
||||
$excluded_service_ids = implode(",", $linked_services);
|
||||
$exclude_condition = "AND service_id NOT IN ($excluded_service_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed services
|
||||
}
|
||||
|
||||
$sql_services_select = mysqli_query($mysqli, "SELECT * FROM services
|
||||
WHERE service_client_id = $client_id
|
||||
$exclude_condition
|
||||
ORDER BY service_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_services_select)) {
|
||||
$service_id = intval($row['service_id']);
|
||||
$service_name = nullable_htmlentities($row['service_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_service_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,58 +0,0 @@
|
||||
<div class="modal" id="linkSoftwareModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content bg-dark">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $contact_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
|
||||
<div class="modal-body bg-white">
|
||||
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="software_id">
|
||||
<option value="">- Select a User Software License -</option>
|
||||
<?php
|
||||
// Check if there are any associated sofctware
|
||||
if (!empty($linked_software)) {
|
||||
$excluded_software_ids = implode(",", $linked_software);
|
||||
$exclude_condition = "AND software_id NOT IN ($excluded_software_ids)";
|
||||
} else {
|
||||
$exclude_condition = ""; // No condition if there are no displayed software
|
||||
}
|
||||
|
||||
$sql_software_select = mysqli_query($mysqli, "SELECT * FROM software
|
||||
WHERE software_client_id = $client_id
|
||||
AND software_archived_at IS NULL
|
||||
AND software_license_type = 'User'
|
||||
$exclude_condition
|
||||
ORDER BY software_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_software_select)) {
|
||||
$software_id = intval($row['software_id']);
|
||||
$software_name = nullable_htmlentities($row['software_name']);
|
||||
|
||||
?>
|
||||
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="link_software_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
</div>
|
||||
<div class="modal-footer bg-white">
|
||||
<button type="submit" name="add_invoice_recurring" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create Invoice</button>
|
||||
<button type="submit" name="add_invoice_recurring" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create Recurring Invoice</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user