Merge pull request #1233 from itflow-org/develop

25.09 Release
This commit is contained in:
Johnny 2025-09-05 13:24:54 -04:00 committed by GitHub
commit 58d43063ec
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
935 changed files with 18434 additions and 26685 deletions

1
.gitignore vendored
View File

@ -25,5 +25,6 @@ plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/CSS/*
xcustom/*
!xcustom/readme.php
post/xcustom
custom/*
!post/xcustom/readme.php
.zed

View File

@ -2,6 +2,92 @@
This file documents all notable changes made to ITFlow.
## [25.09]
***BACK UP*** before updating.
---
### Breaking Changes and Notes
- We strongly recommend updating from the command line, however if performed via the webui and after performed it will return a 404. thats normal as the directory structure has changed, just close your browser then log back in then go back to update to perform the many database updates.
- This is a major release with significant changes. While the community has done a great job identifying bugs, some may still remain — continued testing is encouraged.
- All AI settings will be **reset** and must be reconfigured using the new AI provider backend.
- The `xcustom` directory has been renamed to `custom`. All custom libraries and post-processing scripts should now be placed here.
---
### Added / Changed
- Numerous UI improvements and refinements across the application.
- Enhanced visual clarity by thickening the left border on ticket comments to help identify comment types.
- Ticket details UI redesigned to use less space at the top of the screen.
- Introduced tracking for the **first response date/time** on tickets.
- New reporting feature: **Average time to first response** on tickets.
- Stripe integration rebuilt using the new **payment provider backend**.
- Clients can now save and manage **multiple payment methods**.
- Support for selecting saved cards for **recurring invoices** in both the client and agent portals.
- Initial database structure and logic added for **credit management** (feature not yet enabled).
- Major **backend directory restructuring**.
- Introduced **stock/inventory management**, including a stock ledger backend.
- Stock quantities now update automatically when invoice items are added or removed.
- Invoice autocomplete now includes: **name, description, price, tax, stock levels**, and links `product_id` to `item_id`.
- Added a **category filter** to invoices.
- Linked stock to related expenses.
- New product fields: **location, code, and type**.
- Products now separated into two types: **Service** and **Product**.
- **Dark mode** introduced.
- Projects: Now support linking **closed tickets**.
- Clients: Added bulk actions for tags, referral source, industry, hourly rate, email, archive, and restore.
- Invoices: Bulk action added to **assign categories**.
- Assets: New `client_uri` field, visible in both the agent and client portals.
- Client Portal: Clients can now **select an asset** during ticket creation.
- Client Portal: Company logo now **displays in the header**.
- Client Portal: Dashboard cards are now **clickable** for more detail.
- Assets: Option added to include **MAC Address** in additional columns.
- Asset Interface: Bulk actions added — set DHCP, network type, and delete.
- API:
- Added `/location` endpoint.
- Ticket content now supports **HTML formatting**.
- New option to filter and display **500 records per page** in the footer.
- Payment methods are now treated as a **separate entity** instead of being grouped under categories.
- Updated libraries:
- **TinyMCE**
- **Chart.js** (major upgrade)
- **DataTables**
- **Bootstrap**
- **FullCalendar**
- **php-stripe**
---
### Fixed
- Several security vulnerabilities patched.
- Ticket status is no longer updated when scheduling.
- Client Portal: Tech contacts can no longer edit their own details.
- Fixed overlapping logo issue in Invoice/Quote PDF exports.
- Refactored `check_login.php` into multiple files for modular login functionality.
- Removed redundant logging comments for redirects.
- Renamed `get_settings.php` to `load_global_settings.php`.
- Simplified syntax for `ajax-modal` and updated usage throughout the app.
- Fixed issue where primary contact text wasnt displaying.
- Corrected client **Net Terms** display.
- Fixed logic for recurring expense **next run date**.
- Resolved broken **IMAP test button**.
- Archived clients can no longer log into the portal.
- Searching closed tickets no longer reverts to open tickets.
- Fixed project search filter not showing completed projects.
- Fixed issue where company logo was not being removed correctly.
- Resolved API bugs:
- Default rate and net terms.
- Contact location.
- Document endpoint.
---
### Developer Updates
- Replaced legacy code with newer functions like `redirect()`, `getFieldById()`, and `flash_alert()`.
- Significantly improved performance of queries used for filter selection boxes.
## [25.06.1]
### Fixed

108
admin/ai_model.php Normal file
View File

@ -0,0 +1,108 @@
<?php
// Default Column Sortby Filter
$sort = "ai_model_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli, "SELECT * FROM ai_models LEFT JOIN ai_providers ON ai_model_ai_provider_id = ai_provider_id ORDER BY $sort $order");
$num_rows = mysqli_num_rows($sql);
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-robot mr-2"></i>AI Models</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAIModelModal"><i class="fas fa-plus mr-2"></i>Add Model</button>
</div>
</div>
<div class="card-body">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ai_model_name&order=<?php echo $disp; ?>">
Model <?php if ($sort == 'ai_model_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ai_provider_name&order=<?php echo $disp; ?>">
Provider <?php if ($sort == 'ai_provider_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ai_model_use_case&order=<?php echo $disp; ?>">
Use Case<?php if ($sort == 'ai_model_use_case') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark">Prompt</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$provider_id = intval($row['ai_provider_id']);
$provider_name = nullable_htmlentities($row['ai_provider_name']);
$model_id = intval($row['ai_model_id']);
$model_name = nullable_htmlentities($row['ai_model_name']);
$use_case = nullable_htmlentities($row['ai_model_use_case']);
$prompt = nl2br(nullable_htmlentities($row['ai_model_prompt']));
?>
<tr>
<td>
<a class="text-dark text-bold ajax-modal" href="#"
data-modal-url="modals/ai/ai_model_edit.php?id=<?= $model_id ?>">
<?php echo $model_name; ?>
</a>
</td>
<td><?php echo $provider_name; ?></td>
<td><?php echo $use_case; ?></td>
<td><?php echo $prompt; ?></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">
<a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/ai/ai_model_edit.php?id=<?= $model_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_ai_model=<?php echo $model_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
}
if ($num_rows == 0) {
echo "<h3 class='text-secondary mt-3' style='text-align: center'>No Records Here</h3>";
}
?>
</tbody>
</table>
</div>
</div>
</div>
<?php
require_once "modals/ai/ai_model_add.php";
require_once "../includes/footer.php";

109
admin/ai_provider.php Normal file
View File

@ -0,0 +1,109 @@
<?php
// Default Column Sortby Filter
$sort = "ai_provider_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli, "SELECT * FROM ai_providers ORDER BY $sort $order");
$num_rows = mysqli_num_rows($sql);
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-robot mr-2"></i>AI Providers</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAIProviderModal"><i class="fas fa-plus mr-2"></i>Add Provider</button>
</div>
</div>
<div class="card-body">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ai_provider_name&order=<?php echo $disp; ?>">
Provider <?php if ($sort == 'ai_provider_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ai_provider_api_url&order=<?php echo $disp; ?>">
URL <?php if ($sort == 'ai_provider_api_url') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ai_provider_api_key&order=<?php echo $disp; ?>">
Key <?php if ($sort == 'ai_provider_api_key') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark">Models</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$provider_id = intval($row['ai_provider_id']);
$provider_name = nullable_htmlentities($row['ai_provider_name']);
$url = nullable_htmlentities($row['ai_provider_api_url']);
$key = nullable_htmlentities($row['ai_provider_api_key']);
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('ai_model_id') AS ai_model_count FROM ai_models WHERE ai_model_ai_provider_id = $provider_id"));
$ai_model_count = intval($row['ai_model_count']);
?>
<tr>
<td>
<a class="text-dark text-bold ajax-modal" href="#"
data-modal-url="modals/ai/ai_provider_edit.php?id=<?= $provider_id ?>">
<?php echo $provider_name; ?>
</a>
</td>
<td><?php echo $url; ?></td>
<td><?php echo $key; ?></td>
<td><?php echo $ai_model_count; ?></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">
<a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/ai/ai_provider_edit.php?id=<?= $provider_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_ai_provider=<?php echo $provider_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
}
if ($num_rows == 0) {
echo "<h3 class='text-secondary mt-3' style='text-align: center'>No Records Here</h3>";
}
?>
</tbody>
</table>
</div>
</div>
</div>
<?php
require_once "modals/ai/ai_provider_add.php";
require_once "../includes/footer.php";

View File

@ -162,15 +162,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</form>
</div>
<?php require_once "includes/filter_footer.php";
<?php require_once "../includes/filter_footer.php";
?>
</div>
</div>
<script src="js/bulk_actions.js"></script>
<script src="../js/bulk_actions.js"></script>
<?php
require_once "modals/admin_api_key_add_modal.php";
require_once "modals/api/api_key_add.php";
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -183,10 +183,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
<?php require_once "../includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -266,7 +266,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if (empty($client_name)) {
$client_name_display = "-";
} else {
$client_name_display = "<a href='client_overview.php?client_id=$client_id'>$client_name</a>";
$client_name_display = "<a href='../user/client_overview.php?client_id=$client_id'>$client_name</a>";
}
$log_entity_id = intval($row['log_entity_id']);
@ -292,11 +292,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
<?php require_once "../includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -34,5 +34,5 @@ require_once "includes/inc_all_admin.php";
</div>
<?php
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -34,7 +34,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if (!isset($_GET['archived'])) {
?>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addCategoryModal"><i
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/category/category_add.php?category=<?= nullable_htmlentities($category) ?>"><i
class="fas fa-plus mr-2"></i>New <?php echo nullable_htmlentities($category); ?> Category</button>
</div>
<?php
@ -77,13 +77,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
} else {
echo 'btn-default';
} ?>">Referral</a>
<a href="?category=Payment Method"
class="btn <?php if ($category == 'Payment Method') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Payment
Method</a>
<a href="?category=Ticket"
class="btn <?php if ($category == 'Ticket') {
echo 'btn-primary';
@ -126,11 +119,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<tr>
<td>
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_category_edit.php"
data-ajax-id="<?php echo $category_id; ?>"
>
<a class="text-dark ajax-modal" href="#"
data-modal-url="modals/category/category_edit.php?id=<?= $category_id ?>">
<?php echo $category_name; ?>
</a>
</td>
@ -155,11 +145,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
} else {
?>
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_category_edit.php"
data-ajax-id="<?php echo $category_id; ?>"
>
<a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/category/category_edit.php?id=<?= $category_id ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<a class="dropdown-item text-danger confirm-link"
@ -183,11 +170,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
<?php require_once "../includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_category_add_modal.php";
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -101,11 +101,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<tr>
<td>
<a href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_custom_link_edit.php"
data-ajax-id="<?php echo $custom_link_id; ?>"
>
<a class="ajax-modal" href="#"
data-modal-url="modals/custom_link/custom_link_edit.php?id=<?= $custom_link_id ?>">
<i class="fa fa-fw fa-<?php echo $custom_link_icon; ?> mr-2"></i><?php echo $custom_link_name;?>
</a>
</td>
@ -118,7 +115,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_custom_link_edit.php" data-ajax-id="<?php echo $custom_link_id; ?>">
<a class="dropdown-item ajax-modal" href="#" data-modal-url="modals/custom_link/custom_link_edit.php?id=<?= $custom_link_id ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
@ -138,11 +135,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
<?php require_once "../includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_custom_link_add_modal.php";
require_once "includes/footer.php";
require_once "modals/custom_link/custom_link_add.php";
require_once "../includes/footer.php";

View File

@ -2776,7 +2776,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
//Dropping patch panel as a patch panel can be documented as an asset with interfaces.
mysqli_query($mysqli, "DROP TABLE `patch_panel_ports`");
mysqli_query($mysqli, "DROP TABLE `patch_panels`");
mysqli_query($mysqli, "RENAME TABLE `events` TO `calendar_events`");
mysqli_query($mysqli, "RENAME TABLE `event_attendees` TO `calendar_event_attendees`");
@ -2957,7 +2957,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
ALTER TABLE `calendar_events`
ADD FOREIGN KEY (`event_calendar_id`) REFERENCES `calendars`(`calendar_id`) ON DELETE CASCADE
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.0.3'");
}
@ -2974,7 +2974,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
ALTER TABLE `certificate_history`
ADD FOREIGN KEY (`certificate_history_certificate_id`) REFERENCES `certificates`(`certificate_id`) ON DELETE CASCADE
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.0.4'");
}
@ -3335,14 +3335,14 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
ADD FOREIGN KEY (`vendor_id`) REFERENCES `vendors`(`vendor_id`) ON DELETE CASCADE,
ADD FOREIGN KEY (`file_id`) REFERENCES `files`(`file_id`) ON DELETE CASCADE
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.0.5'");
}
if (CURRENT_DATABASE_VERSION == '2.0.5') {
// CONVERT All tables TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci
$tables = [
'accounts', 'api_keys', 'app_logs', 'asset_credentials', 'asset_custom', 'asset_documents',
'asset_files', 'asset_history', 'asset_interface_links', 'asset_interfaces', 'asset_notes', 'assets',
@ -3381,14 +3381,14 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '2.0.7') {
mysqli_query($mysqli, "ALTER TABLE `files` DROP `file_hash`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.0.8'");
}
if (CURRENT_DATABASE_VERSION == '2.0.8') {
mysqli_query($mysqli, "ALTER TABLE `files` DROP `file_has_thumbnail`");
mysqli_query($mysqli, "ALTER TABLE `files` DROP `file_has_preview`");
mysqli_query($mysqli, "ALTER TABLE `files` DROP `file_asset_id`");
@ -3397,7 +3397,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
if (CURRENT_DATABASE_VERSION == '2.0.9') {
mysqli_query($mysqli, "ALTER TABLE `contacts` ADD `contact_phone_country_code` VARCHAR(10) DEFAULT 1 AFTER `contact_email`");
mysqli_query($mysqli, "ALTER TABLE `contacts` ADD `contact_mobile_country_code` VARCHAR(10) DEFAULT 1 AFTER `contact_extension`");
@ -3425,7 +3425,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
}
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");
@ -3460,7 +3460,7 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
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'");
}
@ -3675,13 +3675,306 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.0'");
}
// if (CURRENT_DATABASE_VERSION == '2.2.0') {
// // Insert queries here required to update to DB version 2.2.1
if (CURRENT_DATABASE_VERSION == '2.2.0') {
mysqli_query($mysqli, "ALTER TABLE `tickets` ADD `ticket_quote_id` INT(11) NOT NULL DEFAULT 0 AFTER `ticket_asset_id`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.1'");
}
if (CURRENT_DATABASE_VERSION == '2.2.1') {
mysqli_query($mysqli, "CREATE TABLE `ai_providers` (
`ai_provider_id` INT(11) NOT NULL AUTO_INCREMENT,
`ai_provider_name` VARCHAR(200) NOT NULL,
`ai_provider_api_url` VARCHAR(200) NOT NULL,
`ai_provider_api_key` VARCHAR(200) DEFAULT NULL,
`ai_provider_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ai_provider_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`ai_provider_id`)
)");
mysqli_query($mysqli, "
CREATE TABLE `ai_models` (
`ai_model_id` INT(11) NOT NULL AUTO_INCREMENT,
`ai_model_name` VARCHAR(200) NOT NULL,
`ai_model_prompt` TEXT DEFAULT NULL,
`ai_model_use_case` VARCHAR(200) DEFAULT NULL,
`ai_model_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`ai_model_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
`ai_model_ai_provider_id` INT(11) NOT NULL,
PRIMARY KEY (`ai_model_id`),
FOREIGN KEY (`ai_model_ai_provider_id`)
REFERENCES `ai_providers`(`ai_provider_id`)
ON DELETE CASCADE
)
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.2'");
}
if (CURRENT_DATABASE_VERSION == '2.2.2') {
mysqli_query($mysqli, "CREATE TABLE `payment_methods` (
`payment_method_id` INT(11) NOT NULL AUTO_INCREMENT,
`payment_method_name` VARCHAR(200) NOT NULL,
`payment_method_description` VARCHAR(250) DEFAULT NULL,
`payment_method_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`payment_method_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`payment_method_id`)
)");
mysqli_query($mysqli, "CREATE TABLE `payment_providers` (
`payment_provider_id` INT(11) NOT NULL AUTO_INCREMENT,
`payment_provider_name` VARCHAR(200) NOT NULL,
`payment_provider_description` VARCHAR(250) DEFAULT NULL,
`payment_provider_public_key` VARCHAR(250) DEFAULT NULL,
`payment_provider_private_key` VARCHAR(250) DEFAULT NULL,
`payment_provider_threshold` DECIMAL(15,2) DEFAULT NULL,
`payment_provider_active` TINYINT(1) NOT NULL DEFAULT 1,
`payment_provider_account` INT(11) NOT NULL,
`payment_provider_expense_vendor` INT(11) NOT NULL DEFAULT 0,
`payment_provider_expense_category` INT(11) NOT NULL DEFAULT 0,
`payment_provider_expense_percentage_fee` DECIMAL(4,4) DEFAULT NULL,
`payment_provider_expense_flat_fee` DECIMAL(15,2) DEFAULT NULL,
`payment_provider_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`payment_provider_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`payment_provider_id`)
)");
mysqli_query($mysqli, "CREATE TABLE `client_saved_payment_methods` (
`saved_payment_id` INT(11) NOT NULL AUTO_INCREMENT,
`saved_payment_provider_method` VARCHAR(200) NOT NULL,
`saved_payment_description` VARCHAR(200) DEFAULT NULL,
`saved_payment_client_id` INT(11) NOT NULL,
`saved_payment_provider_id` INT(11) NOT NULL,
`saved_payment_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
`saved_payment_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`saved_payment_id`),
FOREIGN KEY (`saved_payment_client_id`) REFERENCES clients(`client_id`) ON DELETE CASCADE,
FOREIGN KEY (`saved_payment_provider_id`) REFERENCES payment_providers(`payment_provider_id`) ON DELETE CASCADE
)");
mysqli_query($mysqli, "CREATE TABLE `client_payment_provider` (
`client_id` INT(11) NOT NULL,
`payment_provider_id` INT(11) NOT NULL,
`payment_provider_client` VARCHAR(200) NOT NULL,
`client_payment_provider_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`client_id`, `payment_provider_id`),
FOREIGN KEY (`client_id`) REFERENCES clients(`client_id`) ON DELETE CASCADE,
FOREIGN KEY (`payment_provider_id`) REFERENCES payment_providers(`payment_provider_id`) ON DELETE CASCADE
)");
mysqli_query($mysqli, "ALTER TABLE `recurring_payments` ADD `recurring_payment_saved_payment_id` INT(11) DEFAULT NULL AFTER `recurring_payment_recurring_invoice_id`");
mysqli_query($mysqli, "ALTER TABLE `recurring_payments` ADD CONSTRAINT `fk_recurring_saved_payment` FOREIGN KEY (`recurring_payment_saved_payment_id`) REFERENCES `client_saved_payment_methods`(`saved_payment_id`) ON DELETE CASCADE");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.3'");
}
if (CURRENT_DATABASE_VERSION == '2.2.3') {
mysqli_query($mysqli, "CREATE TABLE `credits` (
`credit_id` INT(11) NOT NULL AUTO_INCREMENT,
`credit_amount` DECIMAL(15,2) NOT NULL,
`credit_reference` VARCHAR(250) DEFAULT NULL,
`credit_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
`credit_created_by` INT(11) NOT NULL,
`credit_expire_at` DATE DEFAULT NULL,
`credit_client_id` INT(11) NOT NULL,
PRIMARY KEY (`credit_id`)
)");
mysqli_query($mysqli, "ALTER TABLE `invoices` ADD `invoice_credit_amount` DECIMAL(15,2) NOT NULL DEFAULT 0.00 AFTER `invoice_discount_amount`");
mysqli_query($mysqli, "CREATE TABLE `discount_codes` (
`discount_code_id` INT(11) NOT NULL AUTO_INCREMENT,
`discount_code_description` VARCHAR(250) DEFAULT NULL,
`discount_code_amount` DECIMAL(15,2) NOT NULL,
`discount_code` VARCHAR(200) NOT NULL,
`discount_code_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
`discount_code_created_by` INT(11) NOT NULL,
`discount_code_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
`discount_code_archived_at` DATETIME NULL DEFAULT NULL,
`discount_code_expire_at` DATE DEFAULT NULL,
PRIMARY KEY (`discount_code_id`)
)");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.4'");
}
if (CURRENT_DATABASE_VERSION == '2.2.4') {
mysqli_query($mysqli, "ALTER TABLE `settings` ADD `config_theme_dark` TINYINT(1) NOT NULL DEFAULT 0 AFTER `config_theme`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.5'");
}
if (CURRENT_DATABASE_VERSION == '2.2.5') {
mysqli_query($mysqli, "ALTER TABLE `assets` ADD `asset_uri_client` VARCHAR(500) NULL DEFAULT NULL AFTER `asset_uri_2`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.6'");
}
if (CURRENT_DATABASE_VERSION == '2.2.6') {
mysqli_query($mysqli, "ALTER TABLE `credits` DROP `credit_reference`");
mysqli_query($mysqli, "ALTER TABLE `credits` ADD `credit_type` ENUM('prepaid', 'manual', 'refund', 'promotion', 'usage') NOT NULL DEFAULT 'manual' AFTER `credit_amount`");
mysqli_query($mysqli, "ALTER TABLE `credits` ADD `credit_note` TEXT NULL DEFAULT NULL AFTER `credit_type`");
mysqli_query($mysqli, "ALTER TABLE `credits` ADD `credit_invoice_id` INT(11) NULL DEFAULT NULL AFTER `credit_expire_at`");
mysqli_query($mysqli, "ALTER TABLE `credits` ADD INDEX (`credit_client_id`)");
mysqli_query($mysqli, "ALTER TABLE `credits` ADD INDEX (`credit_invoice_id`)");
mysqli_query($mysqli, "ALTER TABLE `credits` ADD INDEX (`credit_created_at`)");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.7'");
}
if (CURRENT_DATABASE_VERSION == '2.2.7') {
mysqli_query($mysqli, "ALTER TABLE `user_settings` ADD `user_config_theme_dark` TINYINT(1) NOT NULL DEFAULT 0 AFTER `user_config_signature`");
mysqli_query($mysqli, "ALTER TABLE `settings` DROP `config_theme_dark`");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.8'");
}
if (CURRENT_DATABASE_VERSION == '2.2.8') {
mysqli_query($mysqli, "ALTER TABLE `products` ADD `product_type` ENUM('service', 'product') NOT NULL DEFAULT 'service' AFTER `product_name`");
mysqli_query($mysqli, "ALTER TABLE `products` ADD `product_code` VARCHAR(200) DEFAULT NULL AFTER `product_description`");
mysqli_query($mysqli, "ALTER TABLE `products` ADD `product_location` VARCHAR(250) DEFAULT NULL AFTER `product_code`");
mysqli_query($mysqli, "CREATE TABLE `product_stock` (
`stock_id` INT(11) NOT NULL AUTO_INCREMENT,
`stock_qty` INT(11) NOT NULL,
`stock_note` TEXT DEFAULT NULL,
`stock_created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP(),
`stock_expense_id` INT(11) DEFAULT NULL,
`stock_item_id` INT(11) DEFAULT NULL,
`stock_product_id` INT(11) NOT NULL,
PRIMARY KEY (`stock_id`)
)");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.9'");
}
if (CURRENT_DATABASE_VERSION == '2.2.9') {
// Migrate Stripe Settings over to new Tables
// Get Current Stripe Settings
$sql_stripe_settings = mysqli_query($mysqli, "SELECT * FROM settings WHERE company_id = 1");
$row = mysqli_fetch_array($sql_stripe_settings);
$config_stripe_enable = intval($row['config_stripe_enable']);
if ($config_stripe_enable === 1) {
$config_stripe_publishable = mysqli_real_escape_string($mysqli, $row['config_stripe_publishable']);
$config_stripe_secret = mysqli_real_escape_string($mysqli, $row['config_stripe_secret']);
$config_stripe_account = intval($row['config_stripe_account']);
$config_stripe_expense_vendor = intval($row['config_stripe_expense_vendor']);
$config_stripe_expense_category = intval($row['config_stripe_expense_category']);
$config_stripe_percentage_fee = floatval($row['config_stripe_percentage_fee']);
$config_stripe_flat_fee = floatval($row['config_stripe_flat_fee']);
mysqli_query($mysqli,"INSERT INTO payment_providers SET
payment_provider_name = 'Stripe',
payment_provider_public_key = '$config_stripe_publishable',
payment_provider_private_key = '$config_stripe_secret',
payment_provider_account = $config_stripe_account,
payment_provider_expense_vendor = $config_stripe_expense_vendor,
payment_provider_expense_category = $config_stripe_expense_category,
payment_provider_expense_percentage_fee = $config_stripe_percentage_fee,
payment_provider_expense_flat_fee = $config_stripe_flat_fee"
);
$provider_id = mysqli_insert_id($mysqli);
// Migrate Clients and Payment Method over
$sql_stripe_clients = mysqli_query($mysqli, "SELECT * FROM client_stripe WHERE stripe_pm IS NOT NULL AND stripe_pm != ''");
while ($row = mysqli_fetch_array($sql_stripe_clients)) {
$client_id = intval($row['client_id']);
$stripe_id = mysqli_real_escape_string($mysqli, $row['stripe_id']);
$stripe_pm = mysqli_real_escape_string($mysqli, $row['stripe_pm']);
$stripe_pm_details = mysqli_real_escape_string($mysqli, $row['stripe_pm_details'] ?? 'Saved Card');
mysqli_query($mysqli,"INSERT INTO client_payment_provider SET
client_id = $client_id,
payment_provider_id = $provider_id,
payment_provider_client = '$stripe_id'"
);
mysqli_query($mysqli,"INSERT INTO client_saved_payment_methods SET
saved_payment_provider_method = '$stripe_pm',
saved_payment_description = '$stripe_pm_details',
saved_payment_client_id = $client_id,
saved_payment_provider_id = $provider_id"
);
}
}
// Get Stripe provider id
$res = mysqli_query($mysqli, "
SELECT payment_provider_id
FROM payment_providers
WHERE payment_provider_name = 'Stripe'
ORDER BY payment_provider_id DESC
LIMIT 1
");
$stripe = mysqli_fetch_assoc($res);
$stripe_provider_id = intval($stripe['payment_provider_id']);
// Correct mapping: RP -> Recurring Invoice -> Client -> Client's Stripe saved method
mysqli_query($mysqli, "
UPDATE recurring_payments rp
INNER JOIN recurring_invoices ri
ON ri.recurring_invoice_id = rp.recurring_payment_recurring_invoice_id
INNER JOIN client_saved_payment_methods spm
ON spm.saved_payment_client_id = ri.recurring_invoice_client_id
AND spm.saved_payment_provider_id = $stripe_provider_id
SET
rp.recurring_payment_method = 'Credit Card',
rp.recurring_payment_saved_payment_id = spm.saved_payment_id
WHERE rp.recurring_payment_method = 'Stripe'
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.0'");
}
if (CURRENT_DATABASE_VERSION == '2.3.0') {
// Migrate Payment Methods from Categories Table to new payment_methods table
$sql_categories = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Payment Method' AND category_name != 'Stripe' AND category_archived_at IS NULL");
while ($row = mysqli_fetch_array($sql_categories)) {
$category_name = sanitizeInput($row['category_name']);
mysqli_query($mysqli,"INSERT INTO payment_methods SET payment_method_name = '$category_name'");
}
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.1'");
}
if (CURRENT_DATABASE_VERSION == '2.3.1') {
// Delete all Recurring Payments that are Stripe
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe'");
// Delete Stripe Specific ITFlow Client Stripe Client Relationship Table
mysqli_query($mysqli, "DROP TABLE client_stripe");
// Delete Unused Stripe and AI Settings now in their own tables
mysqli_query($mysqli, "ALTER TABLE `settings`
DROP `config_stripe_enable`,
DROP `config_stripe_publishable`,
DROP `config_stripe_secret`,
DROP `config_stripe_account`,
DROP `config_stripe_expense_vendor`,
DROP `config_stripe_expense_category`,
DROP `config_stripe_percentage_fee`,
DROP `config_stripe_flat_fee`,
DROP `config_ai_enable`,
DROP `config_ai_provider`,
DROP `config_ai_model`,
DROP `config_ai_url`,
DROP `config_ai_api_key`
");
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.2'");
}
// if (CURRENT_DATABASE_VERSION == '2.3.2') {
// // Insert queries here required to update to DB version 2.3.3
// // Then, update the database to the next sequential version
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.2.1'");
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.3'");
// }
} else {
// Up-to-date
}

View File

@ -1,8 +1,8 @@
<?php
require_once "includes/inc_all_admin.php";
require_once "includes/database_version.php";
require_once "config.php";
require_once "../includes/database_version.php";
require_once "../config.php";
$checks = [];
@ -53,6 +53,7 @@ $extensions = [
'php-curl' => 'curl',
'php-mbstring' => 'mbstring',
'php-gd' => 'gd',
'php-zip' => 'zip',
];
foreach ($extensions as $name => $ext) {
@ -245,7 +246,7 @@ $filePermissions[] = [
$uploadsStats = [];
// Define the uploads directory path
$uploadsDir = __DIR__ . '/uploads'; // Adjust the path if needed
$uploadsDir = __DIR__ . '/../uploads'; // Adjust the path if needed
if (is_dir($uploadsDir)) {
// Function to recursively count files and calculate total size
@ -348,7 +349,7 @@ if ($tablesResult) {
$dbComparison = [];
// Path to the db.sql file
$dbSqlFile = __DIR__ . '/db.sql';
$dbSqlFile = __DIR__ . '/../db.sql';
if (file_exists($dbSqlFile)) {
// Read the db.sql file
@ -765,5 +766,5 @@ $mysqli->close();
<?php
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -79,7 +79,7 @@
<tr>
<td>
<a class="text-bold" href="admin_document_template_details.php?document_template_id=<?php echo $document_template_id; ?>"><i class="fas fa-fw fa-file-alt text-dark"></i> <?php echo $document_template_name; ?></a>
<a class="text-bold" href="document_template_details.php?document_template_id=<?php echo $document_template_id; ?>"><i class="fas fa-fw fa-file-alt text-dark"></i> <?php echo $document_template_name; ?></a>
<div class="mt-1 text-secondary"><?php echo $document_template_description; ?></div>
</td>
<td>
@ -93,12 +93,9 @@
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
<a class="dropdown-item ajax-modal" href="#"
data-modal-size="xl"
data-ajax-url="ajax/ajax_document_template_edit.php"
data-ajax-id="<?php echo $document_template_id; ?>"
>
data-modal-url="modals/document_template/document_template_edit.php?id=<?= $document_template_id ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
@ -120,12 +117,12 @@
</table>
<br>
</div>
<?php require_once "includes/filter_footer.php"; ?>
<?php require_once "../includes/filter_footer.php"; ?>
</div>
</div>
<?php require_once "modals/admin_document_template_add_modal.php"; ?>
<?php require_once "includes/footer.php"; ?>
<?php require_once "modals/document_template/document_template_add.php"; ?>
<?php require_once "../includes/footer.php"; ?>
<script>
$(document).ready(function(){

View File

@ -4,7 +4,7 @@ require_once "includes/inc_all_admin.php";
//Initialize the HTML Purifier to prevent XSS
require "plugins/htmlpurifier/HTMLPurifier.standalone.php";
require "../plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
@ -29,13 +29,13 @@ $document_template_updated_at = nullable_htmlentities($row['document_template_up
<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="clients.php">Home</a>
<a href="../">Home</a>
</li>
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
<a href="users.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_document_template.php">Document Templates</a>
<a href="document_template.php">Document Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-file mr-2"></i><?php echo $document_template_name; ?></li>
</ol>
@ -46,12 +46,9 @@ $document_template_updated_at = nullable_htmlentities($row['document_template_up
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file mr-2"></i><?php echo $document_template_name; ?></h3>
<div class="card-tools">
<button type="button" class="btn btn-primary"
data-toggle="ajax-modal"
<button type="button" class="btn btn-primary ajax-modal"
data-modal-size="xl"
data-ajax-url="ajax/ajax_document_template_edit.php"
data-ajax-id="<?php echo $document_template_id; ?>"
>
data-modal-url="modals/document_template/document_template_edit.php?id=<?= $document_template_id ?>">
<i class="fas fa-edit mr-2"></i>Edit
</button>
</div>
@ -61,7 +58,7 @@ $document_template_updated_at = nullable_htmlentities($row['document_template_up
</div>
</div>
<script src="js/pretty_content.js"></script>
<script src="../js/pretty_content.js"></script>
<?php
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -13,7 +13,7 @@ require_once "includes/inc_all_admin.php";
<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>
<label>Identity Provider <small class='text-secondary'>(Currently only works with Microsoft Entra ID/AAD)</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>
@ -55,4 +55,4 @@ require_once "includes/inc_all_admin.php";
</div>
</div>
<?php require_once "includes/footer.php";
<?php require_once "../includes/footer.php";

View File

@ -0,0 +1,17 @@
<?php
require_once "../config.php";
require_once "../functions.php";
require_once "../includes/router.php";
require_once "../includes/check_login.php";
require_once "../includes/page_title.php";
if (!isset($session_is_admin) || !$session_is_admin) {
exit(WORDING_ROLECHECK_FAILED . "<br>Tell your admin: Your role does not have admin access.");
}
require_once "../includes/header.php";
require_once "../includes/top_nav.php";
require_once "includes/side_nav.php";
require_once "../includes/inc_wrapper.php";
require_once "../includes/inc_alert_feedback.php";
require_once "../includes/filter_header.php";
require_once "../includes/app_version.php";

View File

@ -1,6 +1,6 @@
<!-- Main Sidebar Container -->
<aside class="main-sidebar sidebar-dark-<?php echo nullable_htmlentities($config_theme); ?> d-print-none">
<a class="brand-link pb-1 mt-1" href="clients.php">
<a class="brand-link pb-1 mt-1" href="../user/dashboard.php">
<p class="h6">
<i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
<span class="brand-text">
@ -16,19 +16,19 @@
<ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" data-accordion="false">
<!-- ACCESS Section -->
<li class="nav-item">
<a href="admin_user.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "admin_user.php") {echo "active";} ?>">
<a href="users.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "users.php") {echo "active";} ?>">
<i class="nav-icon fas fa-users"></i>
<p>Users</p>
</a>
</li>
<li class="nav-item">
<a href="admin_role.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "admin_role.php") {echo "active";} ?>">
<a href="roles.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "roles.php") {echo "active";} ?>">
<i class="nav-icon fas fa-user-shield"></i>
<p>Roles</p>
</a>
</li>
<li class="nav-item">
<a href="admin_api.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "admin_api.php") {echo "active";} ?>">
<a href="api_keys.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "api_keys.php") {echo "active";} ?>">
<i class="nav-icon fas fa-key"></i>
<p>API Keys</p>
</a>
@ -36,35 +36,65 @@
<li class="nav-header">TAGS & CATEGORIES</li>
<li class="nav-item">
<a href="admin_tag.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_tag.php' ? 'active' : ''); ?>">
<a href="tag.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tag.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-tags"></i>
<p>Tags</p>
</a>
</li>
<li class="nav-item">
<a href="admin_category.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_category.php' ? 'active' : ''); ?>">
<a href="category.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'category.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-list-ul"></i>
<p>Categories</p>
</a>
</li>
<?php if ($config_module_enable_accounting) { ?>
<li class="nav-item">
<a href="admin_tax.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_tax.php' ? 'active' : ''); ?>">
<a href="tax.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tax.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-balance-scale"></i>
<p>Taxes</p>
</a>
</li>
<li class="nav-item">
<a href="payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'payment_method.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-hand-holding-usd"></i>
<p>Payment Methods</p>
</a>
</li>
<li class="nav-item">
<a href="payment_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'payment_provider.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i>
<p>Payment Providers</p>
</a>
</li>
<li class="nav-item">
<a href="saved_payment_method.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'saved_payment_method.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i>
<p>Saved Payments</p>
</a>
</li>
<li class="nav-item">
<a href="ai_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_provider.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-robot"></i>
<p>AI Providers</p>
</a>
</li>
<li class="nav-item">
<a href="ai_model.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_model.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-robot"></i>
<p>AI Models</p>
</a>
</li>
<?php } ?>
<?php if ($config_module_enable_ticketing) { ?>
<li class="nav-item">
<a href="admin_ticket_status.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_ticket_status.php' ? 'active' : ''); ?>">
<a href="ticket_status.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ticket_status.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-info-circle"></i>
<p>Ticket Statuses</p>
</a>
</li>
<?php } ?>
<li class="nav-item">
<a href="admin_custom_link.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_custom_link.php' ? 'active' : ''); ?>">
<a href="custom_link.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'custom_link.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-external-link-alt"></i>
<p>Custom Links</p>
</a>
@ -74,31 +104,31 @@
<li class="nav-header">TEMPLATES</li>
<li class="nav-item">
<a href="admin_project_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['admin_project_template.php', 'admin_project_template_details.php']) ? 'active' : ''); ?>">
<a href="project_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['project_template.php', 'project_template_details.php']) ? 'active' : ''); ?>">
<i class="nav-icon fas fa-project-diagram"></i>
<p>Project Templates</p>
</a>
</li>
<li class="nav-item">
<a href="admin_ticket_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['admin_ticket_template.php', 'admin_ticket_template_details.php']) ? 'active' : ''); ?>">
<a href="ticket_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['ticket_template.php', 'ticket_template_details.php']) ? 'active' : ''); ?>">
<i class="nav-icon fas fa-life-ring"></i>
<p>Ticket Templates</p>
</a>
</li>
<li class="nav-item">
<a href="admin_vendor_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_vendor_template.php' ? 'active' : ''); ?>">
<a href="vendor_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'vendor_template.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-building"></i>
<p>Vendor Templates</p>
</a>
</li>
<li class="nav-item">
<a href="admin_software_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_software_template.php' ? 'active' : ''); ?>">
<a href="software_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'software_template.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-rocket"></i>
<p>License Templates</p>
</a>
</li>
<li class="nav-item">
<a href="admin_document_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['admin_document_template.php', 'admin_document_template_details.php']) ? 'active' : ''); ?>">
<a href="document_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['document_template.php', 'document_template_details.php']) ? 'active' : ''); ?>">
<i class="nav-icon fas fa-file"></i>
<p>Document Templates</p>
</a>
@ -108,44 +138,44 @@
<li class="nav-header">MAINTENANCE</li>
<li class="nav-item">
<a href="admin_mail_queue.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_mail_queue.php' ? 'active' : ''); ?>">
<a href="mail_queue.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'mail_queue.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-mail-bulk"></i>
<p>Mail Queue</p>
</a>
</li>
<li class="nav-item">
<a href="admin_audit_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_audit_log.php' ? 'active' : ''); ?>">
<a href="audit_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'audit_log.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-history"></i>
<p>Audit Logs</p>
</a>
</li>
<li class="nav-item">
<a href="admin_app_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_app_log.php' ? 'active' : ''); ?>">
<a href="app_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'app_log.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-history"></i>
<p>App Logs</p>
</a>
</li>
<li class="nav-item">
<a href="admin_backup.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_backup.php' ? 'active' : ''); ?>">
<a href="backup.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'backup.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-cloud-upload-alt"></i>
<p>Backup</p>
</a>
</li>
<li class="nav-item">
<a href="admin_debug.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_debug.php' ? 'active' : ''); ?>">
<a href="debug.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'debug.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-bug"></i>
<p>Debug</p>
</a>
</li>
<li class="nav-item">
<a href="admin_update.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_update.php' ? 'active' : ''); ?>">
<a href="update.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'update.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-download"></i>
<p>Update</p>
</a>
</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_identity_provider.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']), ['settings_company.php', 'settings_localization.php', 'settings_theme.php', 'settings_security.php', 'settings_mail.php', 'settings_notification.php', 'settings_default.php', 'settings_invoice.php', 'settings_quote.php', 'settings_online_payment.php', 'settings_online_payment_clients.php', 'settings_project.php', 'settings_ticket.php', 'settings_ai.php', 'identity_provider.php', 'settings_telemetry.php', 'settings_module.php']) ? 'menu-open' : ''); ?>">
<a href="#" class="nav-link">
<p>
SETTINGS
@ -154,112 +184,92 @@
</a>
<ul class="nav nav-treeview">
<li class="nav-item">
<a href="admin_settings_company.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_company.php' ? 'active' : ''); ?>">
<a href="settings_company.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_company.php' ? 'active' : ''); ?>">
<i class="nav-icon fa fa-briefcase"></i>
<p>Company Details</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_localization.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_localization.php' ? 'active' : ''); ?>">
<a href="settings_localization.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_localization.php' ? 'active' : ''); ?>">
<i class="nav-icon fa fa-globe"></i>
<p>Localization</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_theme.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_theme.php' ? 'active' : ''); ?>">
<a href="settings_theme.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_theme.php' ? 'active' : ''); ?>">
<i class="nav-icon fa fa-paint-brush"></i>
<p>Theme</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_security.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_security.php' ? 'active' : ''); ?>">
<a href="settings_security.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_security.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-shield-alt"></i>
<p>Security</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_mail.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_mail.php' ? 'active' : ''); ?>">
<a href="settings_mail.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_mail.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-envelope"></i>
<p>Mail</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_notification.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_notification.php' ? 'active' : ''); ?>">
<a href="settings_notification.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_notification.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-bell"></i>
<p>Notifications</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_default.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_default.php' ? 'active' : ''); ?>">
<a href="settings_default.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_default.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-cogs"></i>
<p>Defaults</p>
</a>
</li>
<?php if ($config_module_enable_accounting) { ?>
<li class="nav-item">
<a href="admin_settings_invoice.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_invoice.php' ? 'active' : ''); ?>">
<a href="settings_invoice.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_invoice.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-file-invoice"></i>
<p>Invoice</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_quote.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_quote.php' ? 'active' : ''); ?>">
<a href="settings_quote.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_quote.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-comment-dollar"></i>
<p>Quote</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_online_payment.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_online_payment.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i>
<p>Online Payment</p>
</a>
</li>
<?php if ($config_stripe_enable) { ?>
<li class="nav-item">
<a href="admin_settings_online_payment_clients.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_online_payment_clients.php' ? 'active' : ''); ?>">
<i class="nav-icon far fa-credit-card"></i>
<p>Payment/Stripe Clients</p>
</a>
</li>
<?php } ?>
<?php } ?>
<?php if ($config_module_enable_ticketing) { ?>
<li class="nav-item">
<a href="admin_settings_project.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_project.php' ? 'active' : ''); ?>">
<a href="settings_project.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_project.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-project-diagram"></i>
<p>Project</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_ticket.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_ticket.php' ? 'active' : ''); ?>">
<a href="settings_ticket.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_ticket.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-life-ring"></i>
<p>Ticket</p>
</a>
</li>
<?php } ?>
<li class="nav-item">
<a href="admin_settings_ai.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_ai.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-robot"></i>
<p>AI</p>
</a>
</li>
<!-- Currently the only integration is the client portal SSO -->
<?php if ($config_client_portal_enable) { ?>
<li class="nav-item">
<a href="admin_identity_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_identity_provider.php' ? 'active' : ''); ?>">
<a href="identity_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'identity_provider.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-fingerprint"></i>
<p>Identity Provider</p>
</a>
</li>
<?php } ?>
<li class="nav-item">
<a href="admin_settings_telemetry.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_telemetry.php' ? 'active' : ''); ?>">
<a href="settings_telemetry.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_telemetry.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-satellite-dish"></i>
<p>Telemetry</p>
</a>
</li>
<li class="nav-item">
<a href="admin_settings_module.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'admin_settings_module.php' ? 'active' : ''); ?>">
<a href="settings_module.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_module.php' ? 'active' : ''); ?>">
<i class="nav-icon fas fa-cube"></i>
<p>Modules</p>
</a>

4
admin/index.php Normal file
View File

@ -0,0 +1,4 @@
<?php
header('Location: users.php');

View File

@ -174,12 +174,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<td><?php echo $email_status_display; ?></td>
<td><?php echo $email_attempts; ?></td>
<td class="text-center">
<a class="btn btn-sm btn-secondary" href="#"
data-toggle = "ajax-modal"
data-modal-size = "lg"
data-ajax-url = "ajax/ajax_admin_mail_queue_message_view.php"
data-ajax-id = "<?php echo $email_id; ?>"
>
<a class="btn btn-sm btn-secondary ajax-modal" href="#"
data-modal-size="lg"
data-modal-url="modals/mail_queue/mail_queue_message_view.php?id=<?= $email_id ?>">
<i class="fas fa-fw fa-eye"></i>
</a>
@ -205,11 +202,11 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</form>
<?php require_once "includes/filter_footer.php"; ?>
<?php require_once "../includes/filter_footer.php"; ?>
</div>
</div>
<script src="js/bulk_actions.js"></script>
<script src="../js/bulk_actions.js"></script>
<?php
require_once "includes/footer.php";
require_once "../includes/footer.php";

View File

@ -0,0 +1,73 @@
<div class="form-group">
<div class="modal" id="addAIModelModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-robot mr-2"></i>Add AI Model</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body">
<div class="form-group">
<label>Provider <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<select class="form-control select2" name="provider" required>
<option value="">- Select an AI Provider -</option>
<?php
$sql_ai_providers = mysqli_query($mysqli, "SELECT * FROM ai_providers");
while ($row = mysqli_fetch_array($sql_ai_providers)) {
$ai_provider_id = intval($row['ai_provider_id']);
$ai_provider_name = nullable_htmlentities($row['ai_provider_name']);
?>
<option value="<?php echo $ai_provider_id; ?>"><?php echo $ai_provider_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Model Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<input type="text" class="form-control" name="model" placeholder="ex gpt-4">
</div>
</div>
<div class="form-group">
<label>Use Case <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-th-list"></i></span>
</div>
<select class="form-control select2" name="use_case">
<option>General</option>
<option>Tickets</option>
<option>Documentation</option>
</select>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="8" name="prompt" placeholder="Enter a model prompt:"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_ai_model" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</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>

View File

@ -0,0 +1,90 @@
<?php
require_once '../../../includes/modal_header.php';
$model_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM ai_models WHERE ai_model_id = $model_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$ai_model_ai_provider_id = intval($row['ai_model_ai_provider_id']);
$model_id = intval($row['ai_model_id']);
$model_name = nullable_htmlentities($row['ai_model_name']);
$use_case = nullable_htmlentities($row['ai_model_use_case']);
$prompt = nullable_htmlentities($row['ai_model_prompt']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-robot mr-2"></i>Editing: <strong><?php echo $model_name; ?></strong></h5>
<button type="button" class="close text-light" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="model_id" value="<?php echo $model_id; ?>">
<div class="modal-body">
<div class="form-group">
<label>Provider <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<select class="form-control select2" name="provider" required>
<option value="">- Select an AI Provider -</option>
<?php
$sql_ai_providers = mysqli_query($mysqli, "SELECT * FROM ai_providers");
while ($row = mysqli_fetch_array($sql_ai_providers)) {
$ai_provider_id = intval($row['ai_provider_id']);
$ai_provider_name = nullable_htmlentities($row['ai_provider_name']);
?>
<option <?php if ($ai_provider_id = $ai_model_ai_provider_id) { echo "selected"; } ?> value="<?php echo $ai_provider_id; ?>"><?php echo $ai_provider_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Model Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<input type="text" class="form-control" name="model" value="<?php echo $model_name; ?>" placeholder="ex gpt-4">
</div>
</div>
<div class="form-group">
<label>Use Case <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-th-list"></i></span>
</div>
<select class="form-control select2" name="use_case">
<option <?php if ($use_case == 'General') { echo "selected"; } ?>>General</option>
<option <?php if ($use_case == 'Tickets') { echo "selected"; } ?>>Tickets</option>
<option <?php if ($use_case == 'Documentation') { echo "selected"; } ?>>Documentation</option>
</select>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="8" name="prompt" placeholder="Enter a model prompt:"><?php echo $prompt; ?></textarea>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_ai_model" 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>
<?php
require_once '../../../includes/modal_footer.php';

View File

@ -0,0 +1,54 @@
<div class="form-group">
<div class="modal" id="addAIProviderModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-robot mr-2"></i>New AI Provider</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body">
<div class="form-group">
<label>Provider Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<input type="text" class="form-control" name="provider" placeholder="ex OpenAI">
</div>
</div>
<div class="form-group">
<label>URL <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-globe"></i></span>
</div>
<input type="url" class="form-control" name="url" placeholder="ex https://ai.company.ext/api">
</div>
</div>
<div class="form-group">
<label>API Key</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="api_key" placeholder="Enter API key here">
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_ai_provider" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</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>

View File

@ -0,0 +1,69 @@
<?php
require_once '../../../includes/modal_header.php';
$provider_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM ai_providers WHERE ai_provider_id = $provider_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$provider_name = nullable_htmlentities($row['ai_provider_name']);
$url = nullable_htmlentities($row['ai_provider_api_url']);
$key = nullable_htmlentities($row['ai_provider_api_key']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-robot mr-2"></i>Editing: <strong><?php echo $provider_name; ?></strong></h5>
<button type="button" class="close text-light" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="provider_id" value="<?php echo $provider_id; ?>">
<div class="modal-body">
<div class="form-group">
<label>Provider Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<input type="text" class="form-control" name="provider" value="<?php echo $provider_name; ?>" placeholder="ex OpenAI">
</div>
</div>
<div class="form-group">
<label>URL <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-globe"></i></span>
</div>
<input type="url" class="form-control" name="url" value="<?php echo $url; ?>" placeholder="ex https://ai.company.ext/api">
</div>
</div>
<div class="form-group">
<label>API Key</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="api_key" value="<?php echo $key; ?>" placeholder="Enter API key here">
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_ai_provider" 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>
<?php
require_once '../../../includes/modal_footer.php';

View File

@ -4,15 +4,15 @@ $decryptPW = randomString(160);
?>
<div class="modal" id="addApiKeyModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-key mr-2"></i>New Key</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
@ -111,7 +111,7 @@ $decryptPW = randomString(160);
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_api_key" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -0,0 +1,48 @@
<?php
require_once '../../../includes/modal_header.php';
$category = nullable_htmlentities($_GET['category']);
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-list-ul mr-2"></i>New <strong><?= nullable_htmlentities($category) ?></strong> Category</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="type" value="<?php echo ($category); ?>">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-list-ul"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Category name" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group">
<label>Color <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paint-brush"></i></span>
</div>
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_category" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</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/modal_footer.php';

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$category_id = intval($_GET['id']);
@ -14,7 +14,7 @@ $category_type = nullable_htmlentities($row['category_type']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-list-ul mr-2"></i>Editing category: <strong><?php echo $category_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -23,7 +23,7 @@ ob_start();
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="category_id" value="<?php echo $category_id; ?>">
<input type="hidden" name="type" value="<?php echo $category_type; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -46,11 +46,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_category" 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>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,7 +1,7 @@
<div class="modal" id="createCustomFieldModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-th-list mr-2"></i>Create <?php echo nullable_htmlentities($table); ?> field</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -10,7 +10,7 @@
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="table" value="<?php echo nullable_htmlentities($table); ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Label <strong class="text-danger">*</strong></label>
@ -31,7 +31,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="create_custom_field" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,7 +1,7 @@
<div class="modal" id="editCustomFieldModal<?php echo $custom_field_id; ?>" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-th-list mr-2"></i>Editing custom field: <strong><?php echo $custom_field_label; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="custom_field_id" value="<?php echo $custom_field_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Label <strong class="text-danger">*</strong></label>
@ -30,7 +30,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_custom_field" 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>

View File

@ -1,7 +1,7 @@
<div class="modal" id="addLinkModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-external-link-alt mr-2"></i>New Custom Link</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -71,7 +71,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_custom_link" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$custom_link_id = intval($_GET['id']);
@ -17,7 +17,7 @@ $custom_link_location = intval($row['custom_link_location']);
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-external-link-alt mr-2"></i>Editing link: <strong><?php echo $custom_link_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -27,7 +27,7 @@ ob_start();
<input type="hidden" name="custom_link_id" value="<?php echo $custom_link_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -89,11 +89,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_custom_link" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,14 +1,14 @@
<div class="modal" id="addDocumentTemplateModal" tabindex="-1">
<div class="modal-dialog modal-xl">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-file-alt mr-2"></i>Creating Document Template</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<input type="text" class="form-control" name="name" placeholder="Template name" maxlength="200">
@ -40,7 +40,7 @@
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_document_template" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$document_template_id = intval($_GET['id']);
@ -14,7 +14,7 @@ $document_template_content = nullable_htmlentities($row['document_template_conte
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-file-alt mr-2"></i>Editing template: <strong><?php echo $document_template_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -22,7 +22,7 @@ ob_start();
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="document_template_id" value="<?php echo $document_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $document_template_name; ?>" placeholder="Name" required>
@ -37,11 +37,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_document_template" 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>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
if (!isset($session_is_admin) || !$session_is_admin) {
exit(WORDING_ROLECHECK_FAILED . "<br>Tell your admin: Your role does not have admin access.");
@ -9,7 +9,7 @@ if (!isset($session_is_admin) || !$session_is_admin) {
$email_id = intval($_GET['id']);
//Initialize the HTML Purifier to prevent XSS
require "../plugins/htmlpurifier/HTMLPurifier.standalone.php";
require "../../../plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
@ -43,13 +43,13 @@ if ($email_status == 0) {
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class='fas fa-fw fa-envelope-open mr-2'></i><strong><?php echo $email_subject; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<button type="button" class="close text-light" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body bg-white">
<div class="modal-body">
<div class="row">
<div class="col-md-1">
<span class="text-secondary">From:</span>
@ -73,7 +73,7 @@ ob_start();
</div>
</div>
<script src="../js/pretty_content.js"></script>
<script src="../../js/pretty_content.js"></script>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -0,0 +1,37 @@
<div class="modal" id="addPaymentMethodModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-credit-card mr-2"></i>Creating: <strong>Payment Method</strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-credit-card"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Payment method name" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="3" name="description" placeholder="Enter a description..."></textarea>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_payment_method" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</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>

View File

@ -0,0 +1,51 @@
<?php
require_once '../../../includes/modal_header.php';
$payment_method_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM payment_methods WHERE payment_method_id = $payment_method_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$payment_method_id = intval($row['payment_method_id']);
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
$payment_method_description = nullable_htmlentities($row['payment_method_description']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-credit-card mr-2"></i>Editing: <strong><?php echo $payment_method_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-credit-card"></i></span>
</div>
<input type="text" class="form-control" name="name" value="<?php echo $payment_method_name; ?>" placeholder="Payment method name" maxlength="200" required autofocus>
</div>
</div>
<div class="form-group">
<textarea class="form-control" rows="3" name="description" placeholder="Enter a description..."><?php echo $payment_method_description; ?></textarea>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_payment_method" 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>
<?php
require_once '../../../includes/modal_footer.php';

View File

@ -0,0 +1,103 @@
<div class="form-group">
<div class="modal" id="addPaymentProviderModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-credit-card mr-2"></i>Add Payment Provider</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body">
<div class="alert alert-info">
An income account named after the provider will always be created and used for income of paid invoices.<br>
If "Enable Expense" option is enabled, a matching vendor will also be automatically created for expense tracking. Additionally, an expense category named "Payment Processing" will be created.
</div>
<div class="form-group">
<label>Provider <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-credit-card"></i></span>
</div>
<select class="form-control select2" name="provider">
<option>Stripe</option>
</select>
</div>
</div>
<div class="form-group">
<label>Publishable key <strong class="text-danger">*</strong></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>
<input type="text" class="form-control" name="public_key" placeholder="Publishable API Key (pk_...)">
</div>
</div>
<div class="form-group">
<label>Secret key <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="private_key" placeholder="Secret API Key (sk_...)">
</div>
</div>
<div class="form-group">
<label>Threshold</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" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="threshold" placeholder="1000.00">
</div>
<small class="form-text text-muted">Will not show as an option at Checkout if above this number</small>
</div>
<hr>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="enable_expense" checked value="1" id="enableExpenseSwitch">
<label class="custom-control-label" for="enableExpenseSwitch">Enable Expense</label>
</div>
</div>
<div class="form-group">
<label>Percentage Fee to expense</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-percent"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="percentage_fee" placeholder="Enter Percentage">
</div>
<small class="form-text text-muted">See <a href="https://stripe.com/pricing" target="_blank">here <i class="fas fa-fw fa-external-link-alt"></i></a> for the latest Stripe Fees.</small>
</div>
<div class="form-group">
<label>Flat Fee to expense</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" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,3}" name="flat_fee" placeholder="0.030">
</div>
<small class="form-text text-muted">See <a href="https://stripe.com/pricing" target="_blank">here <i class="fas fa-fw fa-external-link-alt"></i></a> for the latest Stripe Fees.</small>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_payment_provider" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Add</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>

View File

@ -0,0 +1,107 @@
<?php
require_once '../../../includes/modal_header.php';
$provider_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM payment_providers WHERE payment_provider_id = $provider_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$provider_name = nullable_htmlentities($row['payment_provider_name']);
$public_key = nullable_htmlentities($row['payment_provider_public_key']);
$private_key = nullable_htmlentities($row['payment_provider_private_key']);
$account_id = nullable_htmlentities($row['payment_provider_account']);
$threshold = floatval($row['payment_provider_threshold']);
$vendor_id = nullable_htmlentities($row['payment_provider_expense_vendor']);
$category_id = nullable_htmlentities($row['payment_provider_expense_category']);
$percent_fee = floatval($row['payment_provider_expense_percentage_fee']) * 100;
$flat_fee = floatval($row['payment_provider_expense_flat_fee']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-credit-card mr-2"></i>Editing: <strong><?php echo $provider_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="provider_id" value="<?php echo $provider_id; ?>">
<div class="modal-body">
<div class="form-group">
<label>Publishable key <strong class="text-danger">*</strong></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>
<input type="text" class="form-control" name="public_key" placeholder="Publishable API Key (pk_...)" value="<?php echo $public_key; ?>">
</div>
</div>
<div class="form-group">
<label>Secret key <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="private_key" placeholder="Secret API Key (sk_...)" value="<?php echo $private_key; ?>">
</div>
</div>
<div class="form-group">
<label>Threshold</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" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="Threshold" placeholder="1000.00" value="<?php echo $threshold; ?>">
</div>
<small class="form-text text-muted">Will not show as an option at Checkout if above this number</small>
</div>
<hr>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="enable_expense" <?php if ($vendor_id) { echo "checked"; } ?> value="1" id="enableEditExpenseSwitch">
<label class="custom-control-label" for="enableEditExpenseSwitch">Enable Expense</label>
</div>
<small>(Category: Payment Processing -- Vendor: <?php echo $provider_name; ?></small>
</div>
<div class="form-group">
<label>Percentage Fee to expense</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-percent"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="percentage_fee" value="<?php echo $percent_fee; ?>" placeholder="Enter Percentage">
</div>
<small class="form-text text-muted">See <a href="https://stripe.com/pricing" target="_blank">here <i class="fas fa-fw fa-external-link-alt"></i></a> for the latest Stripe Fees.</small>
</div>
<div class="form-group">
<label>Flat Fee to expense</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" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,3}" name="flat_fee" value="<?php echo $flat_fee; ?>" placeholder="0.030">
</div>
<small class="form-text text-muted">See <a href="https://stripe.com/pricing" target="_blank">here <i class="fas fa-fw fa-external-link-alt"></i></a> for the latest Stripe Fees.</small>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_payment_provider" 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>
<?php
require_once '../../../includes/modal_footer.php';

View File

@ -1,7 +1,7 @@
<div class="modal" id="addProjectTemplateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-project-diagram mr-2"></i>Creating Project Template</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Project Template Name <strong class="text-danger">*</strong></label>
<div class="input-group">
@ -31,7 +31,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_project_template" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,7 +1,7 @@
<div class="modal" id="editProjectTemplateModal<?php echo $project_template_id; ?>" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-project-diagram mr-2"></i>Editing Project Template: <strong><?php echo $project_template_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -10,7 +10,7 @@
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="project_template_id" value="<?php echo $project_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Project Template Name <strong class="text-danger">*</strong></label>
<div class="input-group">
@ -33,7 +33,7 @@
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_project_template" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,7 +1,7 @@
<div class="modal" id="addProjectTemplateTicketTemplateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-life-ring mr-2"></i>Adding Ticket Template</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="project_template_id" value="<?php echo $project_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Ticket Template <strong class="text-danger">*</strong></label>
@ -54,7 +54,7 @@
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_ticket_template_to_project_template" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Add</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,7 +1,7 @@
<div class="modal" id="addRoleModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-shield mr-2"></i>Add new role</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="tab-content">
<div class="form-group">
@ -48,7 +48,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_role" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$role_id = intval($_GET['id']);
@ -35,7 +35,7 @@ if (empty($user_names_string)) {
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-shield mr-2"></i>Editing role:
<strong><?php echo $role_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
@ -45,7 +45,7 @@ ob_start();
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="role_id" value="<?php echo $role_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
@ -143,11 +143,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_role" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,14 +1,14 @@
<div class="modal" id="addSoftwareTemplateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>New License Template</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Template Name <strong class="text-danger">*</strong></label>
@ -73,7 +73,7 @@
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_software_template" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$software_template_id = intval($_GET['id']);
@ -17,7 +17,7 @@ $software_notes = nullable_htmlentities($row['software_template_notes']);
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>Editing template: <strong><?php echo $software_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -25,7 +25,7 @@ ob_start();
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="software_template_id" value="<?php echo $software_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Template Name <strong class="text-danger">*</strong></label>
@ -89,11 +89,11 @@ ob_start();
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"><?php echo $software_notes; ?></textarea>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_software_template" 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>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -0,0 +1,94 @@
<?php
require_once '../../../includes/modal_header.php';
$type_display = '';
if (isset($_GET['type'])) {
$type = intval($_GET['type']);
if ($type === 1) {
$type_display = "Client";
} elseif($type === 2) {
$type_display = "Location";
} elseif ($type === 3) {
$type_display = "Contact";
} elseif ($type === 4) {
$type_display = "Credential";
}
}
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-tag mr-2"></i>New <strong><?= $type_display ?></strong> Tag</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="type" value="<?php echo $type; ?>">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<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" placeholder="Tag name" maxlength="200" required autofocus>
</div>
</div>
<?php if (isset($_GET['type'])) { ?>
<input type="hidden" name="type" value="<?= $type ?>">
<?php } else { ?>
<div class="form-group">
<label>Type <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-th"></i></span>
</div>
<select class="form-control select2" name="type" required>
<option value="">- Type -</option>
<option value="1">Client Tag</option>
<option value="2">Location Tag</option>
<option value="3">Contact Tag</option>
<option value="4">Credential Tag</option>
</select>
</div>
</div>
<?php } ?>
<div class="form-group">
<label>Color <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paint-brush"></i></span>
</div>
<input type="color" class="form-control col-3" name="color" required>
</div>
</div>
<div class="form-group">
<label>Icon</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-image"></i></span>
</div>
<input type="text" class="form-control" name="icon" placeholder="Icon ex handshake">
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="add_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once '../../../includes/modal_footer.php';

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$tag_id = intval($_GET['id']);
@ -15,7 +15,7 @@ $tag_icon = nullable_htmlentities($row['tag_icon']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-tag mr-2"></i>Editing tag: <strong><?php echo $tag_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -23,7 +23,7 @@ ob_start();
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="tag_id" value="<?php echo $tag_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -72,11 +72,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,7 +1,7 @@
<div class="modal" id="addTaxModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header text-white">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-balance-scale mr-2"></i>New Tax</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span aria-hidden="true">&times;</span>
@ -10,7 +10,7 @@
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<input type="text" class="form-control" name="name" placeholder="Tax name" maxlength="200" required autofocus>
@ -20,7 +20,7 @@
<input type="number" min="0" step="any" class="form-control col-md-4" name="percent">
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_tax" class="btn btn-primary text-bold"><i class="fa fa-check mr- 2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$tax_id = intval($_GET['id']);
@ -13,7 +13,7 @@ $tax_percent = floatval($row['tax_percent']);
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-balance-scale mr-2"></i>Editing tax: <strong><?php echo $tax_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -23,7 +23,7 @@ ob_start();
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="tax_id" value="<?php echo $tax_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -36,11 +36,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_tax" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,7 +1,7 @@
<div class="modal" id="addTicketStatusModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-info-circle mr-2"></i>New Ticket Status</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -32,7 +32,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_ticket_status" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$ticket_status_id = intval($_GET['id']);
@ -15,7 +15,7 @@ $ticket_status_active = intval($row['ticket_status_active']);
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-info-circle mr-2"></i>Editing Ticket Status: <strong><?php echo $ticket_status_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -23,7 +23,7 @@ ob_start();
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_status_id" value="<?php echo $ticket_status_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -69,11 +69,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_ticket_status" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,14 +1,14 @@
<div class="modal" id="addTicketTemplateModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-life-ring mr-2"></i>Creating Ticket Template</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Template Name <strong class="text-danger">*</strong></label>
@ -31,7 +31,7 @@
</div>
<div class="form-group">
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" name="details"></textarea>
<textarea class="form-control tinymceTicket" name="details"></textarea>
</div>
<div class="form-group">
@ -65,7 +65,7 @@
</div>
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_ticket_template" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,8 +1,8 @@
<div class="modal" id="editTicketTemplateModal" tabindex="-1">
<div class="modal-dialog modal-lg">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-life-ring mr-2"></i>Editing Ticket Template: <?php echo $ticket_template_name; ?></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -10,7 +10,7 @@
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Template Name <strong class="text-danger">*</strong></label>
@ -33,7 +33,7 @@
</div>
<div class="form-group">
<textarea class="form-control tinymceTicket<?php if($config_ai_enable) { echo "AI"; } ?>" name="details"><?php echo $ticket_template_details; ?></textarea>
<textarea class="form-control tinymceTicket" name="details"><?php echo $ticket_template_details; ?></textarea>
</div>
<div class="form-group">
@ -47,7 +47,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_ticket_template" 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>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$task_template_id = intval($_GET['id']);
@ -17,7 +17,7 @@ ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fa fa-fw fa-tasks mr-2"></i>Editing task</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -26,7 +26,7 @@ ob_start();
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="task_template_id" value="<?php echo $task_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
@ -50,7 +50,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_ticket_template_task" 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>
@ -59,4 +59,4 @@ ob_start();
<?php
require_once "../includes/ajax_footer.php";
require_once '../../../includes/modal_footer.php';

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../includes/modal_header.php';
$user_id = intval($_GET['id']);
@ -28,7 +28,7 @@ while ($row = mysqli_fetch_assoc($user_client_access_sql)) {
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-edit mr-2"></i>Editing user:
<strong><?php echo $user_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
@ -38,7 +38,7 @@ ob_start();
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="user_id" value="<?php echo $user_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
@ -194,11 +194,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="edit_user" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
require_once '../../includes/modal_footer.php';

View File

@ -1,7 +1,7 @@
<div class="modal" id="addUserModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-plus mr-2"></i>New User</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
@ -146,7 +146,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_user" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -0,0 +1,204 @@
<?php
require_once '../../../includes/modal_header.php';
$user_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM users
LEFT JOIN user_settings ON users.user_id = user_settings.user_id
WHERE users.user_id = $user_id LIMIT 1"
);
$row = mysqli_fetch_array($sql);
$user_name = nullable_htmlentities($row['user_name']);
$user_email = nullable_htmlentities($row['user_email']);
$user_avatar = nullable_htmlentities($row['user_avatar']);
$user_token = nullable_htmlentities($row['user_token']);
$user_config_force_mfa = intval($row['user_config_force_mfa']);
$user_role_id = intval($row['user_role_id']);
$user_initials = nullable_htmlentities(initials($user_name));
// Get User Client Access Permissions
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_client_permissions WHERE user_id = $user_id");
$client_access_array = [];
while ($row = mysqli_fetch_assoc($user_client_access_sql)) {
$client_access_array[] = intval($row['client_id']);
}
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-edit mr-2"></i>Editing user:
<strong><?php echo $user_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="user_id" value="<?php echo $user_id; ?>">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-user-details<?php echo $user_id; ?>">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-user-access<?php echo $user_id; ?>">Restrict Access</a>
</li>
</ul>
<hr>
<div class="tab-content">
<div class="tab-pane fade show active" id="pills-user-details<?php echo $user_id; ?>">
<center class="mb-3">
<?php if (!empty($user_avatar)) { ?>
<img class="img-fluid" src="<?php echo "uploads/users/$user_id/$user_avatar"; ?>">
<?php } else { ?>
<span class="fa-stack fa-4x">
<i class="fa fa-circle fa-stack-2x text-secondary"></i>
<span class="fa fa-stack-1x text-white"><?php echo $user_initials; ?></span>
</span>
<?php } ?>
</center>
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Full Name" maxlength="200"
value="<?php echo $user_name; ?>" required>
</div>
</div>
<div class="form-group">
<label>Email <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="email" placeholder="Email Address" maxlength="200"
value="<?php echo $user_email; ?>" required>
</div>
</div>
<div class="form-group">
<label>New Password</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<input type="password" class="form-control" data-toggle="password" name="new_password"
placeholder="Leave Blank For No Password Change" autocomplete="new-password">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
</div>
</div>
<div class="form-group">
<label>Role <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user-shield"></i></span>
</div>
<select class="form-control select2" name="role" required>
<?php
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE role_archived_at IS NULL");
while ($row = mysqli_fetch_array($sql_user_roles)) {
$role_id = intval($row['role_id']);
$role_name = nullable_htmlentities($row['role_name']);
?>
<option <?php if ($role_id == $user_role_id) {echo "selected";} ?> value="<?php echo $role_id; ?>"><?php echo $role_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Avatar</label>
<input type="file" class="form-control-file" accept="image/*" name="file">
</div>
<div class="form-group">
<div class="custom-control custom-checkbox">
<input class="custom-control-input" type="checkbox" id="forceMFACheckBox<?php echo $user_id; ?>" name="force_mfa" value="1" <?php if($user_config_force_mfa == 1){ echo "checked"; } ?>>
<label for="forceMFACheckBox<?php echo $user_id; ?>" class="custom-control-label">
Force MFA
</label>
</div>
</div>
<?php if (!empty($user_token)) { ?>
<div class="form-group">
<label>2FA</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-id-card"></i></span>
</div>
<select class="form-control" name="2fa">
<option value="">Keep enabled</option>
<option value="disable">Disable</option>
</select>
</div>
</div>
<?php } ?>
</div>
<div class="tab-pane fade" id="pills-user-access<?php echo $user_id; ?>">
<div class="alert alert-info">
Check boxes to authorize user client access. No boxes grant full client access. Admin users are unaffected.
</div>
<ul class="list-group">
<li class="list-group-item bg-dark">
<div class="form-check">
<input type="checkbox" class="form-check-input" onclick="this.closest('.tab-pane').querySelectorAll('.client-checkbox').forEach(checkbox => checkbox.checked = this.checked);">
<label class="form-check-label ml-3"><strong>Restrict Access to Clients</strong></label>
</div>
</li>
<?php
$sql_client_select = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql_client_select)) {
$client_id_select = intval($row['client_id']);
$client_name_select = nullable_htmlentities($row['client_name']);
?>
<li class="list-group-item">
<div class="form-check">
<input type="checkbox" class="form-check-input client-checkbox" name="clients[]" value="<?php echo $client_id_select; ?>" <?php if (in_array($client_id_select, $client_access_array)) { echo "checked"; } ?>>
<label class="form-check-label ml-2"><?php echo $client_name_select; ?></label>
</div>
</li>
<?php } ?>
</ul>
</div>
</div>
</div>
<div class="modal-footer">
<button type="submit" name="edit_user" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../../../includes/modal_footer_new.php";

View File

@ -1,17 +1,17 @@
<div class="modal" id="exportUserModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-download mr-2"></i>Export Users to CSV</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">
<div class="modal-body">
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="export_users_csv" class="btn btn-primary text-bold"><i class="fas fa-fw fa-download mr-2"></i>Download CSV</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,7 +1,7 @@
<div class="modal" id="userInviteModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-user-plus"></i>Invite User</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -9,7 +9,7 @@
</div>
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<div class="form-group">
<label>Email <strong class="text-danger">*</strong></label>
@ -35,7 +35,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="invite_user" class="btn btn-primary text-bold"><i class="fas fa-paper-plane mr-2"></i>Send Invite</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,7 +1,7 @@
<div class="modal" id="addVendorTemplateModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<div class="modal-content">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-building mr-2"></i>New Vendor Template</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -11,7 +11,7 @@
<input type="hidden" name="client_id" value="<?php if (isset($_GET['client_id'])) { echo $client_id; } else { echo 0; } ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
@ -158,7 +158,7 @@
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" name="add_vendor_template" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create Template</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>

View File

@ -1,6 +1,6 @@
<?php
require_once '../includes/ajax_header.php';
require_once '../../../includes/modal_header.php';
$vendor_template_id = intval($_GET['id']);
@ -10,7 +10,8 @@ $vendor_name = nullable_htmlentities($row['vendor_template_name']);
$vendor_description = nullable_htmlentities($row['vendor_template_description']);
$vendor_account_number = nullable_htmlentities($row['vendor_template_account_number']);
$vendor_contact_name = nullable_htmlentities($row['vendor_template_contact_name']);
$vendor_phone = formatPhoneNumber($row['vendor_template_phone']);
$vendor_phone_country_code = intval($row['vendor_template_phone_country_code']);
$vendor_phone = formatPhoneNumber($row['vendor_template_phone'], $vendor_phone_country_code);
$vendor_extension = nullable_htmlentities($row['vendor_template_extension']);
$vendor_email = nullable_htmlentities($row['vendor_template_email']);
$vendor_website = nullable_htmlentities($row['vendor_template_website']);
@ -23,7 +24,7 @@ $vendor_notes = nullable_htmlentities($row['vendor_template_notes']);
ob_start();
?>
<div class="modal-header">
<div class="modal-header bg-dark">
<h5 class="modal-title"><i class="fas fa-fw fa-building mr-2"></i>Editing vendor template: <strong><?php echo $vendor_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
@ -31,7 +32,7 @@ ob_start();
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="vendor_template_id" value="<?php echo $vendor_template_id; ?>">
<div class="modal-body bg-white">
<div class="modal-body">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
@ -133,17 +134,20 @@ 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" placeholder="+" maxlength="4" value="<?php echo $vendor_phone_country_code; ?>">
<input type="tel" class="form-control" name="phone" value="<?php echo $vendor_phone; ?>">
<div class="input-group-append">
<div class="input-group-text">
<input type="checkbox" name="global_update_vendor_phone" value="1">
</div>
</div>
</div>
</div>
</div>
<div class="col-4">
<input type="text" class="form-control" name="extension" placeholder="Prompts" maxlength="200" value="<?php echo $vendor_extension; ?>">
<div class="input-group">
<input type="text" class="form-control" name="extension" placeholder="Prompts" maxlength="200" value="<?php echo $vendor_extension; ?>">
<div class="input-group-append">
<div class="input-group-text">
<input type="checkbox" name="global_update_vendor_phone" value="1">
</div>
</div>
</div>
</div>
</div>
@ -240,11 +244,11 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<div class="modal-footer">
<button type="submit" class="btn btn-primary text-bold" name="edit_vendor_template"><i class="fa fa-check mr-2"></i>Update Template</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";
require_once '../../../includes/modal_footer.php';

102
admin/payment_method.php Normal file
View File

@ -0,0 +1,102 @@
<?php
// Default Column Sortby Filter
$sort = "payment_method_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli, "SELECT * FROM payment_methods ORDER BY $sort $order");
$num_rows = mysqli_num_rows($sql);
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-credit-card mr-2"></i>Payment Methods</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addPaymentMethodModal"><i class="fas fa-plus mr-2"></i>Add Payment Method</button>
</div>
</div>
<div class="card-body">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_method_name&order=<?php echo $disp; ?>">
Method <?php if ($sort == 'payment_method_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_method_description&order=<?php echo $disp; ?>">
Description <?php if ($sort == 'payment_method_description') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_method_created_at&order=<?php echo $disp; ?>">
Created at <?php if ($sort == 'payment_method_created_at') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$payment_method_id = intval($row['payment_method_id']);
$payment_method_name = nullable_htmlentities($row['payment_method_name']);
$payment_method_description = nullable_htmlentities($row['payment_method_description']);
$payment_method_created_at = nullable_htmlentities($row['payment_method_created_at']);
?>
<tr>
<td>
<a class="text-dark text-bold ajax-modal" href="#"
data-modal-url="modals/payment_method/payment_method_edit.php?id=<?= $payment_method_id ?>">
<?php echo $payment_method_name; ?>
</a>
</td>
<td><?php echo $payment_method_description; ?></td>
<td><?php echo $payment_method_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">
<a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/payment_method/payment_method_edit.php?id=<?= $payment_method_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_payment_method=<?php echo $payment_method_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
}
if ($num_rows == 0) {
echo "<h3 class='text-secondary mt-3' style='text-align: center'>No Records Here</h3>";
}
?>
</tbody>
</table>
</div>
</div>
</div>
<?php
require_once "modals/payment_method/payment_method_add.php";
require_once "../includes/footer.php";

136
admin/payment_provider.php Normal file
View File

@ -0,0 +1,136 @@
<?php
// Default Column Sortby Filter
$sort = "payment_provider_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli, "SELECT * FROM payment_providers
LEFT JOIN accounts ON payment_provider_account = account_id
LEFT JOIN vendors ON payment_provider_expense_vendor = vendor_id
LEFT JOIN categories ON payment_provider_expense_category = category_id
ORDER BY $sort $order"
);
$num_rows = mysqli_num_rows($sql);
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-credit-card mr-2"></i>Payment Providers</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addPaymentProviderModal"><i class="fas fa-plus mr-2"></i>Add Provider</button>
</div>
</div>
<div class="card-body">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_provider_name&order=<?php echo $disp; ?>">
Provider <?php if ($sort == 'payment_provider_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=account_name&order=<?php echo $disp; ?>">
Expense / Income Account <?php if ($sort == 'account_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=payment_provider_threshold&order=<?php echo $disp; ?>">
Threshold <?php if ($sort == 'payment_provider_threshold') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_name&order=<?php echo $disp; ?>">
Expense 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; ?>">
Expense Category <?php if ($sort == 'category_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark">Fee</a>
</th>
<th>
<a class="text-dark">Saved Payment Methods</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$provider_id = intval($row['payment_provider_id']);
$provider_name = nullable_htmlentities($row['payment_provider_name']);
$provider_description = nullable_htmlentities($row['payment_provider_description']);
$account_name = nullable_htmlentities($row['account_name']);
$threshold = floatval($row['payment_provider_threshold']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
$category = nullable_htmlentities($row['category_name']);
$percent_fee = floatval($row['payment_provider_expense_percentage_fee']) * 100;
$flat_fee = floatval($row['payment_provider_expense_flat_fee']);
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT('saved_payment_id') AS saved_payment_count FROM client_saved_payment_methods WHERE saved_payment_provider_id = $provider_id"));
$saved_payment_count = intval($row['saved_payment_count']);
?>
<tr>
<td>
<a class="text-dark text-bold ajax-modal" href="#"
data-modal-url="modals/payment_provider/payment_provider_edit.php?id=<?= $provider_id ?>">
<?php echo $provider_name; ?>
</a>
<span class="text-secondary"><?php echo $provider_description; ?></span>
</td>
<td><?php echo $account_name; ?></td>
<td><?php echo numfmt_format_currency($currency_format, $threshold, $session_company_currency); ?></td>
<td><?php echo $vendor_name; ?></td>
<td><?php echo $category; ?></td>
<td><?php echo $percent_fee; ?> + <?php echo numfmt_format_currency($currency_format, $flat_fee, $session_company_currency); ?></td>
<td><?php echo $saved_payment_count; ?></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">
<a class="dropdown-item ajax-modal" href="#"
data-modal-url="modals/payment_provider/payment_provider_edit.php?id=<?= $provider_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?disable_payment_provicer=<?php echo $provider_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-thumbs-down mr-2"></i>Disable
</a>
</div>
</div>
</td>
</tr>
<?php
}
if ($num_rows == 0) {
echo "<h3 class='text-secondary mt-3' style='text-align: center'>No Records Here</h3>";
}
?>
</tbody>
</table>
</div>
</div>
</div>
<?php
require_once "modals/payment_provider/payment_provider_add.php";
require_once "../includes/footer.php";

42
admin/post.php Normal file
View File

@ -0,0 +1,42 @@
<?php
/*
* ITFlow - Admin GET/POST request handler
*/
require_once "../config.php";
require_once "../functions.php";
require_once "../includes/check_login.php";
// Define a variable that we can use to only allow running post files via inclusion (prevents people/bots poking them)
define('FROM_POST_HANDLER', true);
// Determine which files we should load
// Parse URL & get the path
$path = parse_url($_SERVER['HTTP_REFERER'], PHP_URL_PATH);
// Get the base name (the page name)
$module = explode(".", basename($path))[0];
// Strip off any _details bits
$module = str_ireplace('_details', '', $module);
// Dynamically load admin-related module POST logic
if (isset($session_is_admin) && $session_is_admin) {
// As (almost) every admin setting is only changed from 1 page, we can dynamically load the relevant logic inside this single admin check IF statement
// To add a new admin POST request handler, add a file named after the admin page
// e.g. changes made on the page http://itflow/admin_ticket_statues.php will load the page admin/post/admin_ticket_statues.php to handle the changes
include_once "post/$module.php";
}
// Logout is the same for user and admin
require_once "../post/logout.php";
// TODO: Find a home for these
require_once "../post/ai.php";
require_once "../post/misc.php";

65
admin/post/ai_model.php Normal file
View File

@ -0,0 +1,65 @@
<?php
/*
* ITFlow - GET/POST request handler for AI Models ('ai_model')
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_ai_model'])) {
validateCSRFToken($_POST['csrf_token']);
$provider_id = intval($_POST['provider']);
$model = sanitizeInput($_POST['model']);
$prompt = sanitizeInput($_POST['prompt']);
$use_case = sanitizeInput($_POST['use_case']);
mysqli_query($mysqli,"INSERT INTO ai_models SET ai_model_name = '$model', ai_model_prompt = '$prompt', ai_model_use_case = '$use_case', ai_model_ai_provider_id = $provider_id");
$ai_model_id = mysqli_insert_id($mysqli);
logAction("AI Model", "Create", "$session_name created AI Model $model");
flash_alert("AI Model <strong>$model</strong> created");
redirect();
}
if (isset($_POST['edit_ai_model'])) {
validateCSRFToken($_POST['csrf_token']);
$model_id = intval($_POST['model_id']);
$model = sanitizeInput($_POST['model']);
$prompt = sanitizeInput($_POST['prompt']);
$use_case = sanitizeInput($_POST['use_case']);
mysqli_query($mysqli,"UPDATE ai_models SET ai_model_name = '$model', ai_model_prompt = '$prompt', ai_model_use_case = '$use_case' WHERE ai_model_id = $model_id");
logAction("AI Model", "Edit", "$session_name edited AI Model $model");
flash_alert("AI Model <strong>$model</strong> edited");
redirect();
}
if (isset($_GET['delete_ai_model'])) {
validateCSRFToken($_GET['csrf_token']);
$model_id = intval($_GET['delete_ai_model']);
$model_name = sanitizeInput(getFieldById('ai_models', $model_id, 'ai_model_name'));
mysqli_query($mysqli,"DELETE FROM ai_models WHERE ai_model_id = $model_id");
logAction("AI Model", "Delete", "$session_name deleted AI Model $model_name");
flash_alert("AI Model <strong>$model_name</strong> deleted", 'error');
redirect();
}

View File

@ -0,0 +1,65 @@
<?php
/*
* ITFlow - GET/POST request handler for AI Providers ('ai_provider')
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_ai_provider'])) {
validateCSRFToken($_POST['csrf_token']);
$provider = sanitizeInput($_POST['provider']);
$url = sanitizeInput($_POST['url']);
$model = sanitizeInput($_POST['model']);
$api_key = sanitizeInput($_POST['api_key']);
mysqli_query($mysqli,"INSERT INTO ai_providers SET ai_provider_name = '$provider', ai_provider_api_url = '$url', ai_provider_api_key = '$api_key'");
$ai_provider_id = mysqli_insert_id($mysqli);
logAction("AI Provider", "Create", "$session_name created AI Provider $provider");
flash_alert("AI Model <strong>$provider</strong> created");
redirect();
}
if (isset($_POST['edit_ai_provider'])) {
validateCSRFToken($_POST['csrf_token']);
$provider_id = intval($_POST['provider_id']);
$provider = sanitizeInput($_POST['provider']);
$url = sanitizeInput($_POST['url']);
$api_key = sanitizeInput($_POST['api_key']);
mysqli_query($mysqli,"UPDATE ai_providers SET ai_provider_name = '$provider', ai_provider_api_url = '$url', ai_provider_api_key = '$api_key' WHERE ai_provider_id = $provider_id");
logAction("AI Provider", "Edit", "$session_name edited AI Provider $provider");
flash_alert("AI Model <strong>$provider</strong> edited");
redirect();
}
if (isset($_GET['delete_ai_provider'])) {
validateCSRFToken($_GET['csrf_token']);
$provider_id = intval($_GET['delete_ai_provider']);
$provider_name = sanitizeInput(getFieldById('ai_providers', $provider_id, 'ai_provider_name'));
mysqli_query($mysqli,"DELETE FROM ai_providers WHERE ai_provider_id = $provider_id");
logAction("AI Provider", "Delete", "$session_name deleted AI Provider $provider_name", 'error');
flash_alert("AI Provider <strong>$provider_name</strong> deleted", 'error');
redirect();
}

View File

@ -23,12 +23,11 @@ if (isset($_POST['add_api_key'])) {
$api_key_id = mysqli_insert_id($mysqli);
// Logging
logAction("API Key", "Create", "$session_name created API key $name set to expire on $expire", $client_id, $api_key_id);
$_SESSION['alert_message'] = "API Key <strong>$name</strong> created";
flash_alert("API Key <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -45,13 +44,11 @@ if (isset($_GET['delete_api_key'])) {
mysqli_query($mysqli,"DELETE FROM api_keys WHERE api_key_id = $api_key_id");
// Logging
logAction("API Key", "Delete", "$session_name deleted API key $name", $client_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "API Key <strong>$name</strong> deleted";
flash_alert("API Key <strong>$name</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -75,18 +72,16 @@ if (isset($_POST['bulk_delete_api_keys'])) {
mysqli_query($mysqli, "DELETE FROM api_keys WHERE api_key_id = $api_key_id");
// Logging
logAction("API Key", "Delete", "$session_name deleted API key $name", $client_id);
}
// Logging
logAction("API Key", "Bulk Delete", "$session_name deleted $count API key(s)");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Deleted <strong>$count</strong> API keys(s)";
flash_alert("Deleted <strong>$count</strong> API keys(s)", 'error');
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -6,9 +6,10 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
require_once "includes/app_version.php";
require_once "../includes/app_version.php";
if (isset($_GET['download_backup'])) {
validateCSRFToken($_GET['csrf_token']);
$timestamp = date('YmdHis');
@ -122,7 +123,7 @@ if (isset($_GET['download_backup'])) {
file_put_contents($sqlFile, $sqlContent);
// === 4. Zip the uploads folder
$zipFolder("uploads", $uploadsZip);
$zipFolder("../uploads", $uploadsZip);
// === 5. Create version.txt
$commitHash = trim(shell_exec('git log -1 --format=%H')) ?: 'N/A';
@ -175,7 +176,7 @@ if (isset($_GET['download_backup'])) {
fclose($fp);
logAction("System", "Backup Download", "$session_name downloaded full backup.");
$_SESSION['alert_message'] = "Full backup downloaded.";
flash_alert("Full backup downloaded.");
exit;
}
@ -192,10 +193,8 @@ if (isset($_POST['backup_master_key'])) {
if (password_verify($password, $row['user_password'])) {
$site_encryption_master_key = decryptUserSpecificKey($row['user_specific_encryption_ciphertext'], $password);
// Logging
logAction("Master Key", "Download", "$session_name retrieved the master encryption key");
// App Notify
appNotify("Master Key", "$session_name retrieved the master encryption key");
echo "==============================";
@ -204,13 +203,11 @@ if (isset($_POST['backup_master_key'])) {
echo "<br>==============================";
} else {
// Log the failure
logAction("Master Key", "Download", "$session_name attempted to retrieve the master encryption key but failed");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Incorrect password.";
flash_alert("Incorrect password.", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
}

View File

@ -8,35 +8,33 @@ defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_category'])) {
require_once 'post/admin/admin_category_model.php';
require_once 'category_model.php';
mysqli_query($mysqli,"INSERT INTO categories SET category_name = '$name', category_type = '$type', category_color = '$color'");
$category_id = mysqli_insert_id($mysqli);
// Logging
logAction("Category", "Create", "$session_name created category $type $name", 0, $category_id);
$_SESSION['alert_message'] = "Category $type <strong>$name</strong> created";
flash_alert("Category $type <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if (isset($_POST['edit_category'])) {
require_once 'post/admin/admin_category_model.php';
require_once 'category_model.php';
$category_id = intval($_POST['category_id']);
mysqli_query($mysqli,"UPDATE categories SET category_name = '$name', category_type = '$type', category_color = '$color' WHERE category_id = $category_id");
// Logging
logAction("Category", "Edit", "$session_name edited category $type $name", 0, $category_id);
$_SESSION['alert_message'] = "Category $type <strong>$name</strong> edited";
flash_alert("Category $type <strong>$name</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -52,13 +50,11 @@ if (isset($_GET['archive_category'])) {
mysqli_query($mysqli,"UPDATE categories SET category_archived_at = NOW() WHERE category_id = $category_id");
// Logging
logAction("Category", "Archive", "$session_name archived category $category_type $category_name", 0, $category_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Category $category_type <strong>$category_name</strong> archived";
flash_alert("Category $category_type <strong>$category_name</strong> archived", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -74,12 +70,11 @@ if (isset($_GET['unarchive_category'])) {
mysqli_query($mysqli,"UPDATE categories SET category_archived_at = NULL WHERE category_id = $category_id");
// Logging
logAction("Category", "Unarchive", "$session_name unarchived category $category_type $category_name", 0, $category_id);
$_SESSION['alert_message'] = "Category $category_type <strong>$category_name</strong> unarchived";
flash_alert("Category $category_type <strong>$category_name</strong> unarchived");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -95,12 +90,10 @@ if (isset($_GET['delete_category'])) {
mysqli_query($mysqli,"DELETE FROM categories WHERE category_id = $category_id");
// Logging
logAction("Category", "Delete", "$session_name deleted category $category_type $category_name");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Category $category_type <strong>$category_name</strong> deleted";
flash_alert("Category $category_type <strong>$category_name</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -8,7 +8,7 @@ defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if(isset($_POST['create_custom_field'])){
require_once 'post/admin/admin_custom_field_model.php';
require_once 'custom_field_model.php';
$table = sanitizeInput($_POST['table']);
@ -16,48 +16,42 @@ if(isset($_POST['create_custom_field'])){
$custom_field_id = mysqli_insert_id($mysqli);
// Logging
logAction("Custom Field", "Create", "$session_name created custom field $label", 0, $custom_field_id);
$_SESSION['alert_message'] = "Custom field <strong>$label</strong> created";
flash_alert("Custom field <strong>$label</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if(isset($_POST['edit_custom_field'])){
require_once 'post/admin/admin_custom_field_model.php';
require_once 'custom_field_model.php';
$custom_field_id = intval($_POST['custom_field_id']);
mysqli_query($mysqli,"UPDATE custom_fields SET custom_field_label = '$label', custom_field_type = '$type' WHERE custom_field_id = $custom_field_id");
// Logging
logAction("Custom Field", "Edit", "$session_name edited custom field $label", 0, $custom_field_id);
$_SESSION['alert_message'] = "Custom field <strong>$label</strong> edited";
flash_alert("Custom field <strong>$label</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if(isset($_GET['delete_custom_field'])){
$custom_field_id = intval($_GET['delete_custom_field']);
// Get Custom Field Label for logging
$sql = mysqli_query($mysqli,"SELECT custom_field_label FROM custom_fields WHERE custom_field_id = $custom_field_id");
$row = mysqli_fetch_array($sql);
$custom_field_label = sanitizeInput($row['custom_field_label']);
$label = sanitizeInput(getFieldById('custom_fields', $custom_field_id, 'custom_field_label'));
mysqli_query($mysqli,"DELETE FROM custom_fields WHERE custom_field_id = $custom_field_id");
// Logging
logAction("Custom Field", "Delete", "$session_name deleted custom field $label");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Custom field <strong>$label</strong> deleted";
flash_alert("Custom field <strong>$label</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -19,12 +19,11 @@ if (isset($_POST['add_custom_link'])) {
$custom_link_id = mysqli_insert_id($mysqli);
// Logging
logAction("Custom Link", "Create", "$session_name created custom link $name -> $uri", 0, $custom_link_id);
$_SESSION['alert_message'] = "Custom link <strong>$name</strong> created";
flash_alert("Custom link <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -40,16 +39,16 @@ if (isset($_POST['edit_custom_link'])) {
mysqli_query($mysqli,"UPDATE custom_links SET custom_link_name = '$name', custom_link_uri = '$uri', custom_link_new_tab = $new_tab, custom_link_icon = '$icon', custom_link_order = $order, custom_link_location = $location WHERE custom_link_id = $custom_link_id");
// Logging
logAction("Custom Link", "Edit", "$session_name edited custom link $name -> $uri", 0, $custom_link_id);
$_SESSION['alert_message'] = "Custom Link <strong>$name</strong> edited";
flash_alert("Custom Link <strong>$name</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if (isset($_GET['delete_custom_link'])) {
$custom_link_id = intval($_GET['delete_custom_link']);
// Get Custom Link name and uri for logging
@ -60,12 +59,10 @@ if (isset($_GET['delete_custom_link'])) {
mysqli_query($mysqli,"DELETE FROM custom_links WHERE custom_link_id = $custom_link_id");
// Logging
logAction("Custom Link", "Delete", "$session_name deleted custom link $custom_link_name -> $custom_link_uri");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Custom Link <strong>$name</strong> deleted";
flash_alert("Custom Link <strong>$name</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -10,17 +10,15 @@ if (isset($_POST['add_document_template'])) {
$description = sanitizeInput($_POST['description']);
$content = mysqli_real_escape_string($mysqli,$_POST['content']);
// Document create query
mysqli_query($mysqli,"INSERT INTO document_templates SET document_template_name = '$name', document_template_description = '$description', document_template_content = '$content', document_template_created_by = $session_user_id");
$document_template_id = mysqli_insert_id($mysqli);
// Logging
logAction("Document Template", "Create", "$session_name created document template $name", 0, $document_template_id);
$_SESSION['alert_message'] = "Document template <strong>$name</strong> created";
flash_alert("Document template <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -34,12 +32,11 @@ if (isset($_POST['edit_document_template'])) {
// Document edit query
mysqli_query($mysqli,"UPDATE document_templates SET document_template_name = '$name', document_template_description = '$description', document_template_content = '$content', document_template_updated_by = $session_user_id WHERE document_template_id = $document_template_id");
// Logging
logAction("Document Template", "Edit", "$session_name edited document template $name", 0, $document_template_id);
$_SESSION['alert_message'] = "Document Template <strong>$name</strong> edited";
flash_alert("Document Template <strong>$name</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -47,19 +44,14 @@ if (isset($_GET['delete_document_template'])) {
$document_template_id = intval($_GET['delete_document_template']);
// Get Document Template Name for logging
$sql = mysqli_query($mysqli,"SELECT document_template_name FROM document_templates WHERE document_template_id = $document_template_id");
$row = mysqli_fetch_array($sql);
$document_template_name = sanitizeInput($row['document_template_name']);
$document_template_name = sanitizeInput(getFieldById('document_templates', $document_template_id, 'document_template_name'));
mysqli_query($mysqli,"DELETE FROM document_templates WHERE document_template_id = $document_template_id");
//Logging
logAction("Document Template", "Delete", "$session_name deleted document template $document_template_name");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Document Template <strong>$document_template_name</strong> deleted";
flash_alert("Document Template <strong>$document_template_name</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -11,11 +11,10 @@ if (isset($_POST['edit_identity_provider'])) {
mysqli_query($mysqli,"UPDATE settings SET config_azure_client_id = '$azure_client_id', config_azure_client_secret = '$azure_client_secret' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited identity provider settings");
$_SESSION['alert_message'] = "Identity Provider Settings updated";
flash_alert("Identity Provider Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -8,12 +8,11 @@ if (isset($_GET['send_failed_mail'])) {
mysqli_query($mysqli,"UPDATE email_queue SET email_status = 0, email_attempts = 3 WHERE email_id = $email_id");
// Logging
logAction("Email", "Send", "$session_name attempted to force send email id: $email_id in the mail queue", 0, $email_id);
$_SESSION['alert_message'] = "Email Force Sent, give it a minute to resend";
flash_alert("Email Force Sent, give it a minute to resend");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -23,13 +22,11 @@ if (isset($_GET['cancel_mail'])) {
mysqli_query($mysqli,"UPDATE email_queue SET email_status = 2, email_attempts = 99, email_failed_at = NOW() WHERE email_id = $email_id");
// Logging
logAction("Email", "Send", "$session_name canceled send email id: $email_id in the mail queue", 0, $email_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Email cancelled and marked as failed.";
flash_alert("Email cancelled and marked as failed.", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -47,19 +44,18 @@ if (isset($_POST['bulk_cancel_emails'])) {
$email_id = intval($email_id);
mysqli_query($mysqli,"UPDATE email_queue SET email_status = 2, email_attempts = 99, email_failed_at = NOW() WHERE email_id = $email_id");
// Logging
logAction("Email", "Cancel", "$session_name cancelled email id: $email_id in the mail queue", 0, $email_id);
}
// Logging
logAction("Email", "Bulk Cancel", "$session_name cancelled $count email(s) in the mail queue");
$_SESSION['alert_message'] = "Cancelled <strong>$count</strong> email(s)";
flash_alert("Cancelled <strong>$count</strong> email(s)", 'error');
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if (isset($_POST['bulk_delete_emails'])) {
@ -76,18 +72,16 @@ if (isset($_POST['bulk_delete_emails'])) {
$email_id = intval($email_id);
mysqli_query($mysqli,"DELETE FROM email_queue WHERE email_id = $email_id");
// Logging
logAction("Email", "Delete", "$session_name deleted email id: $email_id from the mail queue");
}
// Logging
logAction("Email", "Bulk Delete", "$session_name deleted $count email(s) from the mail queue");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Deleted <strong>$count</strong> email(s)";
flash_alert("Deleted <strong>$count</strong> email(s)", 'error');
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -0,0 +1,58 @@
<?php
/*
* ITFlow - GET/POST request handler for AI Providers ('ai_providers')
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_payment_method'])) {
validateCSRFToken($_POST['csrf_token']);
$name = sanitizeInput($_POST['name']);
$description = sanitizeInput($_POST['description']);
mysqli_query($mysqli,"INSERT INTO payment_methods SET payment_method_name = '$name', payment_method_description = '$description'");
logAction("Payment Method", "Create", "$session_name created Payment Method $name");
flash_alert("Payment Method <strong>$name</strong> created");
redirect();
}
if (isset($_POST['edit_payment_method'])) {
validateCSRFToken($_POST['csrf_token']);
$payment_method_id = intval($_POST['payment_method_id']);
$name = sanitizeInput($_POST['name']);
$description = sanitizeInput($_POST['description']);
mysqli_query($mysqli,"UPDATE payment_methods SET payment_method_name = '$name', payment_method_description = '$description' WHERE payment_method_id = $payment_method_id");
logAction("Payment Method", "Edit", "$session_name edited Payment Method $name");
flash_alert("Payment Method <strong>$name</strong> edited");
redirect();
}
if (isset($_GET['delete_payment_method'])) {
$payment_method_id = intval($_GET['delete_payment_method']);
$payment_method_name = sanitizeInput(getFieldById('payment_methods', $payment_method_is, 'payment_method_name'));
mysqli_query($mysqli,"DELETE FROM payment_methods WHERE payment_method_id = $payment_method_id");
logAction("Payment Method", "Delete", "$session_name deleted Payment Method $payment_method_name");
flash_alert("Payment Method <strong>$payment_method_name</strong> deleted", 'error');
redirect();
}

View File

@ -0,0 +1,108 @@
<?php
/*
* ITFlow - GET/POST request handler for AI Providers ('ai_providers')
*/
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_payment_provider'])) {
validateCSRFToken($_POST['csrf_token']);
$provider = sanitizeInput($_POST['provider']);
$public_key = sanitizeInput($_POST['public_key']);
$private_key = sanitizeInput($_POST['private_key']);
$threshold = floatval($_POST['threshold']);
$enable_expense = intval($_POST['enable_expense'] ?? 0);
$percentage_fee = floatval($_POST['percentage_fee']) / 100;
$flat_fee = floatval($_POST['flat_fee']);
// Check to make sure Provider isnt added Twice
$sql = "SELECT 1 FROM payment_providers WHERE payment_provider_name = '$provider' LIMIT 1";
$result = mysqli_query($mysqli, $sql);
if (mysqli_num_rows($result) > 0) {
flash_alert("Payment Provider <strong>$provider</strong> already exists", 'error');
redirect();
}
// Check for Stripe Account if not create it
$sql_account = mysqli_query($mysqli,"SELECT account_id FROM accounts WHERE account_name = '$provider' AND account_archived_at IS NULL LIMIT 1");
if (mysqli_num_rows($sql_account) == 0) {
$account_id = mysqli_insert_id($mysqli);
} else {
$row = mysqli_fetch_array($sql_account);
$account_id = intval($row['account_id']);
}
if ($enable_expense) {
// Category
$sql_category = mysqli_query($mysqli,"SELECT category_id FROM categories WHERE category_name = 'Payment Processing' AND category_type = 'Expense' AND category_archived_at IS NULL LIMIT 1");
if (mysqli_num_rows($sql_category) == 0) {
mysqli_query($mysqli,"INSERT INTO categories SET category_name = 'Processing Fee', category_type = 'Payment Processing', category_color = 'gray'");
$category_id = mysqli_insert_id($mysqli);
} else {
$row = mysqli_fetch_array($sql_category);
$category_id = intval($row['category_id']);
}
//Vendor
$sql_vendor = mysqli_query($mysqli,"SELECT vendor_id FROM vendors WHERE vendor_name = '$provider' AND vendor_client_id = 0 AND vendor_archived_at IS NULL LIMIT 1");
if (mysqli_num_rows($sql_vendor) == 0) {
mysqli_query($mysqli,"INSERT INTO vendors SET vendor_name = '$provider', vendor_descripion = 'Payment Processor Provider', vendor_client_id = 0");
$vendor_id = mysqli_insert_id($mysqli);
} else {
$row = mysqli_fetch_array($sql_vendor);
$vendor_id = intval($row['vendor_id']);
}
}
mysqli_query($mysqli,"INSERT INTO payment_providers SET payment_provider_name = '$provider', payment_provider_public_key = '$public_key', payment_provider_private_key = '$private_key', payment_provider_account = $account_id, payment_provider_expense_vendor = $vendor_id, payment_provider_expense_category = $category_id, payment_provider_expense_percentage_fee = $percentage_fee, payment_provider_expense_flat_fee = $flat_fee");
$provider_id = mysqli_insert_id($mysqli);
logAction("Payment Provider", "Create", "$session_name created AI Provider $provider");
flash_alert("Payment provider <strong>$provider</strong> created");
redirect();
}
if (isset($_POST['edit_payment_provider'])) {
validateCSRFToken($_POST['csrf_token']);
$provider_id = intval($_POST['provider_id']);
$description = sanitizeInput($_POST['description']);
$public_key = sanitizeInput($_POST['public_key']);
$private_key = sanitizeInput($_POST['private_key']);
$threshold = floatval($_POST['threshold']);
$enable_expense = intval($_POST['enable_expense'] ?? 0);
$percentage_fee = floatval($_POST['percentage_fee']) / 100;
$flat_fee = floatval($_POST['flat_fee']);
mysqli_query($mysqli,"UPDATE payment_providers SET payment_provider_public_key = '$public_key', payment_provider_private_key = '$private_key', payment_provider_expense_percentage_fee = $percentage_fee, payment_provider_expense_flat_fee = $flat_fee WHERE payment_provider_id = $provider_id");
logAction("Payment Provider", "Edit", "$session_name edited Payment Provider $provider");
flash_alert("Payment Provider <strong>$provider</strong> edited");
redirect();
}
if (isset($_GET['delete_payment_provider'])) {
$provider_id = intval($_GET['delete_payment_provider']);
$provider_name = sanitizeInput(getFieldById('provider_providers', $provider_id, 'provider_name'));
mysqli_query($mysqli,"DELETE FROM payment_providers WHERE payment_provider_id = $provider_id");
logAction("Payment Provider", "Delete", "$session_name deleted Payment Provider $provider_name");
flash_alert("Payment Provider <strong>$provider_name</strong> deleted", 'error');
redirect();
}

View File

@ -11,12 +11,11 @@ if (isset($_POST['add_project_template'])) {
$project_template_id = mysqli_insert_id($mysqli);
// Logging
logAction("Project Template", "Create", "$session_name created project template $name", 0, $project_template_id);
$_SESSION['alert_message'] = "Project Template <strong>$name</strong> created";
flash_alert("Project Template <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -28,12 +27,12 @@ if (isset($_POST['edit_project_template'])) {
mysqli_query($mysqli, "UPDATE project_templates SET project_template_name = '$name', project_template_description = '$description' WHERE project_template_id = $project_template_id");
// Logging
logAction("Project Template", "Edit", "$session_name edited project template $name", 0, $project_template_id);
$_SESSION['alert_message'] = "Project Template <strong>$name</strong> edited";
flash_alert("Project Template <strong>$name</strong> edited");
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_POST['edit_ticket_template_order'])) {
@ -44,7 +43,8 @@ if (isset($_POST['edit_ticket_template_order'])) {
mysqli_query($mysqli, "UPDATE project_template_ticket_templates SET ticket_template_order = $order WHERE ticket_template_id = $ticket_template_id AND project_template_id = $project_template_id");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if (isset($_POST['add_ticket_template_to_project_template'])) {
@ -55,12 +55,12 @@ if (isset($_POST['add_ticket_template_to_project_template'])) {
mysqli_query($mysqli, "INSERT INTO project_template_ticket_templates SET project_template_id = $project_template_id, ticket_template_id = $ticket_template_id, ticket_template_order = $order");
// Logging
logAction("Project Template", "Edit", "$session_name added ticket template to project_template", 0, $project_template_id);
$_SESSION['alert_message'] = "Ticket template added";
flash_alert("Ticket template added");
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_POST['remove_ticket_template_from_project_template'])) {
@ -71,34 +71,29 @@ if (isset($_POST['remove_ticket_template_from_project_template'])) {
mysqli_query($mysqli, "DELETE FROM project_template_ticket_templates WHERE project_template_id = $project_template_id AND ticket_template_id = $ticket_template_id");
// Logging
logAction("Project Template", "Edit", "$session_name removed ticket template from project template", 0, $project_template_id);
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Ticket template removed";
flash_alert("Ticket template removed", 'error');
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['delete_project_template'])) {
$project_template_id = intval($_GET['delete_project_template']);
// Get project template name
$sql = mysqli_query($mysqli, "SELECT * FROM project_templates WHERE project_template_id = $project_template_id");
$row = mysqli_fetch_array($sql);
$project_template_name = sanitizeInput($row['project_template_name']);
$project_template_name = sanitizeInput(getFieldById('project_templates', $project_template_id, 'project_template_name'));
mysqli_query($mysqli, "DELETE FROM project_templates WHERE project_template_id = $project_template_id");
// Remove Associated Ticket Templates
mysqli_query($mysqli, "DELETE FROM project_template_ticket_templates WHERE project_template_id = $project_template_id");
// Logging
logAction("Project Template", "Delete", "$session_name deleted project template $project_template_name and its associated ticket templates and tasks");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Project Template <strong>$project_template_name</strong> and its associated ticket templates and tasks deleted";
flash_alert("Project Template <strong>$project_template_name</strong> and its associated ticket templates and tasks deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -18,12 +18,11 @@ if (isset($_POST['add_role'])) {
$role_id = mysqli_insert_id($mysqli);
// Logging
logAction("User Role", "Create", "$session_name created user role $name", 0, $role_id);
$_SESSION['alert_message'] = "User Role <strong$name</strong> created";
flash_alert("User Role <strong$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -31,8 +30,7 @@ if (isset($_POST['edit_role'])) {
validateCSRFToken($_POST['csrf_token']);
// Update role metadata
$role_id = sanitizeInput($_POST['role_id']);
$role_id = intval($_POST['role_id']);
$name = sanitizeInput($_POST['role_name']);
$description = sanitizeInput($_POST['role_description']);
$admin = intval($_POST['role_is_admin']);
@ -53,12 +51,12 @@ if (isset($_POST['edit_role'])) {
}
// Logging
logAction("User Role", "Edit", "$session_name edited user role $name", 0, $role_id);
$_SESSION['alert_message'] = "User Role <strong>$name</strong> edited";
flash_alert("User Role <strong>$name</strong> edited");
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_GET['archive_role'])) {
@ -71,19 +69,19 @@ if (isset($_GET['archive_role'])) {
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(user_id) FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
$role_user_count = mysqli_fetch_row($sql_role_user_count)[0];
if ($role_user_count != 0) {
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Role must not in use to archive it";
header("Location: " . $_SERVER["HTTP_REFERER"]);
exit();
flash_alert("Role must not in use to archive it", 'error');
redirect();
}
mysqli_query($mysqli, "UPDATE user_roles SET role_archived_at = NOW() WHERE role_id = $role_id");
// Logging
$role_details = mysqli_fetch_array(mysqli_query($mysqli, "SELECT role_name FROM user_roles WHERE role_id = $role_id LIMIT 1"));
$role_name = sanitizeInput($role_details['role_name']);
$role_name = sanitizeInput(getFieldById('roles', $role_id, 'role_name'));
logAction("User Role", "Archive", "$session_name archived user role $role_name", 0, $role_id);
$_SESSION['alert_message'] = "User Role archived";
header("Location: " . $_SERVER["HTTP_REFERER"]);
flash_alert("User Role <strong>$role_name</strong> archived", 'error');
redirect();
}

View File

@ -0,0 +1,70 @@
<?php
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_GET['delete_saved_payment'])) {
validateCSRFToken($_GET['csrf_token']);
$saved_payment_id = intval($_GET['delete_saved_payment']);
$sql = mysqli_query($mysqli, "
SELECT
client_saved_payment_methods.saved_payment_id,
client_saved_payment_methods.saved_payment_client_id,
client_saved_payment_methods.saved_payment_provider_id,
client_saved_payment_methods.saved_payment_provider_method,
client_saved_payment_methods.saved_payment_description,
client_payment_provider.payment_provider_client,
payment_providers.payment_provider_name,
payment_providers.payment_provider_private_key
FROM client_saved_payment_methods
LEFT JOIN client_payment_provider
ON client_payment_provider.client_id = client_saved_payment_methods.saved_payment_client_id
AND client_payment_provider.payment_provider_id = client_saved_payment_methods.saved_payment_provider_id
LEFT JOIN payment_providers
ON payment_providers.payment_provider_id = client_saved_payment_methods.saved_payment_provider_id
WHERE client_saved_payment_methods.saved_payment_id = $saved_payment_id"
);
$row = mysqli_fetch_array($sql);
$client_id = intval($row['saved_payment_client_id']);
$provider_id = intval($row['saved_payment_provider_id']);
$payment_provider_name = nullable_htmlentities($row['payment_provider_name']);
$saved_payment_description = nullable_htmlentities($row['saved_payment_description']);
$provider_client = nullable_htmlentities($row['payment_provider_client']);
$payment_method = $row['saved_payment_provider_method'];
$private_key = $row['payment_provider_private_key'];
// Seperate logic for each Payment Provider
if ($payment_provider_name == 'Stripe') {
try {
// Initialize stripe
require_once 'plugins/stripe-php/init.php';
$stripe = new \Stripe\StripeClient($private_key);
// Detach PM
$stripe->paymentMethods->detach($payment_method, []);
} catch (Exception $e) {
$error = $e->getMessage();
error_log("Stripe payment error - encountered exception when removing payment method info for $payment_method: $error");
logApp("Stripe", "error", "Exception removing payment method for $payment_method: $error");
}
}
// Remove payment method from ITFlow
mysqli_query($mysqli, "DELETE FROM client_saved_payment_methods WHERE saved_payment_id = $saved_payment_id");
// SQL Cascade delete will Remove All Associated Auto Payment Methods on recurring invoices in the recurring payments table.
logAction("Payment Provider", "Update", "$session_name deleted saved payment method $saved_payment_description (PM: $payment_method)", $client_id);
flash_alert("Payment method <strong>$saved_payment_description</strong> removed", 'error');
redirect();
}

View File

@ -18,11 +18,10 @@ if (isset($_POST['edit_ai_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_ai_enable = $ai_enable, config_ai_provider = '$provider', config_ai_model = '$model', config_ai_url = '$url', config_ai_api_key = '$api_key' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited AI settings");
$_SESSION['alert_message'] = "AI Settings updated";
flash_alert("AI Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -28,13 +28,13 @@ if (isset($_POST['edit_company'])) {
$file_tmp_path = $_FILES['file']['tmp_name'];
// directory in which the uploaded file will be moved
$upload_file_dir = "uploads/settings/";
$upload_file_dir = "../uploads/settings/";
$dest_path = $upload_file_dir . $new_file_name;
move_uploaded_file($file_tmp_path, $dest_path);
// Delete old file
unlink("uploads/settings/$existing_file_name");
unlink("../uploads/settings/$existing_file_name");
// Set Logo
mysqli_query($mysqli,"UPDATE companies SET company_logo = '$new_file_name' WHERE company_id = 1");
@ -44,12 +44,11 @@ if (isset($_POST['edit_company'])) {
mysqli_query($mysqli,"UPDATE companies SET company_name = '$name', company_address = '$address', company_city = '$city', company_state = '$state', company_zip = '$zip', company_country = '$country', company_phone_country_code = '$phone_country_code', company_phone = '$phone', company_email = '$email', company_website = '$website', company_tax_id = '$tax_id' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited company details");
$_SESSION['alert_message'] = "Company <strong>$name</strong> edited";
flash_alert("Company <strong>$name</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -59,14 +58,14 @@ if (isset($_GET['remove_company_logo'])) {
$row = mysqli_fetch_array($sql);
$company_logo = $row['company_logo']; // FileSystem Operation Logo is already sanitized
unlink("uploads/settings/$company_logo");
unlink("../uploads/settings/$company_logo");
mysqli_query($mysqli,"UPDATE companies SET company_logo = NULL WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name deleted company logo");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Removed company logo";
flash_alert("Removed company logo", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -19,10 +19,10 @@ if (isset($_POST['edit_default_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_start_page = '$start_page', config_default_expense_account = $expense_account, config_default_payment_account = $payment_account, config_default_payment_method = '$payment_method', config_default_expense_payment_method = '$expense_payment_method', config_default_transfer_from_account = $transfer_from_account, config_default_transfer_to_account = $transfer_to_account, config_default_calendar = $calendar, config_default_net_terms = $net_terms, config_default_hourly_rate = $hourly_rate WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited default settings");
$_SESSION['alert_message'] = "Default settings edited";
flash_alert("Default settings edited");
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}

View File

@ -21,11 +21,10 @@ if (isset($_POST['edit_invoice_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_invoice_prefix = '$config_invoice_prefix', config_invoice_next_number = $config_invoice_next_number, config_invoice_footer = '$config_invoice_footer', config_invoice_show_tax_id = $config_invoice_show_tax_id, config_invoice_late_fee_enable = $config_invoice_late_fee_enable, config_invoice_late_fee_percent = $config_invoice_late_fee_percent, config_invoice_paid_notification_email = '$config_invoice_paid_notification_email', config_recurring_invoice_prefix = '$config_recurring_invoice_prefix', config_recurring_invoice_next_number = $config_recurring_invoice_next_number WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited invoice settings");
$_SESSION['alert_message'] = "Invoice Settings edited";
flash_alert("Invoice Settings edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -14,11 +14,10 @@ if (isset($_POST['edit_localization'])) {
mysqli_query($mysqli,"UPDATE settings SET config_timezone = '$timezone' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited localization settings");
$_SESSION['alert_message'] = "Company localization updated";
flash_alert("Company localization updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -14,12 +14,11 @@ if (isset($_POST['edit_mail_smtp_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_smtp_host = '$config_smtp_host', config_smtp_port = $config_smtp_port, config_smtp_encryption = '$config_smtp_encryption', config_smtp_username = '$config_smtp_username', config_smtp_password = '$config_smtp_password' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited SMTP mail settings");
$_SESSION['alert_message'] = "SMTP Mail Settings updated";
flash_alert("SMTP Mail Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -35,13 +34,11 @@ if (isset($_POST['edit_mail_imap_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_imap_host = '$config_imap_host', config_imap_port = $config_imap_port, config_imap_encryption = '$config_imap_encryption', config_imap_username = '$config_imap_username', config_imap_password = '$config_imap_password' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited IMAP mail settings");
$_SESSION['alert_message'] = "IMAP Mail Settings updated";
flash_alert("IMAP Mail Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -63,12 +60,11 @@ if (isset($_POST['edit_mail_from_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_mail_from_email = '$config_mail_from_email', config_mail_from_name = '$config_mail_from_name', config_invoice_from_email = '$config_invoice_from_email', config_invoice_from_name = '$config_invoice_from_name', config_quote_from_email = '$config_quote_from_email', config_quote_from_name = '$config_quote_from_name', config_ticket_from_email = '$config_ticket_from_email', config_ticket_from_name = '$config_ticket_from_name' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited mail from settings");
$_SESSION['alert_message'] = "Mail From Settings updated";
flash_alert("Mail From Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -77,6 +73,7 @@ if (isset($_POST['test_email_smtp'])) {
validateCSRFToken($_POST['csrf_token']);
$test_email = intval($_POST['test_email']);
if($test_email == 1) {
$email_from = sanitizeInput($config_mail_from_email);
$email_from_name = sanitizeInput($config_mail_from_name);
@ -105,54 +102,41 @@ if (isset($_POST['test_email_smtp'])) {
'body' => $body
]
];
$mail = addToMailQueue($data);
if ($mail === true) {
$_SESSION['alert_message'] = "Test email queued! <a class='text-bold text-light' href='admin_mail_queue.php'>Check Admin > Mail queue</a>";
flash_alert("Test email queued! <a class='text-bold text-light' href='admin_mail_queue.php'>Check Admin > Mail queue</a>");
} else {
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Failed to add test mail to queue";
flash_alert("Failed to add test mail to queue", 'error');
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
// Test IMAP
// Autoload Composer dependencies
// require_once __DIR__ . '/../plugins/php-imap/vendor/autoload.php';
// Webklex PHP-IMAP
//use Webklex\PHPIMAP\ClientManager;
if (isset($_POST['test_email_imap'])) {
/*
validateCSRFToken($_POST['csrf_token']);
validateCSRFToken($_POST['csrf_token']);
try {
// Initialize the client manager and create the client
$clientManager = new ClientManager();
$client = $clientManager->make([
'host' => $config_imap_host,
'port' => $config_imap_port,
'encryption' => $config_imap_encryption,
'validate_cert' => true,
'username' => $config_imap_username,
'password' => $config_imap_password,
'protocol' => 'imap'
]);
// Setup your IMAP connection parameters
$hostname = "{" . $config_imap_host . ":" . $config_imap_port . "/" . $config_imap_encryption . "/novalidate-cert}INBOX";
$username = $config_imap_username;
$password = $config_imap_password;
// Connect to the IMAP server
$client->connect();
try {
$inbox = @imap_open($hostname, $username, $password);
$_SESSION['alert_message'] = "Connected successfully";
} catch (Exception $e) {
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Test IMAP connection failed: " . $e->getMessage();
if ($inbox) {
imap_close($inbox);
flash_alert("Connected successfully");
} else {
throw new Exception(imap_last_error());
}
*/
$_SESSION['alert_message'] = "Test is Work In Progress";
} catch (Exception $e) {
flash_alert("<strong>IMAP connection failed:</strong> " . $e->getMessage(), 'error');
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -19,11 +19,10 @@ if (isset($_POST['edit_module_settings'])) {
mysqli_query($mysqli, "UPDATE settings SET config_whitelabel_enabled = 0, config_whitelabel_key = '' WHERE company_id = 1");
}
// Logging
logAction("Settings", "Edit", "$session_name edited module settings");
$_SESSION['alert_message'] = "Module Settings updated";
flash_alert("Module Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -14,11 +14,10 @@ if (isset($_POST['edit_notification_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_send_invoice_reminders = $config_send_invoice_reminders, config_recurring_auto_send_invoice = $config_recurring_auto_send_invoice, config_enable_cron = $config_enable_cron, config_enable_alert_domain_expire = $config_enable_alert_domain_expire, config_ticket_client_general_notifications = $config_ticket_client_general_notifications WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited notification settings");
$_SESSION['alert_message'] = "Notification Settings updated";
flash_alert("Notification Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -17,15 +17,14 @@ if (isset($_POST['edit_online_payment_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_stripe_enable = $config_stripe_enable, config_stripe_publishable = '$config_stripe_publishable', config_stripe_secret = '$config_stripe_secret', config_stripe_account = $config_stripe_account, config_stripe_expense_vendor = $config_stripe_expense_vendor, config_stripe_expense_category = $config_stripe_expense_category, config_stripe_percentage_fee = $config_stripe_percentage_fee, config_stripe_flat_fee = $config_stripe_flat_fee WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited online payment settings");
if ($config_stripe_enable && $config_stripe_account == 0) {
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Stripe payment account must be specified!";
flash_alert("Stripe payment account must be specified!", 'error');
} else {
$_SESSION['alert_message'] = "Online Payment Settings updated";
flash_alert("Online Payment Settings updated");
}
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -3,12 +3,12 @@
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_GET['stripe_remove_pm'])) {
validateCSRFToken($_GET['csrf_token']);
if (!$config_stripe_enable) {
$_SESSION['alert_message'] = "Stripe not enabled";
header("Location: " . $_SERVER["HTTP_REFERER"]);
exit();
flash_alert("Stripe not enabled", 'error');
redirect();
}
$client_id = intval($_GET['client_id']);
@ -16,7 +16,7 @@ if (isset($_GET['stripe_remove_pm'])) {
try {
// Initialize stripe
require_once 'plugins/stripe-php/init.php';
require_once '../plugins/stripe-php/init.php';
$stripe = new \Stripe\StripeClient($config_stripe_secret);
// Detach PM
@ -39,14 +39,16 @@ if (isset($_GET['stripe_remove_pm'])) {
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_name deleted saved Stripe payment method (PM: $payment_method)", $client_id);
$_SESSION['alert_message'] = "Payment method removed";
header("Location: " . $_SERVER["HTTP_REFERER"]);
flash_alert("Payment method removed", 'error');
redirect();
}
if (isset($_GET['stripe_reset_customer'])) {
validateCSRFToken($_GET['csrf_token']);
$client_id = intval($_GET['client_id']);
@ -62,9 +64,10 @@ if (isset($_GET['stripe_reset_customer'])) {
mysqli_query($mysqli, "DELETE FROM recurring_payments WHERE recurring_payment_method = 'Stripe' AND recurring_payment_recurring_invoice_id = $recurring_invoice_id");
}
// Logging
logAction("Stripe", "Delete", "$session_name reset Stripe settings for client", $client_id);
$_SESSION['alert_message'] = "Reset client Stripe settings";
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
flash_alert("Reset client Stripe settings", 'error');
redirect();
}

View File

@ -11,11 +11,10 @@ if (isset($_POST['edit_project_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_project_prefix = '$config_project_prefix', config_project_next_number = $config_project_next_number WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited project settings");
$_SESSION['alert_message'] = "Project Settings updated";
flash_alert("Project Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -16,11 +16,10 @@ if (isset($_POST['edit_quote_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_quote_prefix = '$config_quote_prefix', config_quote_next_number = $config_quote_next_number, config_quote_footer = '$config_quote_footer', config_quote_notification_email = '$config_quote_notification_email' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited Quote settings");
$_SESSION['alert_message'] = "Quote Settings updated";
flash_alert("Quote Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -19,10 +19,10 @@ if (isset($_POST['edit_security_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_login_message = '$config_login_message', config_login_key_required = '$config_login_key_required', config_login_key_secret = '$config_login_key_secret', config_login_remember_me_expire = $config_login_remember_me_expire, config_log_retention = $config_log_retention WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited security settings");
$_SESSION['alert_message'] = "Security settings updated";
flash_alert("Security settings updated");
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}

View File

@ -10,11 +10,10 @@ if (isset($_POST['edit_telemetry_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_telemetry = $config_telemetry WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited telemetry settings");
$_SESSION['alert_message'] = "Telemetry Settings updated";
flash_alert("Telemetry Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -10,12 +10,12 @@ if (isset($_POST['edit_theme_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_theme = '$theme' WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited theme settings");
logAction("Settings", "Edit", "$session_name edited theme settings $dark_mode");
$_SESSION['alert_message'] = "Changed theme to <strong>$theme</strong>";
flash_alert("Changed theme to <strong>$theme</strong>");
redirect();
header("Location: " . $_SERVER["HTTP_REFERER"]);
}
if (isset($_POST['edit_favicon_settings'])) {
@ -28,12 +28,12 @@ if (isset($_POST['edit_favicon_settings'])) {
$file_tmp_path = $_FILES['file']['tmp_name'];
// Delete old file
if(file_exists("uploads/favicon.ico")) {
unlink("uploads/favicon.ico");
if(file_exists("../uploads/favicon.ico")) {
unlink("../uploads/favicon.ico");
}
// directory in which the uploaded file will be moved
$upload_file_dir = "uploads/";
$upload_file_dir = "../uploads/";
//Force File Name
$new_file_name = "favicon.ico";
$dest_path = $upload_file_dir . $new_file_name;
@ -42,11 +42,10 @@ if (isset($_POST['edit_favicon_settings'])) {
}
}
// Logging
logAction("Settings", "Edit", "$session_name changed the favicon");
$_SESSION['alert_message'] = "Favicon Updated";
flash_alert("Favicon Updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -21,11 +21,10 @@ if (isset($_POST['edit_ticket_settings'])) {
mysqli_query($mysqli,"UPDATE settings SET config_ticket_prefix = '$config_ticket_prefix', config_ticket_next_number = $config_ticket_next_number, config_ticket_email_parse = $config_ticket_email_parse, config_ticket_email_parse_unknown_senders = $config_ticket_email_parse_unknown_senders, config_ticket_autoclose_hours = $config_ticket_autoclose_hours, config_ticket_new_ticket_notification_email = '$config_ticket_new_ticket_notification_email', config_ticket_default_billable = $config_ticket_default_billable, config_ticket_default_view = $config_ticket_default_view, config_ticket_moving_columns = $config_ticket_moving_columns, config_ticket_ordering = $config_ticket_ordering, config_ticket_timer_autostart = $config_ticket_timer_autostart WHERE company_id = 1");
// Logging
logAction("Settings", "Edit", "$session_name edited ticket settings");
$_SESSION['alert_message'] = "Ticket Settings updated";
flash_alert("Ticket Settings updated");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
}

View File

@ -17,12 +17,11 @@ if (isset($_POST['add_software_template'])) {
$software_template_id = mysqli_insert_id($mysqli);
// Logging
logAction("Software Template", "Create", "$session_name created software template $name", 0, $software_template_id);
$_SESSION['alert_message'] = "Software template <strong>$name</strong> created";
flash_alert("Software template <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -38,12 +37,11 @@ if (isset($_POST['edit_software_template'])) {
mysqli_query($mysqli,"UPDATE software_templates SET software_template_name = '$name', software_template_version = '$version', software_template_description = '$description', software_template_type = '$type', software_template_license_type = '$license_type', software_template_notes = '$notes' WHERE software_template_id = $software_template_id");
// Logging
logAction("Software Template", "Edit", "$session_name edited software template $name", 0, $software_template_id);
$_SESSION['alert_message'] = "Software template <strong>$name</strong> edited";
flash_alert("Software template <strong>$name</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
@ -58,12 +56,10 @@ if (isset($_GET['delete_software_template'])) {
mysqli_query($mysqli,"DELETE FROM software_templates WHERE software_template_id = $software_template_id");
//Logging
logAction("Software Template", "Delete", "$session_name deleted software template $software_template_name");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Software Template <strong>$software_template_name</strong> deleted";
flash_alert("Software Template <strong>$software_template_name</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

View File

@ -8,54 +8,48 @@ defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
if (isset($_POST['add_tag'])) {
require_once 'post/admin/admin_tag_model.php';
require_once 'tag_model.php';
mysqli_query($mysqli,"INSERT INTO tags SET tag_name = '$name', tag_type = $type, tag_color = '$color', tag_icon = '$icon'");
$tag_id = mysqli_insert_id($mysqli);
// Logging
logAction("Tag", "Create", "$session_name created tag $name", 0, $tag_id);
$_SESSION['alert_message'] = "Tag <strong>$name</strong> created";
flash_alert("Tag <strong>$name</strong> created");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if (isset($_POST['edit_tag'])) {
require_once 'post/admin/admin_tag_model.php';
require_once 'post/tag_model.php';
$tag_id = intval($_POST['tag_id']);
mysqli_query($mysqli,"UPDATE tags SET tag_name = '$name', tag_type = $type, tag_color = '$color', tag_icon = '$icon' WHERE tag_id = $tag_id");
// Logging
logAction("Tag", "Edit", "$session_name edited tag $name", 0, $tag_id);
$_SESSION['alert_message'] = "Tag <strong>$name</strong> edited";
flash_alert("Tag <strong>$name</strong> edited");
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}
if (isset($_GET['delete_tag'])) {
$tag_id = intval($_GET['delete_tag']);
// Get Tag Name for logging
$sql = mysqli_query($mysqli,"SELECT tag_name FROM tags WHERE tag_id = $tag_id");
$row = mysqli_fetch_array($sql);
$tag_name = sanitizeInput($row['tag_name']);
$tag_name = sanitizeInput(getFieldById('tags', $tag_id, 'tag_name'));
mysqli_query($mysqli,"DELETE FROM tags WHERE tag_id = $tag_id");
// Logging
logAction("Tag", "Delete", "$session_name deleted tag $tag_name");
$_SESSION['alert_type'] = "error";
$_SESSION['alert_message'] = "Tag <strong>$tag_name</strong> deleted";
flash_alert("Tag <strong>$tag_name</strong> deleted", 'error');
header("Location: " . $_SERVER["HTTP_REFERER"]);
redirect();
}

Some files were not shown because too many files have changed in this diff Show More