mirror of
https://github.com/itflow-org/itflow
synced 2026-03-11 00:04:50 +00:00
Compare commits
275 Commits
v25.09
...
duplicate-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
216db04d32 | ||
|
|
13b8f93e17 | ||
|
|
0347382a34 | ||
|
|
840460afe7 | ||
|
|
c851e54e1d | ||
|
|
5ef53b569c | ||
|
|
698b4166e8 | ||
|
|
1a9a36829b | ||
|
|
155b8598ff | ||
|
|
4153c91f84 | ||
|
|
a99b19a1b5 | ||
|
|
18429fda2c | ||
|
|
435da991ec | ||
|
|
ebd9aae924 | ||
|
|
414a84d5ec | ||
|
|
a3b2517603 | ||
|
|
43535082f6 | ||
|
|
e73af9980e | ||
|
|
0bdd5784ee | ||
|
|
48719ce29c | ||
|
|
29839d3b23 | ||
|
|
185ea7d6ac | ||
|
|
ac7623d4f5 | ||
|
|
3d119261cc | ||
|
|
169619c9b9 | ||
|
|
b991f787a2 | ||
|
|
215fc6803e | ||
|
|
a79c1c8246 | ||
|
|
1aa6419b1b | ||
|
|
02694f6720 | ||
|
|
f50aabb570 | ||
|
|
19b8d09bfd | ||
|
|
66fb999a8c | ||
|
|
0c5883b61b | ||
|
|
ef66d5172c | ||
|
|
118f9a34d8 | ||
|
|
b61dfac569 | ||
|
|
79160f9b5c | ||
|
|
d2523cff4a | ||
|
|
1839599769 | ||
|
|
29e1b56e78 | ||
|
|
47e647c712 | ||
|
|
a87b0b0447 | ||
|
|
96b8fcad3a | ||
|
|
cf0fa0024c | ||
|
|
aba5ed9271 | ||
|
|
63141f3578 | ||
|
|
612041635d | ||
|
|
efcc0fd5cb | ||
|
|
b0724f5b66 | ||
|
|
66a2b4b6d2 | ||
|
|
77b4dfa50a | ||
|
|
1e6e7fd6d8 | ||
|
|
46a1b673ba | ||
|
|
7230325e62 | ||
|
|
af8e733cfb | ||
|
|
26ab43c57f | ||
|
|
15ed4ef1ce | ||
|
|
0ac76766bd | ||
|
|
abb97ad99f | ||
|
|
6cdc26b55b | ||
|
|
9f19fd3c75 | ||
|
|
61dedb7e7b | ||
|
|
65d2b8b2cb | ||
|
|
1d3f206660 | ||
|
|
ab46899e72 | ||
|
|
723a423b06 | ||
|
|
a837b97870 | ||
|
|
8be0789f25 | ||
|
|
99d017144d | ||
|
|
891f71006b | ||
|
|
d25017216a | ||
|
|
83b7c7b054 | ||
|
|
283c2a17df | ||
|
|
44de049f3b | ||
|
|
920d08f039 | ||
|
|
0cf1e338c2 | ||
|
|
293a2b800e | ||
|
|
650a099e19 | ||
|
|
46c2c8616e | ||
|
|
6295a5c878 | ||
|
|
39d8e19e16 | ||
|
|
9d3a44d110 | ||
|
|
54d46719c2 | ||
|
|
dbed2c17db | ||
|
|
f772ef2efd | ||
|
|
2f28f96f8d | ||
|
|
1f2bcf7c34 | ||
|
|
a9a5850fd4 | ||
|
|
09f3bfd8f4 | ||
|
|
3813fbf8f2 | ||
|
|
16001f8d4e | ||
|
|
49d3dbad9a | ||
|
|
56f32a4da2 | ||
|
|
a297b8d6d8 | ||
|
|
d365f48192 | ||
|
|
df6d955261 | ||
|
|
9fcaf9f5cc | ||
|
|
43a7b7faa5 | ||
|
|
69253385c5 | ||
|
|
cea7d61481 | ||
|
|
41f9a2e6e2 | ||
|
|
31d3659098 | ||
|
|
c12bfb157e | ||
|
|
a55dabb1cd | ||
|
|
06fec3c280 | ||
|
|
f733a27ad7 | ||
|
|
7ea39eb545 | ||
|
|
a85f898ef5 | ||
|
|
519975f3cf | ||
|
|
0e9a071e96 | ||
|
|
3917e66fd8 | ||
|
|
9f48e2d9f0 | ||
|
|
215eadcf2b | ||
|
|
b09e4938b7 | ||
|
|
d3d706ea68 | ||
|
|
8268761ef4 | ||
|
|
2850c35bdc | ||
|
|
24d8635dac | ||
|
|
8314a115bb | ||
|
|
b8e2423dbd | ||
|
|
52c67f4139 | ||
|
|
e895156d03 | ||
|
|
89abc18465 | ||
|
|
355dfbbb25 | ||
|
|
6d15640ae4 | ||
|
|
ad4ab5a54c | ||
|
|
3c5c86c4c5 | ||
|
|
09b91c8826 | ||
|
|
13ea48bff8 | ||
|
|
26bb430d6e | ||
|
|
82da54740f | ||
|
|
e02b10d12a | ||
|
|
1573045157 | ||
|
|
bf31c333a6 | ||
|
|
4229bca978 | ||
|
|
13bd929755 | ||
|
|
7f6c0346af | ||
|
|
0387e66066 | ||
|
|
04bae8dc37 | ||
|
|
559506fc90 | ||
|
|
f2b6d481a1 | ||
|
|
c66aa92365 | ||
|
|
e24ef68d8d | ||
|
|
0cacf83ae5 | ||
|
|
2dc66b329b | ||
|
|
10dc8ea2bf | ||
|
|
303f9174c9 | ||
|
|
c5dd5f2b6f | ||
|
|
ab77705ca2 | ||
|
|
10c89ebf73 | ||
|
|
ecce994921 | ||
|
|
5dd4f5ea62 | ||
|
|
93bb5db019 | ||
|
|
65ff008ccf | ||
|
|
f0c48d23fe | ||
|
|
975b52a43d | ||
|
|
079b0d5024 | ||
|
|
99ccb12b8c | ||
|
|
0bb7d24e07 | ||
|
|
b7a9f9ea38 | ||
|
|
21aee98f9f | ||
|
|
9a5a4be64a | ||
|
|
db7f8501d0 | ||
|
|
61d15cbf9e | ||
|
|
39c9c695f1 | ||
|
|
d97654581b | ||
|
|
2ee70fd3a8 | ||
|
|
b336ec4188 | ||
|
|
c77e1be1c3 | ||
|
|
986f688468 | ||
|
|
1d9429b762 | ||
|
|
d122d90a47 | ||
|
|
2c534d4d20 | ||
|
|
b7e0e5c5eb | ||
|
|
2915b12181 | ||
|
|
ed589ef65b | ||
|
|
0d5bfdafdf | ||
|
|
fbf3346052 | ||
|
|
3ff206f84d | ||
|
|
a3b0fce961 | ||
|
|
8130280b35 | ||
|
|
fea3020d9a | ||
|
|
1eb9d163fa | ||
|
|
e3e7c2e38b | ||
|
|
27e1d6a9cd | ||
|
|
2ec4cdc4fb | ||
|
|
35a7506c26 | ||
|
|
16242be74e | ||
|
|
3fcbe440d3 | ||
|
|
4ef0755039 | ||
|
|
a4ed906dd1 | ||
|
|
416a8d9a94 | ||
|
|
d8803aaac2 | ||
|
|
01f6615ca0 | ||
|
|
fd93ee3263 | ||
|
|
32bfd298a1 | ||
|
|
5de2e7a3bd | ||
|
|
6e8c133a99 | ||
|
|
956f18430b | ||
|
|
76c9933baf | ||
|
|
6c6a988c2b | ||
|
|
d829e39b66 | ||
|
|
0e401df3c0 | ||
|
|
9072c37e95 | ||
|
|
2eff11efbf | ||
|
|
6a7a02d220 | ||
|
|
d6349bbc5c | ||
|
|
9a2f887db1 | ||
|
|
71d30ff95f | ||
|
|
3135247936 | ||
|
|
0d629221fe | ||
|
|
181ea4b487 | ||
|
|
fa769665df | ||
|
|
00f5198bed | ||
|
|
785a291614 | ||
|
|
92209c7125 | ||
|
|
690007be5c | ||
|
|
e6bcf0e12f | ||
|
|
ca6a903b8f | ||
|
|
50f790dd6c | ||
|
|
ed6aa843b7 | ||
|
|
52a27699f1 | ||
|
|
dba08714bf | ||
|
|
edabc5c33f | ||
|
|
6b6c70f1df | ||
|
|
93061eb695 | ||
|
|
1f9133c188 | ||
|
|
e7dcc6df3c | ||
|
|
fbd58b4723 | ||
|
|
e992138456 | ||
|
|
058f79d0a1 | ||
|
|
5c448c05a9 | ||
|
|
e966cd3068 | ||
|
|
6d3351b2f7 | ||
|
|
61a1d61901 | ||
|
|
4ff3231451 | ||
|
|
ce832d2805 | ||
|
|
b11730303e | ||
|
|
565f9ab314 | ||
|
|
9435434cf9 | ||
|
|
a58ca6f66d | ||
|
|
c769bbc405 | ||
|
|
0379143829 | ||
|
|
ee235cf231 | ||
|
|
04b29d43df | ||
|
|
dc0715da57 | ||
|
|
902323a75b | ||
|
|
3a5b18f3dd | ||
|
|
ce7d84aa2f | ||
|
|
981fb9585d | ||
|
|
23b2dcba70 | ||
|
|
e4a437f54c | ||
|
|
d4167f9595 | ||
|
|
88475a2b76 | ||
|
|
c26ce4b7dc | ||
|
|
5960e7cbd9 | ||
|
|
68872ab9fb | ||
|
|
64f12b42b8 | ||
|
|
8c0d542d7d | ||
|
|
c016b67c3a | ||
|
|
49d127e957 | ||
|
|
e7353c4757 | ||
|
|
3106685972 | ||
|
|
2b7017fae2 | ||
|
|
da0b01e23f | ||
|
|
d450ea4beb | ||
|
|
9210734911 | ||
|
|
ebae80bb7e | ||
|
|
dcade3a5c7 | ||
|
|
f51c3e9e3f | ||
|
|
b34298e45b | ||
|
|
9fa78897bc | ||
|
|
9642babb7e | ||
|
|
d2d1aed393 |
29
.gitignore
vendored
29
.gitignore
vendored
@@ -4,8 +4,16 @@ config.php
|
||||
uploads/favicon.ico
|
||||
uploads/clients/*
|
||||
!uploads/clients/index.php
|
||||
uploads/custom/*
|
||||
!uploads/custom/index.php
|
||||
uploads/documents/*
|
||||
!uploads/documents/index.php
|
||||
uploads/document_templates/*
|
||||
!uploads/document_templates/index.php
|
||||
uploads/expenses/*
|
||||
!uploads/expenses/index.php
|
||||
uploads/recurring_tickets/*
|
||||
!uploads/recurring_tickets/index.php
|
||||
uploads/settings/*
|
||||
!uploads/settings/index.php
|
||||
uploads/users/*
|
||||
@@ -14,6 +22,8 @@ uploads/tmp/*
|
||||
!uploads/tmp/index.php
|
||||
uploads/tickets/*
|
||||
!uploads/tickets/index.php
|
||||
uploads/ticket_templates/*
|
||||
!uploads/ticket_templates/index.php
|
||||
.idea/*
|
||||
plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/HTML/*
|
||||
!plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/HTML/.gitkeep
|
||||
@@ -25,6 +35,23 @@ plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/CSS/*
|
||||
xcustom/*
|
||||
!xcustom/readme.php
|
||||
post/xcustom
|
||||
custom/*
|
||||
!post/xcustom/readme.php
|
||||
admin/custom/*
|
||||
!admin/custom/readme.php
|
||||
agent/custom/*
|
||||
!agent/custom/readme.php
|
||||
client/custom/*
|
||||
!client/custom/readme.php
|
||||
guest/custom/*
|
||||
!guest/custom/readme.php
|
||||
cron/custom/*
|
||||
!cron/custom/readme.php
|
||||
scripts/custom/*
|
||||
!scripts/custom/readme.php
|
||||
setup/custom/*
|
||||
!setup/custom/readme.php
|
||||
api/v1/custom/*
|
||||
!api/v1/custom/readme.php
|
||||
.zed
|
||||
|
||||
|
||||
|
||||
226
CHANGELOG.md
226
CHANGELOG.md
@@ -2,6 +2,232 @@
|
||||
|
||||
This file documents all notable changes made to ITFlow.
|
||||
|
||||
## [25.11.1] Maint Release
|
||||
|
||||
### Fixes
|
||||
- Fix broken edit Payment Method.
|
||||
- Fix unable to delete Vendor Template.
|
||||
- Fix Mail Queue link in flash alert for testing email and sending a quote.
|
||||
- Add Show Category Type select if not defined.
|
||||
- Add Show Product Type select if not defined.
|
||||
- Fix add ticket watcher.
|
||||
- Fix if Client isn't assigned to a ticket dont show client view.
|
||||
- Fix missing session client id check when paying an invoice from client portal.
|
||||
- Update Composer Webklex-IMAP library dependency symfony/http-foundation from 7.3.3 to 7.3.7 to fix security related issues.
|
||||
- Add back delete Payment provider the database will handle cascade deletes to saved cards, recurring payments and client payment provider reference.
|
||||
- Don't show Client Tickets Breadcrumb if no client is assigned to a ticket.
|
||||
- Don't Show Contact or Assignment Tab in edit ticket if no Client is Assigned.
|
||||
- Don't Show add contact, asset, vendor, watcher if not client is assigned to a ticket.
|
||||
- Don't Show Public Comment & Email if contact email doesn't exist.
|
||||
- Fixed IMAP Test whicn now uses RAW TCP Connection instead of the depracated php-imap extension.
|
||||
- Fix Broken Link in Ticket Updates via Client Portal to agent.
|
||||
|
||||
### Added / Changed
|
||||
- [Feature] Added Asset Tags.
|
||||
- [Feature] Added Quick Add Links to most side bar navs example quickly add a client from sidebar.
|
||||
- Migrate ticket template add to ajax modal.
|
||||
- Add TOTP secret to Client Export PDF in Credential section.
|
||||
- Add UserID on hover in users listing.
|
||||
- Merge ticket now redirects to the new ticket details page.
|
||||
- [Feature] Add Pay via saved card under invoice Listings.
|
||||
- Ticket Related Side Items UI Cleanup to use btn-tool class.
|
||||
|
||||
## [25.11] Stable
|
||||
|
||||
### Deprecation Notice:
|
||||
- **Outdated CRON Scripts**: The following scripts are removed.
|
||||
- `/scripts/cron_mail_queue.php`
|
||||
- `/scripts/cron_ticket_email_parser.php`
|
||||
- `/scripts/cron.php`
|
||||
- `/scripts/cron_domain_refresher.php`
|
||||
- `/scripts/cron_certificate_refresher.php`
|
||||
|
||||
**Action Required**: Transition to the new versions:
|
||||
- `/cron/mail_queue.php`
|
||||
- `/cron/ticket_email_parser.php`
|
||||
- `/cron/cron.php`
|
||||
- `/cron/domain_refresher.php`
|
||||
- `/cron/certificate_refresher.php`
|
||||
|
||||
- PHP Extensions php-imap and php-mime-mail-parser are no longer required.
|
||||
---
|
||||
|
||||
### Fixes
|
||||
- **Ticket Listing**: Resolved issue where the “Check All” checkbox was visible even when ticket status wasn’t set. Now hidden for closed tickets only.
|
||||
- **Timer Auto-Start**: Show H/M/S placeholders when timer auto-start is disabled.
|
||||
- **Ticket Guest URL**: Fixed email not including the ticket guest URL key.
|
||||
- **EML Generation**: Resolved issue with EML not being generated in the new ticket parser.
|
||||
- **New Ticket Mail Notification**: Included message when notifying the tech of a reply in the new ticket mail parser.
|
||||
- **Advanced Filter Collapse**: Added clause to prevent collapse of advanced filters when the “from” date is set to the default (1970-01-01).
|
||||
- **Recurring Invoice**: Fixed issue where email was marked as sent but not actually sent when forcing a recurring invoice to an invoice.
|
||||
- **CSRF Token**: Fixed issue with deleting recurring ticket from asset details page due to missing CSRF check token.
|
||||
- **Vendor Website Link**: Fixed missing `https://` prefix in the vendor website link on the vendor details modal.
|
||||
- **Agent Select Box**: Resolved issue where agents sometimes didn’t appear in the agent select boxes.
|
||||
- **TinyMCE**: Fixed TinyMCE editor issue on Bulk Create Ticket in Assets.
|
||||
- **Ticket Timer**: Fixed ticket timer initialization after reload and when the tab is put to sleep (background tab).
|
||||
- **Client Deletion**: Fixed issue with client deletion.
|
||||
- **Domain Records**: Added flag for missing SOA record when adding a domain (prevents subdomain creation).
|
||||
- **Domain Fetching**: Quits domain record fetching if no SOA record exists (prevents subdomains).
|
||||
- **Domain Expiry**: Only show time to expiry when there’s an expiry date set; otherwise, display a dash.
|
||||
- **Certificates**: Improved handling of empty date in the agent UI.
|
||||
- **Certificates API**: Fixed bug with missing JS to fetch certificate details.
|
||||
- **API Updates**:
|
||||
- Clients API: Added support for archiving/un-archiving clients, updating client data, and abbreviation support.
|
||||
- Contacts API: Added archiving/un-archiving and restriction to only allow one primary contact per client.
|
||||
- Mail Queue: Added recipient domain MX validation before sending emails.
|
||||
|
||||
---
|
||||
|
||||
### Added / Changed
|
||||
- **Backup / Restore**: Improved backup and restore by streaming data to disk (to prevent memory issues), setting unlimited timeouts, checking for bad backup contents, and using PHP for DB import instead of shell exec. Added `.htaccess` to prevent PHP execution in `/uploads/` directory.
|
||||
- **Ajax Modals**: Migrated all Add and Bulk modals to the new Ajax Modal for improved performance.
|
||||
- **Recurring Ticket Sorting**: Default sorting of recurring tickets by `RunDate` instead of subject.
|
||||
- **Recurring Ticket Enhancements**:
|
||||
- Added Billable column.
|
||||
- Added bulk actions for setting priority, agent, billable status, and next run dates.
|
||||
- Added filters for category, assigned agent, and billable status.
|
||||
- Added new frequency options: 3-day and biweekly.
|
||||
- **Asset Select**: Updated asset select dropdown to separate asset types using opt groups (planned for wider use).
|
||||
- **Expiring Domains & Certificates**: Added "30 Day" warning for expiring domains and certificates in the dashboard.
|
||||
- **Ticket Search**: Allowed search using both ticket prefix and number.
|
||||
- **Recurring Invoice**: Cancel recurring invoices when the associated client is archived.
|
||||
- **Credentials Import/Export**: Now includes TOTP secrets when importing/exporting credentials.
|
||||
- **Asset Notes Import**: Allowed importing of asset notes.
|
||||
- **Ticket View**: Added a "View HTML Code" button in all ticket views for TinyMCE.
|
||||
- **Date Range Picker**: Updated all date filters to use the improved DateRangePicker JS.
|
||||
- **Bulk Ticket Creation**: Added bulk ticket creation for clients.
|
||||
- **Sidebar Updates**: Updated all sidebars to use absolute paths for easier integration with custom code.
|
||||
- **Document Actions**: Added Archive and Delete buttons to the Document Details view with improved redirect behavior.
|
||||
- **Ticket Template Sorting**: Allowed sorting by task count in ticket templates.
|
||||
- **Contact Modal UI**: Updated contact details modal to display contact information at the top.
|
||||
- **API & Code Updates**:
|
||||
- Separated out post files for recurring tickets, invoices, expenses, and payments.
|
||||
- Removed unused budget code.
|
||||
- **Invoice Product Autocomplete**: Now allows searching for product codes as well as names.
|
||||
- **Client Duplicate Check**: Flags duplicate clients or leads when using the client add modal.
|
||||
- **Recurring Invoice Reference**: Added a column to invoices indicating if they were created from a recurring invoice.
|
||||
- **Global Search Enhancements**:
|
||||
- Allowed ticket details to be searchable in global search.
|
||||
- Allowed searching for quotes in global search.
|
||||
- **UI/UX Improvements**:
|
||||
- Spruced up the ticket details page UI.
|
||||
- Added contact email validation to flag duplicates or invalid addresses.
|
||||
- **API Debugging**: Log API endpoint/URL path for authentication failures to aid in debugging.
|
||||
- **Image Upload Optimization**: Removed image optimization from uploads (this will be handled by a cron job in the future).
|
||||
- **View Behavior Change**: Updated ticket/invoice/quote views to always be in the Client section, showing client-side navigation and top info bar.
|
||||
|
||||
---
|
||||
|
||||
### Library Updates:
|
||||
- **DataTable**: Bumped from 2.3.3 to 2.3.4.
|
||||
- **TinyMCE**: Bumped from 8.0.2 to 8.2.0.
|
||||
- **Stripe-PHP**: Bumped from 17.6.0 to 18.1.0.
|
||||
- **PHPMailer**: Bumped from 6.10.0 to 7.0.0.
|
||||
- **Chart.js**: Bumped from 4.5.0 to 4.5.1.
|
||||
|
||||
|
||||
|
||||
|
||||
## [25.10.1]
|
||||
- Deprecation Notice: `/scripts/cron_mail_queue.php` , `/scripts/cron_ticket_email_parser.php` , `/scripts/cron.php` `/scripts/cron_domain_refresher.php`, `/scripts/cron_certificate_refresher.php` are being phased out. Please transition to `/cron/mail_queue.php` , `/cron/ticket_email_parser.php`, `/cron/cron.php`, `/cron/domain_refresher.php`, `/cron/certificate_refresher.php` These older scripts will be removed in the November 25.11 release—update accordingly. 25.10.1 installs have the script already configured.
|
||||
|
||||
### Fixes
|
||||
- Fix regression missing custom Favicon.
|
||||
- Update SMTP and IMAP provider to allow for empty strings, empty means disabled.
|
||||
- Fix Client portal Microsoft SSO Logins.
|
||||
- Fix regression in Vendor Templates.
|
||||
- Fix refression in some broken links from user to agent.
|
||||
- Fix Project edit.
|
||||
- Prevent open redirects upon agent login.
|
||||
- Fix regression on switching to Webklex IMAP to allow for no SSL/TLS in IMAP.
|
||||
- Fix Setup Redirect not behaving properly when setup hasnt been performed.
|
||||
- Added Server Document Root Var to several includes, headers, footers files to allow includes from deeper directory strutures such as the new custom directories.
|
||||
- Fix edit contact in contact details.
|
||||
- Add .htaccess to /cron/.
|
||||
|
||||
### Added / Changed
|
||||
- Support for HTML Signatures.
|
||||
- Add Edit Project Functionality in a ticket.
|
||||
- Added more custom locations: /cron/custom/, /scripts/custom/, /api/v1/custom/, /setup/custom/.
|
||||
- Copied `/scripts/cron.php` `/scripts/cron_domain_refresher.php`, `/scripts/cron_certificate_refresher.php` to `/cron/cron.php`, `/cron/domain_refresher.php`, `/cron/certificate_refresher.php`. See Above!
|
||||
- Signatures is now handled in post ticket reply on Public Comments only.
|
||||
|
||||
## [25.10]
|
||||
|
||||
### Breaking Changes
|
||||
- Renamed `/user/` directory to `/agent/`.
|
||||
- Deprecation Notice: `/scripts/cron_mail_queue.php` and `/scripts/cron_ticket_email_parser.php` are being phased out. Please transition to `/cron/mail_queue.php` and `/cron/ticket_email_parser.php`. These older scripts will be removed in the November release—update accordingly. New Installs via the script will have this already configured.
|
||||
- Custom is working now. Custom code should be placed in /admin/custom/ , /agent/custom/ , /client/custom/ /guest/custom/
|
||||
We will provide example code with directory structure for each custom directory a week after this release.
|
||||
|
||||
### Fixes
|
||||
- Resolved issue with "Restore from Setup" not functioning correctly.
|
||||
- Corrected asset name display in logs and flash messages when editing an asset in a ticket.
|
||||
- Fixed Payment Provider Threshold not being applied.
|
||||
- Fixed issue where Threshold setting was not saving properly.
|
||||
- Various minor fixes for Payment Provider issues.
|
||||
- Removed leads from the client selection list in the "New Ticket" modal.
|
||||
- Fixed issues with the MFA modal.
|
||||
- Resolved MFA enforcement bugs.
|
||||
- Fixed KeepAlive functionality to maintain user sessions longer.
|
||||
- Fixed multiple broken links caused by the `/user/` to `/agent/` path migration.
|
||||
- Fixed Custom code directories.
|
||||
|
||||
### Added / Changed
|
||||
- Removed "ACH" as a payment method; added "Bank Transfer" instead.
|
||||
- Replaced relative paths with absolute paths for web assets.
|
||||
- Tickets can now be resolved via the API.
|
||||
- Added a filter for Archived Users and an option to restore them.
|
||||
- Introduced a modal when archiving users, allowing reassignment of open and recurring tickets to another agent.
|
||||
- Improved logic for determining the index/root page.
|
||||
- Added "Assigned Agent" column for recurring tickets.
|
||||
- Introduced "Additional Assets" option when editing assets in tickets; modal now uses the updated AJAX method.
|
||||
- Added Gibraltar to the list of supported countries.
|
||||
- Added Custom Link Option for the Admin Nav.
|
||||
- Added Custom Link Option for the Reports Nav.
|
||||
|
||||
### Other notes
|
||||
- Major releases will happen on the first week of every Month.
|
||||
|
||||
|
||||
## [25.09.2]
|
||||
|
||||
### Fixes
|
||||
- Fix Payment Method Select box in Revenue.
|
||||
- Remove Extra Feeback Wording When Invoice Sends.
|
||||
- Updated all CSV exports to use escape parameters.
|
||||
- Fix Missing First row on Asset interface export.
|
||||
- Fix Edit User not working due to incorrect modal footer path.
|
||||
- Fix Add Certificate breaking due spelling on function.
|
||||
- Update all CSV Exports to include company name or client name depending on when its being exported from.
|
||||
- Introduced new function sanitize_filename and implmented it in all exports.
|
||||
- Spruced up UI/UX Saved Paymented section in Client Portal.
|
||||
- Fix add Payment Link in client portal recurring invoice section.
|
||||
- Better Logic handling for default page redirect.
|
||||
|
||||
### Features
|
||||
- Introduced new Beta mail parser cron using webklex imap library instead of php-imap as this is deprecated --Not Enabled on existing installs, only new installs.
|
||||
- Introduced Beta support for OAUTH2 Authentication for Microsoft 365 and Google Workspaces for both incoming ticket parsing and outgoing email but must use new mail parser and mail queue for this to work, and requires changing the cron jobs: scripts/cron_mail_queue.php to cron/mail_queue.php and scripts/cron_ticket_email_parser.php to cron/ticket_email_parser.php.
|
||||
|
||||
---
|
||||
|
||||
## [25.09.1]
|
||||
|
||||
### Fixes
|
||||
- **Web Installer**: Resolved issue with broken installer caused by incorrect database schema file name.
|
||||
- Hide the "Add Credit" button as the feature is not fully implemented yet.
|
||||
- Corrected long invoice/quote notes that were overlapping with the footer in PDF exports.
|
||||
- Fixed AI settings not appearing in the Admin Menu when the Billing module was disabled.
|
||||
- Enabled wrapping of client tags when they are too long.
|
||||
- Fixed an issue where AI was not functioning correctly.
|
||||
- Removed extra spacing between the contact name and icon in the Ticket Details contact card.
|
||||
|
||||
### Features
|
||||
- Redesigned **AI Ticket Summary**, now divided into 3 sections: Main Issue, Actions Taken, and Resolution/Next Steps.
|
||||
- Updated the **AI Ticket Summary** prompt to include ticket status, reply author, source, category, and priority.
|
||||
|
||||
---
|
||||
|
||||
## [25.09]
|
||||
|
||||
***BACK UP*** before updating.
|
||||
|
||||
@@ -16,7 +16,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||
<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>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/ai/ai_model_add.php"><i class="fas fa-plus mr-2"></i>Add Model</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -104,5 +104,4 @@ $num_rows = mysqli_num_rows($sql);
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/ai/ai_model_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -16,7 +16,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||
<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>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/ai/ai_provider_add.php"><i class="fas fa-plus mr-2"></i>Add Provider</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -105,5 +105,4 @@ $num_rows = mysqli_num_rows($sql);
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/ai/ai_provider_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -18,159 +18,150 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-key mr-2"></i>API Keys</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addApiKeyModal"><i class="fas fa-plus mr-2"></i>Create</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-body">
|
||||
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search keys">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="btn-group float-right">
|
||||
<div class="dropdown ml-2" id="bulkActionButton" hidden>
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<button class="dropdown-item text-danger text-bold"
|
||||
type="submit" form="bulkActions" name="bulk_delete_api_keys">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Revoke
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<hr>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
|
||||
<form id="bulkActions" action="post.php" method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" onclick="checkAll(this)">
|
||||
</div>
|
||||
</td>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_name&order=<?php echo $disp; ?>">
|
||||
Name <?php if ($sort == 'api_key_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_client_id&order=<?php echo $disp; ?>">
|
||||
Client <?php if ($sort == 'api_key_client_id') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_secret&order=<?php echo $disp; ?>">
|
||||
Secret <?php if ($sort == 'api_key_secret') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_created_at&order=<?php echo $disp; ?>">
|
||||
Created <?php if ($sort == 'api_key_created_at') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_expire&order=<?php echo $disp; ?>">
|
||||
Expires <?php if ($sort == 'api_key_expire') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$api_key_id = intval($row['api_key_id']);
|
||||
$api_key_name = nullable_htmlentities($row['api_key_name']);
|
||||
$api_key_secret = nullable_htmlentities("************" . substr($row['api_key_secret'], -4));
|
||||
$api_key_created_at = nullable_htmlentities($row['api_key_created_at']);
|
||||
$api_key_expire = nullable_htmlentities($row['api_key_expire']);
|
||||
if ($api_key_expire < date("Y-m-d H:i:s")) {
|
||||
$api_key_expire = $api_key_expire . " (Expired)";
|
||||
}
|
||||
|
||||
if ($row['api_key_client_id'] == 0) {
|
||||
$api_key_client = "<i>All Clients</i>";
|
||||
} else {
|
||||
$api_key_client = nullable_htmlentities($row['client_name']);
|
||||
}
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input bulk-select" type="checkbox" name="api_key_ids[]" value="<?php echo $api_key_id ?>">
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="text-bold"><?php echo $api_key_name; ?></td>
|
||||
|
||||
<td><?php echo $api_key_client; ?></td>
|
||||
|
||||
<td><?php echo $api_key_secret; ?></td>
|
||||
|
||||
<td><?php echo $api_key_created_at; ?></td>
|
||||
|
||||
<td><?php echo $api_key_expire; ?></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 text-danger text-bold confirm-link" href="post.php?delete_api_key=<?php echo $api_key_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-times mr-2"></i>Revoke
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<?php require_once "../includes/filter_footer.php";
|
||||
?>
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-key mr-2"></i>API Keys</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/api/api_key_add.php"><i class="fas fa-plus mr-2"></i>New API Key</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../js/bulk_actions.js"></script>
|
||||
<div class="card-body">
|
||||
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search keys">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-8">
|
||||
<div class="btn-group float-right">
|
||||
<div class="dropdown ml-2" id="bulkActionButton" hidden>
|
||||
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
|
||||
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<button class="dropdown-item text-danger text-bold"
|
||||
type="submit" form="bulkActions" name="bulk_delete_api_keys">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Revoke
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</form>
|
||||
<hr>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
|
||||
<form id="bulkActions" action="post.php" method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" onclick="checkAll(this)">
|
||||
</div>
|
||||
</td>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_name&order=<?php echo $disp; ?>">
|
||||
Name <?php if ($sort == 'api_key_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_client_id&order=<?php echo $disp; ?>">
|
||||
Client <?php if ($sort == 'api_key_client_id') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_secret&order=<?php echo $disp; ?>">
|
||||
Secret <?php if ($sort == 'api_key_secret') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_created_at&order=<?php echo $disp; ?>">
|
||||
Created <?php if ($sort == 'api_key_created_at') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_expire&order=<?php echo $disp; ?>">
|
||||
Expires <?php if ($sort == 'api_key_expire') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$api_key_id = intval($row['api_key_id']);
|
||||
$api_key_name = nullable_htmlentities($row['api_key_name']);
|
||||
$api_key_secret = nullable_htmlentities("************" . substr($row['api_key_secret'], -4));
|
||||
$api_key_created_at = nullable_htmlentities($row['api_key_created_at']);
|
||||
$api_key_expire = nullable_htmlentities($row['api_key_expire']);
|
||||
if ($api_key_expire < date("Y-m-d H:i:s")) {
|
||||
$api_key_expire = $api_key_expire . " (Expired)";
|
||||
}
|
||||
|
||||
if ($row['api_key_client_id'] == 0) {
|
||||
$api_key_client = "<i>All Clients</i>";
|
||||
} else {
|
||||
$api_key_client = nullable_htmlentities($row['client_name']);
|
||||
}
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td class="pr-0">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input bulk-select" type="checkbox" name="api_key_ids[]" value="<?php echo $api_key_id ?>">
|
||||
</div>
|
||||
</td>
|
||||
<td class="text-bold"><?php echo $api_key_name; ?></td>
|
||||
<td><?php echo $api_key_client; ?></td>
|
||||
<td><?php echo $api_key_secret; ?></td>
|
||||
<td><?php echo $api_key_created_at; ?></td>
|
||||
<td><?php echo $api_key_expire; ?></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 text-danger text-bold confirm-link" href="post.php?delete_api_key=<?php echo $api_key_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-times mr-2"></i>Revoke
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</form>
|
||||
|
||||
</div>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="../js/bulk_actions.js"></script>
|
||||
|
||||
<?php
|
||||
require_once "modals/api/api_key_add.php";
|
||||
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
|
||||
@@ -97,34 +97,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Canned Date</label>
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
|
||||
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option>
|
||||
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
|
||||
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date From</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date To</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
|
||||
<label>Date range</label>
|
||||
<input type="text" id="dateFilter" class="form-control" autocomplete="off">
|
||||
<input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
|
||||
<input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
|
||||
<input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -159,34 +159,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Canned Date</label>
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
|
||||
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option>
|
||||
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
|
||||
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date From</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date To</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
|
||||
<label>Date range</label>
|
||||
<input type="text" id="dateFilter" class="form-control" autocomplete="off">
|
||||
<input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
|
||||
<input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
|
||||
<input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -266,7 +247,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='../user/client_overview.php?client_id=$client_id'>$client_name</a>";
|
||||
$client_name_display = "<a href='../agent/client_overview.php?client_id=$client_id'>$client_name</a>";
|
||||
}
|
||||
$log_entity_id = intval($row['log_entity_id']);
|
||||
|
||||
|
||||
125
admin/contract_template.php
Normal file
125
admin/contract_template.php
Normal file
@@ -0,0 +1,125 @@
|
||||
<?php
|
||||
|
||||
// Default Column Sort by Filter
|
||||
$sort = "contract_template_name";
|
||||
$order = "ASC";
|
||||
|
||||
require_once "includes/inc_all_admin.php";
|
||||
|
||||
// Search query
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM contract_templates
|
||||
WHERE contract_template_name LIKE '%$q%' OR contract_template_type LIKE '%$q%' OR contract_template_name LIKE '%$q%'
|
||||
ORDER BY $sort $order LIMIT $record_from, $record_to"
|
||||
);
|
||||
|
||||
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file-contract mr-2"></i>Contract Templates</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/contract_template/contract_template_add.php" data-modal-size="lg">
|
||||
<i class="fas fa-plus mr-2"></i>New Template
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
|
||||
<form autocomplete="off">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search templates">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-secondary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<th>Template Name</th>
|
||||
<th>Type</th>
|
||||
<th>Update Frequency</th>
|
||||
<th>SLA (L/M/H Response)</th>
|
||||
<th>SLA (L/M/H Resolution)</th>
|
||||
<th>Hourly Rate</th>
|
||||
<th>After Hours Rate</th>
|
||||
<th>Support Hours</th>
|
||||
<th>Net Terms</th>
|
||||
<th>Created</th>
|
||||
<th>Updated</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$id = intval($row['contract_template_id']);
|
||||
$name = nullable_htmlentities($row['contract_template_name']);
|
||||
$type = nullable_htmlentities($row['contract_template_type']);
|
||||
$freq = nullable_htmlentities($row['contract_template_update_frequency']);
|
||||
$sla_low_resp = nullable_htmlentities($row['sla_low_response_time']);
|
||||
$sla_med_resp = nullable_htmlentities($row['sla_medium_response_time']);
|
||||
$sla_high_resp = nullable_htmlentities($row['sla_high_response_time']);
|
||||
$sla_low_res = nullable_htmlentities($row['sla_low_resolution_time']);
|
||||
$sla_med_res = nullable_htmlentities($row['sla_medium_resolution_time']);
|
||||
$sla_high_res = nullable_htmlentities($row['sla_high_resolution_time']);
|
||||
$hourly_rate = nullable_htmlentities($row['contract_template_hourly_rate']);
|
||||
$after_hours = nullable_htmlentities($row['contract_template_after_hours_hourly_rate']);
|
||||
$support_hours = nullable_htmlentities($row['contract_template_support_hours']);
|
||||
$net_terms = nullable_htmlentities($row['contract_template_net_terms']);
|
||||
$created = nullable_htmlentities($row['contract_template_created_at']);
|
||||
$updated = nullable_htmlentities($row['contract_template_updated_at']);
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<a class="text-bold" href="contract_template_details.php?contract_template_id=<?php echo $id; ?>">
|
||||
<i class="fas fa-fw fa-file-alt text-dark"></i> <?php echo $name; ?>
|
||||
</a>
|
||||
<div class="mt-1 text-secondary"><?php echo nullable_htmlentities($row['contract_template_description']); ?></div>
|
||||
</td>
|
||||
<td><?php echo $type; ?></td>
|
||||
<td><?php echo $freq; ?></td>
|
||||
<td><?php echo "$sla_low_resp / $sla_med_resp / $sla_high_resp"; ?></td>
|
||||
<td><?php echo "$sla_low_res / $sla_med_res / $sla_high_res"; ?></td>
|
||||
<td><?php echo $hourly_rate; ?></td>
|
||||
<td><?php echo $after_hours; ?></td>
|
||||
<td><?php echo $support_hours; ?></td>
|
||||
<td><?php echo $net_terms; ?></td>
|
||||
<td><?php echo $created; ?></td>
|
||||
<td><?php echo $updated; ?></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-size="xl"
|
||||
data-modal-url="modals/contract_template/contract_template_edit.php?id=<?= $id ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold" href="post.php?delete_contract_template=<?php echo $id; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
<?php } ?>
|
||||
</tbody>
|
||||
</table>
|
||||
<br>
|
||||
</div>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "../includes/footer.php"; ?>
|
||||
8
admin/custom/readme.php
Normal file
8
admin/custom/readme.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
|
||||
- Custom Pages -
|
||||
If you wish to add custom pages to ITFlow, add them to this directory"
|
||||
Link to Documentation for File Directory Structure and examples
|
||||
*/
|
||||
@@ -21,7 +21,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-external-link-alt mr-2"></i>Custom Links</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addLinkModal"><i class="fas fa-plus mr-2"></i>New Link</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/custom_link/custom_link_add.php"><i class="fas fa-plus mr-2"></i>New Link</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -96,6 +96,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$custom_link_location_display = "Top Nav";
|
||||
} elseif ($custom_link_location == 3) {
|
||||
$custom_link_location_display = "Client Portal Nav";
|
||||
} elseif ($custom_link_location == 4) {
|
||||
$custom_link_location_display = "Admin Nav";
|
||||
} elseif ($custom_link_location == 5) {
|
||||
$custom_link_location_display = "Reports Nav";
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -141,5 +145,4 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/custom_link/custom_link_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -3969,10 +3969,175 @@ if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) {
|
||||
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
|
||||
if (CURRENT_DATABASE_VERSION == '2.3.2') {
|
||||
|
||||
mysqli_query($mysqli, "ALTER TABLE settings
|
||||
ADD `config_imap_provider` ENUM('standard_imap','google_oauth','microsoft_oauth') NULL DEFAULT NULL AFTER `config_mail_from_name`,
|
||||
ADD `config_mail_oauth_client_id` VARCHAR(255) NULL AFTER `config_imap_provider`,
|
||||
ADD `config_mail_oauth_client_secret` VARCHAR(255) NULL AFTER `config_mail_oauth_client_id`,
|
||||
ADD `config_mail_oauth_tenant_id` VARCHAR(255) NULL AFTER `config_mail_oauth_client_secret`,
|
||||
ADD `config_mail_oauth_refresh_token` TEXT NULL AFTER `config_mail_oauth_tenant_id`,
|
||||
ADD `config_mail_oauth_access_token` TEXT NULL AFTER `config_mail_oauth_refresh_token`,
|
||||
ADD `config_mail_oauth_access_token_expires_at` DATETIME NULL AFTER `config_mail_oauth_access_token`
|
||||
");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.3'");
|
||||
}
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '2.3.3') {
|
||||
|
||||
mysqli_query($mysqli, "ALTER TABLE settings
|
||||
ADD `config_smtp_provider` ENUM('standard_smtp','google_oauth','microsoft_oauth') NULL DEFAULT NULL AFTER `config_start_page`
|
||||
");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.4'");
|
||||
}
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '2.3.4') {
|
||||
|
||||
// Add Software Keys
|
||||
mysqli_query($mysqli, "CREATE TABLE `software_keys` (
|
||||
`software_key_id` INT(11) NOT NULL AUTO_INCREMENT,
|
||||
`software_key` VARCHAR(400) NOT NULL,
|
||||
`software_key_software_id` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`software_key_id`),
|
||||
FOREIGN KEY (`software_key_software_id`) REFERENCES `software`(`software_id`) ON DELETE CASCADE
|
||||
)");
|
||||
|
||||
// Software Key Assignments to Contacts
|
||||
mysqli_query($mysqli, "CREATE TABLE `software_key_contact_assignments` (
|
||||
`software_key_id` INT(11) NOT NULL,
|
||||
`contact_id` INT(11) NOT NULL,
|
||||
`software_key_assigned_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`software_key_id`, `contact_id`),
|
||||
FOREIGN KEY (`software_key_id`) REFERENCES `software_keys`(`software_key_id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`contact_id`) REFERENCES `contacts`(`contact_id`) ON DELETE CASCADE
|
||||
)");
|
||||
|
||||
// Software Key Assignments to Assets
|
||||
mysqli_query($mysqli, "CREATE TABLE `software_key_asset_assignments` (
|
||||
`software_key_id` INT(11) NOT NULL,
|
||||
`asset_id` INT(11) NOT NULL,
|
||||
`software_key_assigned_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
PRIMARY KEY (`software_key_id`, `asset_id`),
|
||||
FOREIGN KEY (`software_key_id`) REFERENCES `software_keys`(`software_key_id`) ON DELETE CASCADE,
|
||||
FOREIGN KEY (`asset_id`) REFERENCES `assets`(`asset_id`) ON DELETE CASCADE
|
||||
)");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.5'");
|
||||
}
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '2.3.5') {
|
||||
mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_smtp_provider` `config_smtp_provider` VARCHAR(200) DEFAULT NULL");
|
||||
mysqli_query($mysqli, "ALTER TABLE `settings` CHANGE `config_imap_provider` `config_imap_provider` VARCHAR(200) DEFAULT NULL");
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.6'");
|
||||
}
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '2.3.6') {
|
||||
// Create New Contract Templates Table
|
||||
mysqli_query($mysqli, "CREATE TABLE `contract_templates` (
|
||||
`contract_template_id` INT(11) AUTO_INCREMENT PRIMARY KEY,
|
||||
`contract_template_name` VARCHAR(255) NOT NULL,
|
||||
`contract_template_description` TEXT NULL DEFAULT NULL,
|
||||
`contract_template_type` VARCHAR(50) NULL DEFAULT NULL,
|
||||
|
||||
`contract_template_sla_low_response_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_template_sla_low_resolution_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_template_sla_medium_response_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_template_sla_medium_resolution_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_template_sla_high_response_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_template_sla_high_resolution_time` INT(11) NULL DEFAULT NULL,
|
||||
|
||||
`contract_template_rate_standard` DECIMAL(10,2) NULL DEFAULT NULL,
|
||||
`contract_template_rate_after_hours` DECIMAL(10,2) NULL DEFAULT NULL,
|
||||
|
||||
`contract_template_net_terms` VARCHAR(50) NULL DEFAULT NULL,
|
||||
`contract_template_support_hours` VARCHAR(100) NULL DEFAULT NULL,
|
||||
`contract_template_renewal_frequency` VARCHAR(50) NULL DEFAULT NULL,
|
||||
|
||||
`contract_template_details` TEXT NULL DEFAULT NULL,
|
||||
|
||||
`contract_template_created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
`contract_template_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`contract_template_archived_at` DATETIME NULL DEFAULT NULL
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
|
||||
|
||||
|
||||
// Create New Contracts Table
|
||||
mysqli_query($mysqli, "CREATE TABLE `contracts` (
|
||||
`contract_id` INT(11) AUTO_INCREMENT PRIMARY KEY,
|
||||
`contract_name` VARCHAR(255) NOT NULL,
|
||||
`contract_status` VARCHAR(50) NOT NULL,
|
||||
`contract_type` VARCHAR(50) NOT NULL,
|
||||
|
||||
`contract_sla_low_response_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_sla_low_resolution_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_sla_medium_response_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_sla_medium_resolution_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_sla_high_response_time` INT(11) NULL DEFAULT NULL,
|
||||
`contract_sla_high_resolution_time` INT(11) NULL DEFAULT NULL,
|
||||
|
||||
`contract_details` TEXT NULL DEFAULT NULL,
|
||||
|
||||
`contract_client_id` INT(11) NULL DEFAULT NULL,
|
||||
`contract_client_name` VARCHAR(255) NULL DEFAULT NULL,
|
||||
`contract_client_address` TEXT NULL DEFAULT NULL,
|
||||
`contract_client_email` VARCHAR(255) NULL DEFAULT NULL,
|
||||
`contract_client_phone` VARCHAR(100) NULL DEFAULT NULL,
|
||||
|
||||
`contract_contact_name` VARCHAR(255) NULL DEFAULT NULL,
|
||||
`contract_contact_signature` TEXT NULL DEFAULT NULL,
|
||||
`contract_contact_signature_date` DATETIME NULL DEFAULT NULL,
|
||||
|
||||
`contract_agent_name` VARCHAR(255) NULL DEFAULT NULL,
|
||||
`contract_agent_signature` TEXT NULL DEFAULT NULL,
|
||||
`contract_agent_signature_date` DATETIME NULL DEFAULT NULL,
|
||||
|
||||
`contract_rate_standard` DECIMAL(10,2) NULL DEFAULT NULL,
|
||||
`contract_rate_after_hours` DECIMAL(10,2) NULL DEFAULT NULL,
|
||||
|
||||
`contract_net_terms` VARCHAR(50) NULL DEFAULT NULL,
|
||||
`contract_support_hours` VARCHAR(100) NULL DEFAULT NULL,
|
||||
|
||||
`contract_start_date` DATE NULL DEFAULT NULL,
|
||||
`contract_end_date` DATE NULL DEFAULT NULL,
|
||||
`contract_renewal_frequency` VARCHAR(50) NULL DEFAULT NULL,
|
||||
|
||||
`contract_created_at` DATETIME DEFAULT CURRENT_TIMESTAMP,
|
||||
`contract_updated_at` DATETIME NULL ON UPDATE CURRENT_TIMESTAMP,
|
||||
`contract_archived_at` DATETIME NULL DEFAULT NULL,
|
||||
|
||||
FOREIGN KEY (`contract_client_id`) REFERENCES `clients`(`client_id`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.7'");
|
||||
}
|
||||
|
||||
if (CURRENT_DATABASE_VERSION == '2.3.7') {
|
||||
|
||||
mysqli_query($mysqli, "
|
||||
CREATE TABLE `asset_tags` (
|
||||
`asset_tag_asset_id` INT(11) NOT NULL,
|
||||
`asset_tag_tag_id` INT(11) NOT NULL,
|
||||
PRIMARY KEY (`asset_tag_asset_id`, `asset_tag_tag_id`),
|
||||
CONSTRAINT `fk_asset`
|
||||
FOREIGN KEY (`asset_tag_asset_id`)
|
||||
REFERENCES `assets`(`asset_id`)
|
||||
ON DELETE CASCADE,
|
||||
CONSTRAINT `fk_tag`
|
||||
FOREIGN KEY (`asset_tag_tag_id`)
|
||||
REFERENCES `tags`(`tag_id`)
|
||||
ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
|
||||
");
|
||||
|
||||
mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.8'");
|
||||
}
|
||||
|
||||
// if (CURRENT_DATABASE_VERSION == '2.3.8') {
|
||||
// // Insert queries here required to update to DB version 2.3.9
|
||||
// // Then, update the database to the next sequential version
|
||||
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.3'");
|
||||
// mysqli_query($mysqli, "UPDATE `settings` SET `config_current_database_version` = '2.3.9'");
|
||||
// }
|
||||
|
||||
} else {
|
||||
|
||||
@@ -46,8 +46,6 @@ $systemInfo[] = [
|
||||
// Section: PHP Extensions
|
||||
$phpExtensions = [];
|
||||
$extensions = [
|
||||
'php-mailparse' => 'mailparse',
|
||||
'php-imap' => 'imap',
|
||||
'php-mysqli' => 'mysqli',
|
||||
'php-intl' => 'intl',
|
||||
'php-curl' => 'curl',
|
||||
@@ -504,6 +502,12 @@ if (file_exists($dbSqlFile)) {
|
||||
];
|
||||
}
|
||||
|
||||
// Duplicate checks
|
||||
$duplicate_tickets_sql = mysqli_query($mysqli, "SELECT ticket_number, COUNT(*) AS count FROM tickets GROUP BY ticket_number HAVING count > 1");
|
||||
$duplicate_quotes_sql = mysqli_query($mysqli, "SELECT quote_number, COUNT(*) AS count FROM quotes GROUP BY quote_number HAVING count > 1");
|
||||
$duplicate_invoices_sql = mysqli_query($mysqli, "SELECT invoice_number, COUNT(*) AS count FROM invoices GROUP BY invoice_number HAVING count > 1");
|
||||
|
||||
|
||||
$mysqli->close();
|
||||
?>
|
||||
|
||||
@@ -760,6 +764,40 @@ $mysqli->close();
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Duplicated ticket/quote/invoice numbers -->
|
||||
<h3 class="mt-3">Duplicated Numbering</h3>
|
||||
<h4>Tickets</h4>
|
||||
<ul>
|
||||
<?php if (mysqli_num_rows($duplicate_tickets_sql) > 0 ) {
|
||||
while ($row = $duplicate_tickets_sql->fetch_assoc()) {
|
||||
echo "<li>" . $config_ticket_prefix . nullable_htmlentities($row['ticket_number']) . " (" . $row['count'] . ")" . "</li>";
|
||||
}
|
||||
} else {
|
||||
echo "No duplicate ticket numbers.";
|
||||
} ?>
|
||||
</ul>
|
||||
<h4>Quotes</h4>
|
||||
<ul>
|
||||
<?php if (mysqli_num_rows($duplicate_quotes_sql) > 0 ) {
|
||||
while ($row = $duplicate_quotes_sql->fetch_assoc()) {
|
||||
echo "<li>" . $config_quote_prefix . nullable_htmlentities($row['quote_number']) . " (" . $row['count'] . ")" . "</li>";
|
||||
}
|
||||
} else {
|
||||
echo "No duplicate quote numbers.";
|
||||
} ?>
|
||||
</ul>
|
||||
<h4>Invoices</h4>
|
||||
<ul>
|
||||
<?php if (mysqli_num_rows($duplicate_invoices_sql) > 0 ) {
|
||||
while ($row = $duplicate_invoices_sql->fetch_assoc()) {
|
||||
echo "<li>" . $config_invoice_prefix . nullable_htmlentities($row['invoice_number']) . " (" . $row['count'] . ")" . "</li>";
|
||||
}
|
||||
} else {
|
||||
echo "No duplicate invoice numbers.";
|
||||
} ?>
|
||||
</ul>
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file mr-2"></i>Document Templates</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addDocumentTemplateModal">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/document_template/document_template_add.php" data-modal-size="xl">
|
||||
<i class="fas fa-plus mr-2"></i>New Template
|
||||
</button>
|
||||
</div>
|
||||
@@ -121,38 +121,4 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php require_once "modals/document_template/document_template_add.php"; ?>
|
||||
<?php require_once "../includes/footer.php"; ?>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
$('#generateAIContent').on('click', function(){
|
||||
var prompt = $('#aiPrompt').val().trim();
|
||||
if(prompt === '') {
|
||||
alert('Please enter a prompt.');
|
||||
return;
|
||||
}
|
||||
|
||||
$('#generateAIContent').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Generating...');
|
||||
|
||||
$.ajax({
|
||||
url: 'post.php?ai_create_document_template', // The PHP script that calls the OpenAI API
|
||||
method: 'POST',
|
||||
data: { prompt: prompt },
|
||||
dataType: 'html',
|
||||
success: function(response) {
|
||||
// Assuming you have exactly one TinyMCE instance on the page
|
||||
// and it's targeting the .tinymce textarea:
|
||||
tinymce.activeEditor.setContent(response);
|
||||
},
|
||||
error: function() {
|
||||
alert('Error generating content. Please try again.');
|
||||
},
|
||||
complete: function() {
|
||||
$('#generateAIContent').prop('disabled', false).html('<i class="fa fa-fw fa-magic mr-1"></i>Generate with AI');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<?php require_once "../includes/footer.php";
|
||||
|
||||
@@ -15,7 +15,13 @@ if (isset($_GET['document_template_id'])) {
|
||||
$document_template_id = intval($_GET['document_template_id']);
|
||||
}
|
||||
|
||||
$sql_document = mysqli_query($mysqli, "SELECT * FROM document_templates WHERE document_template_id = $document_template_id");
|
||||
$sql_document = mysqli_query($mysqli, "SELECT * FROM document_templates WHERE document_template_id = $document_template_id LIMIT 1");
|
||||
|
||||
if (mysqli_num_rows($sql_document) == 0) {
|
||||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='javascript:history.back()'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
require_once "../includes/footer.php";
|
||||
exit();
|
||||
}
|
||||
|
||||
$row = mysqli_fetch_array($sql_document);
|
||||
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
<?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";
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/config.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/functions.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/check_login.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/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";
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/header.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/top_nav.php';
|
||||
require_once 'includes/side_nav.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_wrapper.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/inc_alert_feedback.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/filter_header.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/includes/app_version.php';
|
||||
|
||||
@@ -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="../user/dashboard.php">
|
||||
<a class="brand-link pb-1 mt-1" href="/agent/<?php echo $config_start_page ?>">
|
||||
<p class="h6">
|
||||
<i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
|
||||
<span class="brand-text">
|
||||
@@ -14,21 +14,27 @@
|
||||
<!-- Sidebar Menu -->
|
||||
<nav>
|
||||
<ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" data-accordion="false">
|
||||
<!-- ACCESS Section -->
|
||||
<li class="nav-header">ACCESS</li>
|
||||
<li class="nav-item">
|
||||
<a href="users.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "users.php") {echo "active";} ?>">
|
||||
<a href="/admin/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="roles.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "roles.php") {echo "active";} ?>">
|
||||
<a href="/admin/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="api_keys.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "api_keys.php") {echo "active";} ?>">
|
||||
<a href="/admin/modules.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "modules.php") {echo "active";} ?>">
|
||||
<i class="nav-icon fas fa-puzzle-piece"></i>
|
||||
<p>Modules</p>
|
||||
</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a href="/admin/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,65 +42,66 @@
|
||||
<li class="nav-header">TAGS & CATEGORIES</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="tag.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tag.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="category.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'category.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="tax.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'tax.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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' : ''); ?>">
|
||||
<a href="/admin/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' : ''); ?>">
|
||||
<a href="/admin/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' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
<?php } ?>
|
||||
<li class="nav-item">
|
||||
<a href="ai_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ai_provider.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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' : ''); ?>">
|
||||
<a href="/admin/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="ticket_status.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'ticket_status.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="custom_link.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'custom_link.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
@@ -103,32 +110,43 @@
|
||||
<?php if ($config_module_enable_itdoc) { ?>
|
||||
<li class="nav-header">TEMPLATES</li>
|
||||
|
||||
<!-- 2025-11-16 JQ - Hide Contracts not yet ready
|
||||
<li class="nav-item">
|
||||
<a href="project_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['project_template.php', 'project_template_details.php']) ? 'active' : ''); ?>">
|
||||
<a href="/admin/contract_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'contract_template.php' ? 'active' : ''); ?>">
|
||||
<i class="nav-icon fas fa-file-contract"></i>
|
||||
<p>
|
||||
<span href="#" class="fas fa-plus-circle right ajax-modal" data-modal-url="/admin/modals/contract_template/contract_template_add.php" data-modal-size="lg"></span>
|
||||
Contract Templates
|
||||
</p>
|
||||
</a>
|
||||
</li>
|
||||
-->
|
||||
<li class="nav-item">
|
||||
<a href="/admin/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="ticket_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['ticket_template.php', 'ticket_template_details.php']) ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="vendor_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'vendor_template.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="software_template.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'software_template.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="document_template.php" class="nav-link <?php echo (in_array(basename($_SERVER['PHP_SELF']), ['document_template.php', 'document_template_details.php']) ? 'active' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
@@ -138,37 +156,37 @@
|
||||
<li class="nav-header">MAINTENANCE</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="mail_queue.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'mail_queue.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="audit_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'audit_log.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="app_log.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'app_log.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="backup.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'backup.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="debug.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'debug.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="update.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'update.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
@@ -184,56 +202,56 @@
|
||||
</a>
|
||||
<ul class="nav nav-treeview">
|
||||
<li class="nav-item">
|
||||
<a href="settings_company.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_company.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_localization.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_localization.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_theme.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_theme.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_security.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_security.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_mail.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_mail.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_notification.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_notification.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_default.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_default.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_invoice.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_invoice.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_quote.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_quote.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
@@ -241,13 +259,13 @@
|
||||
<?php } ?>
|
||||
<?php if ($config_module_enable_ticketing) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="settings_project.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_project.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_ticket.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_ticket.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
@@ -256,26 +274,56 @@
|
||||
<!-- Currently the only integration is the client portal SSO -->
|
||||
<?php if ($config_client_portal_enable) { ?>
|
||||
<li class="nav-item">
|
||||
<a href="identity_provider.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'identity_provider.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_telemetry.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_telemetry.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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="settings_module.php" class="nav-link <?php echo (basename($_SERVER['PHP_SELF']) == 'settings_module.php' ? 'active' : ''); ?>">
|
||||
<a href="/admin/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>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<?php
|
||||
$sql_custom_links = mysqli_query($mysqli, "SELECT * FROM custom_links
|
||||
WHERE custom_link_location = 4 AND custom_link_archived_at IS NULL
|
||||
ORDER BY custom_link_order ASC, custom_link_name ASC"
|
||||
);
|
||||
|
||||
while ($row = mysqli_fetch_array($sql_custom_links)) {
|
||||
$custom_link_name = nullable_htmlentities($row['custom_link_name']);
|
||||
$custom_link_uri = sanitize_url($row['custom_link_uri']);
|
||||
$custom_link_icon = nullable_htmlentities($row['custom_link_icon']);
|
||||
$custom_link_new_tab = intval($row['custom_link_new_tab']);
|
||||
if ($custom_link_new_tab == 1) {
|
||||
$target = "target='_blank' rel='noopener noreferrer'";
|
||||
} else {
|
||||
$target = "";
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="<?php echo $custom_link_uri; ?>" <?php echo $target; ?> class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == basename($custom_link_uri)) { echo "active"; } ?>">
|
||||
<i class="fas fa-<?php echo $custom_link_icon; ?> nav-icon"></i>
|
||||
<p><?php echo $custom_link_name; ?></p>
|
||||
<i class="fas fa-angle-right nav-icon float-right"></i>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
</nav>
|
||||
<!-- /.sidebar-menu -->
|
||||
|
||||
@@ -53,34 +53,15 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="collapse mt-3 <?php if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01') { echo "show"; } ?>" id="advancedFilter">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Canned Date</label>
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
|
||||
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option>
|
||||
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
|
||||
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date From</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date To</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
|
||||
<label>Date range</label>
|
||||
<input type="text" id="dateFilter" class="form-control" autocomplete="off">
|
||||
<input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
|
||||
<input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
|
||||
<input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,73 +1,77 @@
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<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']);
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
<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 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>×</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>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,54 +1,58 @@
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<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>
|
||||
ob_start();
|
||||
|
||||
<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 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>×</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>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,121 +1,124 @@
|
||||
<?php
|
||||
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
$key = randomString(156);
|
||||
$decryptPW = randomString(160);
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<div class="modal" id="addApiKeyModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<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-api-details">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-api-keys">Keys</a>
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-api-details">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="key" value="<?php echo $key ?>">
|
||||
<input type="hidden" name="password" value="<?php echo $decryptPW ?>">
|
||||
|
||||
<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-sticky-note"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Key Name" maxlength="255" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Expiration Date <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-calendar"></i></span>
|
||||
</div>
|
||||
<input type="date" class="form-control" name="expire" min="<?php echo date('Y-m-d')?>" max="2999-12-31" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Client Access <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>
|
||||
<select class="form-control select2" name="client" required>
|
||||
<option value="0"> ALL CLIENTS </option>
|
||||
<?php
|
||||
$sql = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']); ?>
|
||||
<option value="<?php echo $client_id; ?>"><?php echo "$client_name (Client ID: $client_id)"; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-api-keys">
|
||||
<div class="form-group">
|
||||
<label>API 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" value="<?php echo $key ?>" required disabled>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $key; ?>"><i class="fa fa-fw fa-copy"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Login credential decryption password <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-unlock-alt"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" value="<?php echo $decryptPW ?>" required disabled>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $decryptPW; ?>"><i class="fa fa-fw fa-copy"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label>I have made a copy of the key(s)<strong class="text-danger">*</strong></label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<input type="checkbox" name="ack" value="1" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<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-api-details">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-api-keys">Keys</a>
|
||||
</li>
|
||||
</ul>
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-api-details">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="key" value="<?php echo $key ?>">
|
||||
<input type="hidden" name="password" value="<?php echo $decryptPW ?>">
|
||||
|
||||
<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-sticky-note"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Key Name" maxlength="255" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Expiration Date <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-calendar"></i></span>
|
||||
</div>
|
||||
<input type="date" class="form-control" name="expire" min="<?php echo date('Y-m-d')?>" max="2999-12-31" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Client Access <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>
|
||||
<select class="form-control select2" name="client" required>
|
||||
<option value="0"> ALL CLIENTS </option>
|
||||
<?php
|
||||
$sql = mysqli_query($mysqli, "SELECT client_id, client_name FROM clients WHERE client_archived_at IS NULL ORDER BY client_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']); ?>
|
||||
<option value="<?php echo $client_id; ?>"><?php echo "$client_name (Client ID: $client_id)"; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-api-keys">
|
||||
<div class="form-group">
|
||||
<label>API 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" value="<?php echo $key ?>" required disabled>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $key; ?>"><i class="fa fa-fw fa-copy"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Login credential decryption password <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-unlock-alt"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" value="<?php echo $decryptPW ?>" required disabled>
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $decryptPW; ?>"><i class="fa fa-fw fa-copy"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<div class="form-group">
|
||||
<label>I have made a copy of the key(s)<strong class="text-danger">*</strong></label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<input type="checkbox" name="ack" value="1" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
$category = nullable_htmlentities($_GET['category']);
|
||||
$category = nullable_htmlentities($_GET['category'] ?? '');
|
||||
|
||||
$category_types_array = ['Expense', 'Income', 'Referral', 'Ticket'];
|
||||
|
||||
?>
|
||||
|
||||
@@ -13,10 +15,30 @@ $category = nullable_htmlentities($_GET['category']);
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="type" value="<?php echo ($category); ?>">
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
<?php if ($category) { ?>
|
||||
<input type="hidden" name="type" value="<?= $category ?>">
|
||||
<?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-tag"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="type" required>
|
||||
<option value="">- Select Type -</option>
|
||||
<?php foreach ($category_types_array as $type_select) { ?>
|
||||
<option><?= $type_select ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Name <strong class="text-danger">*</strong></label>
|
||||
<div class="input-group">
|
||||
@@ -39,7 +61,7 @@ $category = nullable_htmlentities($_GET['category']);
|
||||
|
||||
</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="submit" name="add_category" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create Category</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
221
admin/modals/contract_template/contract_template_add.php
Normal file
221
admin/modals/contract_template/contract_template_add.php
Normal file
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
|
||||
$contract_types_array = ['Fully Managed', 'Partialy Managed', 'Break/Fix'];
|
||||
$renewal_frequency_array = ['Manual', 'Annually', '2 Year', '3 Year', '5 Year', '7 Year'];
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-file-contract mr-2"></i>New Contract Template</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal"><span>×</span></button>
|
||||
</div>
|
||||
|
||||
<!-- Tabs Navigation -->
|
||||
<ul class="modal-header nav nav-pills nav-justified">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="general-tab" data-toggle="tab" href="#general" role="tab">General Info</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="sla-tab" data-toggle="tab" href="#sla" role="tab">SLA</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="rates-tab" data-toggle="tab" href="#rates" role="tab">Rates & Support</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="details-tab" data-toggle="tab" href="#details" role="tab">Details</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
<div class="tab-content" id="contractTemplateTabContent">
|
||||
|
||||
<!-- General Info Tab -->
|
||||
<div class="tab-pane fade show active" id="general" role="tabpanel">
|
||||
<div class="form-group">
|
||||
<label>Template 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-file-contract"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Contract Template Name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Template Description <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-align-left"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description"
|
||||
placeholder="Contract Template Description" maxlength="200" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Contract 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-list"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="type" required>
|
||||
<option value="">- Select Type -</option>
|
||||
<?php foreach ($contract_types_array as $type) { ?>
|
||||
<option><?= $type ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Renewal Frequency</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sync-alt"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="renewal_frequency">
|
||||
<option value="">- Select Frequency -</option>
|
||||
<?php foreach ($renewal_frequency_array as $renewal_frequency) { ?>
|
||||
<option><?= $renewal_frequency ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SLA Tab -->
|
||||
<div class="tab-pane fade" id="sla" role="tabpanel">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>Low Priority Response (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_low_response_time" placeholder="e.g., 24">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label>Low Priority Resolution (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-hourglass-half"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_low_resolution_time" placeholder="e.g., 48">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>Medium Priority Response (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_medium_response_time" placeholder="e.g., 12">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label>Medium Priority Resolution (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-hourglass-half"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_medium_resolution_time" placeholder="e.g., 24">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>High Priority Response (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-bolt"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_high_response_time" placeholder="e.g., 1">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label>High Priority Resolution (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stopwatch"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_high_resolution_time" placeholder="e.g., 4">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rates & Support Tab -->
|
||||
<div class="tab-pane fade" id="rates" role="tabpanel">
|
||||
<div class="form-group">
|
||||
<label>Standard Hourly Rate</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-dollar-sign"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="rate_standard" placeholder="e.g., 100">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>After Hours Hourly Rate</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-moon"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="rate_after_hours" placeholder="e.g., 150">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Hours</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="support_hours" placeholder="e.g., Mon-Fri 9am-5pm">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Net Terms</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-file-invoice-dollar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="net_terms" placeholder="e.g., Net 30">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Details Tab -->
|
||||
<div class="tab-pane fade" id="details" role="tabpanel">
|
||||
<div class="form-group">
|
||||
<textarea class="form-control tinymce" rows="6" name="details" placeholder="Enter Contract Details"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="add_contract_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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
?>
|
||||
265
admin/modals/contract_template/contract_template_edit.php
Normal file
265
admin/modals/contract_template/contract_template_edit.php
Normal file
@@ -0,0 +1,265 @@
|
||||
<?php
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
$contract_template_id = intval($_GET['id']);
|
||||
|
||||
$contract_types_array = ['Fully Managed', 'Partialy Managed', 'Break/Fix'];
|
||||
$update_frequency_array = ['Manual', 'Annually', '2 Year', '3 Year', '5 Year', '7 Year'];
|
||||
|
||||
// Fetch existing template
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM contract_templates WHERE contract_template_id = $contract_template_id LIMIT 1");
|
||||
$row = mysqli_fetch_array($sql);
|
||||
|
||||
// Assign locals
|
||||
$name = nullable_htmlentities($row['contract_template_name']);
|
||||
$description = nullable_htmlentities($row['contract_template_description']);
|
||||
$type = nullable_htmlentities($row['contract_template_type']);
|
||||
$renewal_frequency = nullable_htmlentities($row['contract_template_renewal_frequency']);
|
||||
$sla_low_resp = intval($row['contract_template_sla_low_response_time']);
|
||||
$sla_med_resp = intval($row['contract_template_sla_medium_response_time']);
|
||||
$sla_high_resp = intval($row['contract_template_sla_high_response_time']);
|
||||
$sla_low_res = intval($row['contract_template_sla_low_resolution_time']);
|
||||
$sla_med_res = intval($row['contract_template_sla_medium_resolution_time']);
|
||||
$sla_high_res = intval($row['contract_template_sla_high_resolution_time']);
|
||||
$hourly_rate = intval($row['contract_template_rate_standard']);
|
||||
$after_hours = intval($row['contract_template_rate_after_hours']);
|
||||
$support_hours = nullable_htmlentities($row['contract_template_support_hours']);
|
||||
$net_terms = intval($row['contract_template_net_terms']);
|
||||
$details = nullable_htmlentities($row['contract_template_details']);
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-file-contract mr-2"></i>Edit Contract Template</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal"><span>×</span></button>
|
||||
</div>
|
||||
|
||||
<!-- Tabs Navigation -->
|
||||
<ul class="modal-header nav nav-pills nav-justified">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" id="general-tab" data-toggle="tab" href="#general" role="tab">General Info</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="sla-tab" data-toggle="tab" href="#sla" role="tab">SLA</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="rates-tab" data-toggle="tab" href="#rates" role="tab">Rates & Support</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" id="details-tab" data-toggle="tab" href="#details" role="tab">Details</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="contract_template_id" value="<?php echo $contract_template_id; ?>">
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="tab-content" id="contractTemplateTabContent">
|
||||
|
||||
<!-- General Info Tab -->
|
||||
<div class="tab-pane fade show active" id="general" role="tabpanel">
|
||||
<div class="form-group">
|
||||
<label>Template 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-file-contract"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name"
|
||||
placeholder="Contract Template Name" maxlength="200" required autofocus
|
||||
value="<?= $name ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Template Description <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-align-left"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description"
|
||||
placeholder="Contract Template Description" maxlength="200" required
|
||||
value="<?= $description ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Contract 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-list"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="type" required>
|
||||
<option value="">- Select Type -</option>
|
||||
<?php foreach ($contract_types_array as $type_select) { ?>
|
||||
<option <?php if ($type == $type_select) { echo "selected"; } ?>><?= $type_select ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Renewal Frequency</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sync-alt"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="renewal_frequency">
|
||||
<option value="">- Select Frequency -</option>
|
||||
<?php foreach ($renewal_frequency_array as $renewal_frequency_select) { ?>
|
||||
<option <?php if ($renewal_frequency == $renewal_frequency_select) { echo "selected"; } ?>><?= $renewal_frequency_select ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- SLA Tab -->
|
||||
<div class="tab-pane fade" id="sla" role="tabpanel">
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>Low Priority Response (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_low_response_time" placeholder="e.g., 24"
|
||||
value="<?= $sla_low_resp ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label>Low Priority Resolution (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-hourglass-half"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_low_resolution_time" placeholder="e.g., 48"
|
||||
value="<?= $sla_low_res ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>Medium Priority Response (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_medium_response_time" placeholder="e.g., 12"
|
||||
value="<?= $sla_med_resp ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label>Medium Priority Resolution (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-hourglass-half"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_medium_resolution_time" placeholder="e.g., 24"
|
||||
value="<?= $sla_med_res ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<div class="form-group col-md-6">
|
||||
<label>High Priority Response (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-bolt"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_high_response_time" placeholder="e.g., 1"
|
||||
value="<?= $sla_high_resp ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group col-md-6">
|
||||
<label>High Priority Resolution (hrs)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-stopwatch"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="sla_high_resolution_time" placeholder="e.g., 4"
|
||||
value="<?= $sla_high_res ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Rates & Support Tab -->
|
||||
<div class="tab-pane fade" id="rates" role="tabpanel">
|
||||
<div class="form-group">
|
||||
<label>Standard Hourly Rate</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-dollar-sign"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="rate_standard" placeholder="e.g., 100"
|
||||
value="<?= $rate_standard ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>After Hours Hourly Rate</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-moon"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="rate_after_hours" placeholder="e.g., 150"
|
||||
value="<?= $rate_after_hours ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Hours</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="support_hours" placeholder="e.g., Mon-Fri 9am-5pm"
|
||||
value="<?= $support_hours ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Net Terms</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-file-invoice-dollar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="net_terms" placeholder="e.g., Net 30"
|
||||
value="<?= $net_terms ?>">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Details Tab -->
|
||||
<div class="tab-pane fade" id="details" role="tabpanel">
|
||||
<div class="form-group">
|
||||
<label>Contract Details</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-align-left"></i></span>
|
||||
</div>
|
||||
<textarea class="form-control tinymce" rows="6" name="details"
|
||||
placeholder="Enter Contract Details"><?= $details ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="edit_contract_template" class="btn btn-primary text-bold">
|
||||
<i class="fa fa-check mr-2"></i>Save Changes
|
||||
</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';
|
||||
?>
|
||||
@@ -1,81 +1,88 @@
|
||||
<div class="modal" id="addLinkModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<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="Link name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
ob_start();
|
||||
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="order" placeholder="Leave blank for no order">
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
|
||||
<div class="form-group">
|
||||
<label>URI <strong class="text-danger">*</strong></label> / <span class="text-secondary">Open New Tab</span>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-external-link-alt"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="uri" placeholder="Enter Link" maxlength="500" required>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<input type="checkbox" name="new_tab" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</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" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Location <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-home"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="location" required>
|
||||
<option value="1">Main Side Nav</option>
|
||||
<option value="2">Top Nav (Icon Required)</option>
|
||||
<option value="3">Client Portal Nav</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
|
||||
<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="Link name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
|
||||
</div>
|
||||
<input type="number" class="form-control" name="order" placeholder="Leave blank for no order">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>URI <strong class="text-danger">*</strong></label> / <span class="text-secondary">Open New Tab</span>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-external-link-alt"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="uri" placeholder="Enter Link" maxlength="500" required>
|
||||
<div class="input-group-append">
|
||||
<div class="input-group-text">
|
||||
<input type="checkbox" name="new_tab" value="1">
|
||||
</div>
|
||||
</div>
|
||||
</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" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Location <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-home"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="location" required>
|
||||
<option value="1">Main Side Nav</option>
|
||||
<option value="2">Top Nav (Icon Required)</option>
|
||||
<option value="3">Client Portal Nav</option>
|
||||
<option value="4">Admin Nav</option>
|
||||
<option value="5">Reports Nav</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -81,9 +81,11 @@ ob_start();
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-home"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="location" required>
|
||||
<option value="1" <?php if ($custom_link_location == 1) { echo "selected"; } ?> >Main Side Nav</option>
|
||||
<option value="2" <?php if ($custom_link_location == 2) { echo "selected"; } ?> >Top Nav (Icon Required)</option>
|
||||
<option value="3" <?php if ($custom_link_location == 3) { echo "selected"; } ?> >Client Portal Nav</option>
|
||||
<option value="1" <?php if ($custom_link_location === 1) { echo "selected"; } ?> >Main Side Nav</option>
|
||||
<option value="2" <?php if ($custom_link_location === 2) { echo "selected"; } ?> >Top Nav (Icon Required)</option>
|
||||
<option value="3" <?php if ($custom_link_location === 3) { echo "selected"; } ?> >Client Portal Nav</option>
|
||||
<option value="4" <?php if ($custom_link_location === 4) { echo "selected"; } ?> >Admin Nav</option>
|
||||
<option value="5" <?php if ($custom_link_location === 5) { echo "selected"; } ?> >Reports Nav</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,52 +1,87 @@
|
||||
<div class="modal" id="addDocumentTemplateModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
<?php
|
||||
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="name" placeholder="Template name" maxlength="200">
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<?php if ($config_ai_enable == 1) { ?>
|
||||
<!-- Prompt for AI -->
|
||||
<div class="form-group">
|
||||
<label>Enter a prompt for the type of IT documentation you want to generate:</label>
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" id="aiPrompt" placeholder="e.g. 'A network troubleshooting guide for junior technicians'">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-info" type="button" id="generateAIContent">
|
||||
<i class="fa fa-fw fa-magic mr-1"></i>Generate with AI
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
ob_start();
|
||||
|
||||
<!-- TinyMCE Content -->
|
||||
<div class="form-group">
|
||||
<textarea class="form-control tinymce" name="content"></textarea>
|
||||
</div>
|
||||
?>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="description" placeholder="Enter a short summary">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="name" placeholder="Template name" maxlength="200">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Enter a prompt for the type of IT documentation you want to generate:</label>
|
||||
<div class="input-group mb-3">
|
||||
<input type="text" class="form-control" id="aiPrompt" placeholder="e.g. 'A network troubleshooting guide for junior technicians'">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-info" type="button" id="generateAIContent">
|
||||
<i class="fa fa-fw fa-magic mr-1"></i>Generate with AI
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- TinyMCE Content -->
|
||||
<div class="form-group">
|
||||
<textarea class="form-control tinymce" name="content"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="description" placeholder="Enter a short summary">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<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>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
$('#generateAIContent').on('click', function(){
|
||||
var prompt = $('#aiPrompt').val().trim();
|
||||
if(prompt === '') {
|
||||
alert('Please enter a prompt.');
|
||||
return;
|
||||
}
|
||||
|
||||
$('#generateAIContent').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Generating...');
|
||||
|
||||
$.ajax({
|
||||
url: '/agent/ajax.php?ai_create_document_template', // The PHP script that calls the OpenAI API
|
||||
method: 'POST',
|
||||
data: { prompt: prompt },
|
||||
dataType: 'html',
|
||||
success: function(response) {
|
||||
// Assuming you have exactly one TinyMCE instance on the page
|
||||
// and it's targeting the .tinymce textarea:
|
||||
tinymce.activeEditor.setContent(response);
|
||||
},
|
||||
error: function() {
|
||||
alert('Error generating content. Please try again.');
|
||||
},
|
||||
complete: function() {
|
||||
$('#generateAIContent').prop('disabled', false).html('<i class="fa fa-fw fa-magic mr-1"></i>Generate with AI');
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,37 +1,42 @@
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<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>
|
||||
ob_start();
|
||||
|
||||
<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 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>×</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>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -22,7 +22,7 @@ ob_start();
|
||||
</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="payment_method_id" value="<?= $payment_method_id ?>">
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="form-group">
|
||||
|
||||
@@ -1,103 +1,106 @@
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<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>
|
||||
ob_start();
|
||||
|
||||
<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 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>×</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="decimal" 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 invoice amount is above this number, 0 disables the threshold check.</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="decimal" 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="decimal" 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>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -58,7 +58,7 @@ ob_start();
|
||||
<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; ?>">
|
||||
<input type="text" class="form-control" inputmode="decimal" 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>
|
||||
@@ -79,7 +79,7 @@ ob_start();
|
||||
<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">
|
||||
<input type="text" class="form-control" inputmode="decimal" 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>
|
||||
@@ -90,7 +90,7 @@ ob_start();
|
||||
<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">
|
||||
<input type="text" class="form-control" inputmode="decimal" 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>
|
||||
|
||||
@@ -1,41 +1,45 @@
|
||||
<div class="modal" id="addProjectTemplateModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Project Template 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-project-diagram"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Project Template Name" maxlength="255" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Description">
|
||||
</div>
|
||||
</div>
|
||||
ob_start();
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Project Template 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-project-diagram"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Project Template Name" maxlength="255" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Description">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,44 +1,56 @@
|
||||
<div class="modal" id="editProjectTemplateModal<?php echo $project_template_id; ?>" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="project_template_id" value="<?php echo $project_template_id; ?>">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
<label>Project Template 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-project-diagram"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Project Template Name" maxlength="255" value="<?php echo $project_template_name; ?>" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Description" value="<?php echo $project_template_description; ?>">
|
||||
</div>
|
||||
</div>
|
||||
$project_template_id = intval($_GET['project_template_id']);
|
||||
|
||||
</div>
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM project_templates WHERE project_template_id = $project_template_id LIMIT 1");
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$project_template_name = nullable_htmlentities($row['project_template_name']);
|
||||
$project_template_description = nullable_htmlentities($row['project_template_description']);
|
||||
|
||||
<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>
|
||||
ob_start();
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
|
||||
<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>×</span>
|
||||
</button>
|
||||
</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">
|
||||
<div class="form-group">
|
||||
<label>Project Template 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-project-diagram"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Project Template Name" maxlength="255" value="<?php echo $project_template_name; ?>" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Description" value="<?php echo $project_template_description; ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<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>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';
|
||||
|
||||
@@ -1,64 +1,71 @@
|
||||
<div class="modal" id="addProjectTemplateTicketTemplateModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</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">
|
||||
<?php
|
||||
|
||||
<div class="form-group">
|
||||
<label>Ticket Template <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-life-ring"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="ticket_template_id" required>
|
||||
<option value="">- Select a Ticket Template -</option>
|
||||
<?php
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
$sql_ticket_templates_select = mysqli_query($mysqli, "SELECT ticket_template_id, ticket_template_name FROM ticket_templates
|
||||
WHERE ticket_template_id NOT IN (
|
||||
SELECT ticket_template_id FROM project_template_ticket_templates
|
||||
WHERE project_template_id = $project_template_id
|
||||
)
|
||||
AND ticket_template_archived_at IS NULL
|
||||
ORDER BY ticket_template_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_ticket_templates_select)) {
|
||||
$ticket_template_id_select = intval($row['ticket_template_id']);
|
||||
$ticket_template_name_select = nullable_htmlentities($row['ticket_template_name']);
|
||||
?>
|
||||
<option value="<?php echo $ticket_template_id_select; ?>"><?php echo $ticket_template_name_select; ?></option>
|
||||
<?php
|
||||
}
|
||||
$project_template_id = intval($_GET['project_template_id']);
|
||||
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
ob_start();
|
||||
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="order" value="1">
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</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">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Ticket Template <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-life-ring"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="ticket_template_id" required>
|
||||
<option value="">- Select a Ticket Template -</option>
|
||||
<?php
|
||||
|
||||
$sql_ticket_templates_select = mysqli_query($mysqli, "SELECT ticket_template_id, ticket_template_name FROM ticket_templates
|
||||
WHERE ticket_template_id NOT IN (
|
||||
SELECT ticket_template_id FROM project_template_ticket_templates
|
||||
WHERE project_template_id = $project_template_id
|
||||
)
|
||||
AND ticket_template_archived_at IS NULL
|
||||
ORDER BY ticket_template_name ASC"
|
||||
);
|
||||
while ($row = mysqli_fetch_array($sql_ticket_templates_select)) {
|
||||
$ticket_template_id_select = intval($row['ticket_template_id']);
|
||||
$ticket_template_name_select = nullable_htmlentities($row['ticket_template_name']);
|
||||
?>
|
||||
<option value="<?php echo $ticket_template_id_select; ?>"><?php echo $ticket_template_name_select; ?></option>
|
||||
<?php
|
||||
}
|
||||
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Order</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="order" value="1">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,58 +1,62 @@
|
||||
<div class="modal" id="addRoleModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</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'] ?>">
|
||||
<div class="modal-body">
|
||||
<div class="tab-content">
|
||||
<?php
|
||||
|
||||
<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-shield"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="role_name" placeholder="Role Name" maxlength="200" required>
|
||||
</div>
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description <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-chevron-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="role_description" placeholder="Role Description" maxlength="200" required>
|
||||
</div>
|
||||
</div>
|
||||
ob_start();
|
||||
|
||||
<div class="form-group">
|
||||
<label>Admin Access <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-tools"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="role_is_admin" required>
|
||||
<option value="0">No - edit after creation to set permissions</option>
|
||||
<option value="1">Yes - this role should have full admin access</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title"><i class="fas fa-fw fa-user-shield mr-2"></i>New Role</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</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'] ?>">
|
||||
<div class="modal-body">
|
||||
<div class="tab-content">
|
||||
|
||||
<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-shield"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="role_name" placeholder="Role Name" maxlength="200" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description <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-chevron-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="role_description" placeholder="Role Description" maxlength="200" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Admin Access <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-tools"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="role_is_admin" required>
|
||||
<option value="0">No - edit after creation to set permissions</option>
|
||||
<option value="1">Yes - this role should have full admin access</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,83 +1,88 @@
|
||||
<div class="modal" id="addSoftwareTemplateModal" 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-cube mr-2"></i>New License Template</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
<?php
|
||||
|
||||
<div class="form-group">
|
||||
<label>Template 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-cube"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Software name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<div class="form-group">
|
||||
<label>Version</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="version" placeholder="Software version" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
ob_start();
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Short description">
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
|
||||
<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-tag"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="type" required>
|
||||
<option value="">- Type -</option>
|
||||
<?php foreach($software_types_array as $software_type) { ?>
|
||||
<option><?php echo $software_type; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>License Type</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="license_type">
|
||||
<option value="">- Select a License Type -</option>
|
||||
<?php foreach($license_types_array as $license_type) { ?>
|
||||
<option><?php echo $license_type; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Template 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-cube"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Software name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Version</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="version" placeholder="Software version" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Short description">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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-tag"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="type" required>
|
||||
<option value="">- Type -</option>
|
||||
<?php foreach($software_types_array as $software_type) { ?>
|
||||
<option><?php echo $software_type; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>License Type</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="license_type">
|
||||
<option value="">- Select a License Type -</option>
|
||||
<?php foreach($license_types_array as $license_type) { ?>
|
||||
<option><?php echo $license_type; ?></option>
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -15,8 +15,11 @@ if (isset($_GET['type'])) {
|
||||
$type_display = "Contact";
|
||||
} elseif ($type === 4) {
|
||||
$type_display = "Credential";
|
||||
} elseif ($type === 5) {
|
||||
$type_display = "Asset";
|
||||
}
|
||||
}
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
@@ -57,6 +60,7 @@ if (isset($_GET['type'])) {
|
||||
<option value="2">Location Tag</option>
|
||||
<option value="3">Contact Tag</option>
|
||||
<option value="4">Credential Tag</option>
|
||||
<option value="5">Asset Tag</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
@@ -85,7 +89,7 @@ if (isset($_GET['type'])) {
|
||||
|
||||
</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="submit" name="add_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Create Tag</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -12,11 +12,24 @@ $tag_type = intval($row['tag_type']);
|
||||
$tag_color = nullable_htmlentities($row['tag_color']);
|
||||
$tag_icon = nullable_htmlentities($row['tag_icon']);
|
||||
|
||||
// Generate the HTML form content using output buffering.
|
||||
if ($tag_type == 1) {
|
||||
$tag_type_display = "Client";
|
||||
} elseif ( $tag_type == 2) {
|
||||
$tag_type_display = "Location";
|
||||
} elseif ( $tag_type == 3) {
|
||||
$tag_type_display = "Contact";
|
||||
} elseif ( $tag_type == 4) {
|
||||
$tag_type_display = "Credential";
|
||||
} elseif ( $tag_type == 5) {
|
||||
$tag_type_display = "Asset";
|
||||
} else {
|
||||
$tag_type_display = "Unknown";
|
||||
}
|
||||
|
||||
ob_start();
|
||||
?>
|
||||
<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>
|
||||
<h5 class="modal-title"><i class="fas fa-fw fa-tag mr-2"></i><?= $tag_type_display ?> Tag: <strong><?php echo $tag_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
@@ -35,22 +48,6 @@ ob_start();
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<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" <?php if ($tag_type == 1) { echo "selected"; } ?>>Client Tag</option>
|
||||
<option value="2" <?php if ($tag_type == 2) { echo "selected"; } ?>>Location Tag</option>
|
||||
<option value="3" <?php if ($tag_type == 3) { echo "selected"; } ?>>Contact Tag</option>
|
||||
<option value="4" <?php if ($tag_type == 4) { echo "selected"; } ?>>Credential Tag</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Color <strong class="text-danger">*</strong></label>
|
||||
<div class="input-group">
|
||||
@@ -73,7 +70,7 @@ ob_start();
|
||||
|
||||
</div>
|
||||
<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="submit" name="edit_tag" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save changes</button>
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,30 +1,35 @@
|
||||
<div class="modal" id="addTaxModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<?php
|
||||
|
||||
<div class="modal-body">
|
||||
<div class="form-group">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
|
||||
<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">×</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>
|
||||
<input type="text" class="form-control" name="name" placeholder="Tax name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Percent <strong class="text-danger">*</strong></label>
|
||||
<input type="number" min="0" step="any" class="form-control col-md-4" name="percent">
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,42 +1,43 @@
|
||||
<div class="modal" id="addTicketStatusModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<?php
|
||||
require_once '../../../includes/modal_header.php';
|
||||
ob_start();
|
||||
?>
|
||||
|
||||
<div class="modal-body">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
|
||||
<div class="form-group">
|
||||
<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-info-circle"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Ticket Status name" maxlength="200" required autofocus>
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-info-circle"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Ticket Status name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<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 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>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
@@ -1,75 +1,79 @@
|
||||
<div class="modal" id="addTicketTemplateModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<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>×</span>
|
||||
</button>
|
||||
<?php
|
||||
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
<div class="modal-header bg-dark">
|
||||
<h5 class="modal-title"><i class="fa fa-fw fa-life-ring mr-2"></i>New Ticket Template</h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Template 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-life-ring"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Template name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Template 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-life-ring"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Template name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Subject</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<textarea class="form-control tinymceTicket" name="details"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Short description">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Add it to a Project Template?</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-project-diagram"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="project_template">
|
||||
<option value="0">- No -</option>
|
||||
<?php
|
||||
|
||||
$sql_project_templates = mysqli_query($mysqli, "SELECT * FROM project_templates WHERE project_template_archived_at IS NULL ORDER BY project_template_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql_project_templates)) {
|
||||
$project_template_id_select = intval($row['project_template_id']);
|
||||
$project_template_name_select = nullable_htmlentities($row['project_template_name']); ?>
|
||||
<option value="<?php echo $project_template_id_select; ?>"><?php echo $project_template_name_select; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Subject</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<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>
|
||||
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<textarea class="form-control tinymceTicket" name="details"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
</form>
|
||||
<input type="text" class="form-control" name="description" placeholder="Short description">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Add it to a Project Template?</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-project-diagram"></i></span>
|
||||
</div>
|
||||
<select class="form-control select2" name="project_template">
|
||||
<option value="0">- No -</option>
|
||||
<?php
|
||||
|
||||
$sql_project_templates = mysqli_query($mysqli, "SELECT * FROM project_templates WHERE project_template_archived_at IS NULL ORDER BY project_template_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql_project_templates)) {
|
||||
$project_template_id_select = intval($row['project_template_id']);
|
||||
$project_template_name_select = nullable_htmlentities($row['project_template_name']); ?>
|
||||
<option value="<?php echo $project_template_id_select; ?>"><?php echo $project_template_name_select; ?></option>
|
||||
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<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 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/modal_footer.php';
|
||||
|
||||
@@ -1,204 +0,0 @@
|
||||
<?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>×</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.php';
|
||||
@@ -1,156 +1,176 @@
|
||||
<div class="modal" id="addUserModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</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'] ?>">
|
||||
<div class="modal-body">
|
||||
<?php
|
||||
|
||||
<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">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-user-access">Restrict Access</a>
|
||||
</li>
|
||||
</ul>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<hr>
|
||||
ob_start();
|
||||
|
||||
<div class="tab-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>×</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'] ?>">
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-user-details">
|
||||
<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">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-user-access">Restrict Access</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<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" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
||||
<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" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Password <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-lock"></i></span>
|
||||
</div>
|
||||
<input type="password" class="form-control" data-toggle="password" name="password" id="password" placeholder="Enter a Password" autocomplete="new-password" minlength="8" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
<span class="btn btn-default"><i class="fa fa-fw fa-question" onclick="generatePassword()"></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>
|
||||
<option value="">- Role -</option>
|
||||
<?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 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" <?php if(empty($config_smtp_host)) { echo "hidden"; } ?>>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" id="sendEmailCheckBox" name="send_email" value="" checked>
|
||||
<label for="sendEmailCheckBox" class="custom-control-label">
|
||||
Send user e-mail with login details?
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" id="forceMFACheckBox" name="force_mfa" value=1>
|
||||
<label for="forceMFACheckBox" class="custom-control-label">
|
||||
Force MFA
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tab-pane fade show active" id="pills-user-details">
|
||||
|
||||
<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" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-user-access">
|
||||
<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" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="alert alert-info">
|
||||
Check boxes to authorize user client access. No boxes grant full client access. Admin users are unaffected.
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Password <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-lock"></i></span>
|
||||
</div>
|
||||
<input type="password" class="form-control" data-toggle="password" name="password" id="password" placeholder="Enter a Password" autocomplete="new-password" minlength="8" required>
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
|
||||
</div>
|
||||
<div class="input-group-append">
|
||||
<span class="btn btn-default"><i class="fa fa-fw fa-question" onclick="generatePassword()"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</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 = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
<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>
|
||||
<option value="">- Role -</option>
|
||||
<?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']);
|
||||
|
||||
?>
|
||||
<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; ?>">
|
||||
<label class="form-check-label ml-3"><?php echo $client_name; ?></label>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
<option 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="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 class="form-group" <?php if(empty($config_smtp_host)) { echo "hidden"; } ?>>
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" id="sendEmailCheckBox" name="send_email" value="" checked>
|
||||
<label for="sendEmailCheckBox" class="custom-control-label">
|
||||
Send user e-mail with login details?
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="custom-control custom-checkbox">
|
||||
<input class="custom-control-input" type="checkbox" id="forceMFACheckBox" name="force_mfa" value=1>
|
||||
<label for="forceMFACheckBox" class="custom-control-label">
|
||||
Force MFA
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-user-access">
|
||||
|
||||
<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 = intval($row['client_id']);
|
||||
$client_name = 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; ?>">
|
||||
<label class="form-check-label ml-3"><?php echo $client_name; ?></label>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
<?php } ?>
|
||||
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
function generatePassword() {
|
||||
jQuery.get(
|
||||
"/agent/ajax.php", {
|
||||
get_readable_pass: 'true'
|
||||
},
|
||||
function(data) {
|
||||
const password = JSON.parse(data);
|
||||
document.getElementById("password").value = password;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once "../../../includes/modal_footer.php";
|
||||
|
||||
@@ -1,31 +1,35 @@
|
||||
<div class="modal" id="resetAllUserPassModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div class="mb-4" style="text-align: center;">
|
||||
<i class="far fas fa-10x fa-skull-crossbones text-danger mb-3 mt-3"></i>
|
||||
<h2>Incident Response: Agent Password Reset</h2>
|
||||
<br>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<b>This is a potentially destructive function.<br>It is intended to be used as part of a potential security incident.</b>
|
||||
</div>
|
||||
<h6 class="mb-4 text-secondary"><b>All ITFlow agent passwords will be reset and shown to you </b><i>(except yours - change yours first!)</i>.<br/><br/>You should communicate temporary passwords to agents out of band (e.g. via a phone call) and require they are changed ASAP.</h6>
|
||||
<form action="post.php" method="POST">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<div class="row col-7 offset-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<input type="password" class="form-control" placeholder="Enter your account password to continue" name="admin_password" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<button class="btn btn-danger" type="submit" name="ir_reset_user_password"><i class="fas fa-fw fa-key mr-2"></i>Reset passwords</button>
|
||||
</form>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg px-5 mr-4" data-dismiss="modal">Cancel</button>
|
||||
<?php
|
||||
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
ob_start();
|
||||
|
||||
?>
|
||||
<div class="modal-body">
|
||||
<div class="mb-4" style="text-align: center;">
|
||||
<i class="far fas fa-10x fa-skull-crossbones text-danger mb-3 mt-3"></i>
|
||||
<h2>Incident Response: Agent Password Reset</h2>
|
||||
<br>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<b>This is a potentially destructive function.<br>It is intended to be used as part of a potential security incident.</b>
|
||||
</div>
|
||||
<h6 class="mb-4 text-secondary"><b>All ITFlow agent passwords will be reset and shown to you </b><i>(except yours - change yours first!)</i>.<br/><br/>You should communicate temporary passwords to agents out of band (e.g. via a phone call) and require they are changed ASAP.</h6>
|
||||
<form action="post.php" method="POST">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<div class="row col-7 offset-4">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<input type="password" class="form-control" placeholder="Enter your account password to continue" name="admin_password" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<br>
|
||||
<button class="btn btn-danger" type="submit" name="ir_reset_user_password"><i class="fas fa-fw fa-key mr-2"></i>Reset passwords</button>
|
||||
</form>
|
||||
</div>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg px-5 mr-4" data-dismiss="modal">Cancel</button>
|
||||
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "../../../includes/modal_footer.php";
|
||||
|
||||
@@ -1,16 +1,83 @@
|
||||
<div class="modal" id="archiveUserModal<?php echo $user_id; ?>" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content">
|
||||
<div class="modal-body">
|
||||
<div class="mb-4" style="text-align: center;">
|
||||
<i class="far fa-10x fa-times-circle text-danger mb-3 mt-3"></i>
|
||||
<h2>Are you sure?</h2>
|
||||
<h6 class="mb-4 text-secondary">Do you really want to <b>archive <?php echo $user_name; ?></b>? This process cannot be undone.</h6>
|
||||
<h6 class="mb-4 text-secondary"><?php echo $user_name ?> will no longer be able to log in or use ITFlow, but all associated content will remain accessible.</h6>
|
||||
<button type="button" class="btn btn-outline-secondary btn-lg px-5 mr-4" data-dismiss="modal">Cancel</button>
|
||||
<a class="btn btn-danger btn-lg px-5" href="post.php?archive_user=<?php echo $user_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">Yes, archive!</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
$user_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM users 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_initials = nullable_htmlentities(initials($user_name));
|
||||
|
||||
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
|
||||
WHERE ticket_assigned_to = $user_id AND ticket_resolved_at IS NULL AND ticket_closed_at IS NULL");
|
||||
|
||||
$ticket_count = mysqli_num_rows($sql_related_tickets);
|
||||
|
||||
// Related Recurring Tickets Query
|
||||
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_assigned_to = $user_id");
|
||||
|
||||
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
|
||||
|
||||
// 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-slash mr-2"></i>Archiving user:
|
||||
<strong><?php echo $user_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="user_id" value="<?php echo $user_id; ?>">
|
||||
<div class="modal-body">
|
||||
|
||||
|
||||
<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>Reassign <?= $ticket_count ?> Open Tickets and <?= $recurring_ticket_count ?> Recurring Tickets To:</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>
|
||||
<select class="form-control select2" name="ticket_assign" required>
|
||||
<option value="0">No one</option>
|
||||
<?php
|
||||
$sql_users = mysqli_query($mysqli, "SELECT * FROM users WHERE user_type = 1 AND user_archived_at IS NULL");
|
||||
while ($row = mysqli_fetch_array($sql_users)) {
|
||||
$user_id_select = intval($row['user_id']);
|
||||
$user_name_select = nullable_htmlentities($row['user_name']);
|
||||
|
||||
?>
|
||||
<option value="<?= $user_id_select ?>"><?= $user_name_select ?></option>
|
||||
<?php } ?>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="archive_user" class="btn btn-danger text-bold"><i class="fas fa-archive mr-2"></i>Archive</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";
|
||||
|
||||
@@ -57,7 +57,7 @@ ob_start();
|
||||
|
||||
<center class="mb-3">
|
||||
<?php if (!empty($user_avatar)) { ?>
|
||||
<img class="img-fluid" src="<?php echo "uploads/users/$user_id/$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>
|
||||
@@ -94,11 +94,14 @@ ob_start();
|
||||
<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"
|
||||
<input type="password" class="form-control" data-toggle="password" name="new_password" id="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 class="input-group-append">
|
||||
<span class="btn btn-default"><i class="fa fa-fw fa-question" onclick="generatePassword()"></i></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -200,5 +203,23 @@ ob_start();
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<script>
|
||||
|
||||
function generatePassword() {
|
||||
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
||||
jQuery.get(
|
||||
"/agent/ajax.php", {
|
||||
get_readable_pass: 'true'
|
||||
},
|
||||
function(data) {
|
||||
//If we get a response from post.php, parse it as JSON
|
||||
const password = JSON.parse(data);
|
||||
document.getElementById("password").value = password;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once "../../../includes/modal_footer_new.php";
|
||||
require_once "../../../includes/modal_footer.php";
|
||||
|
||||
@@ -1,45 +1,49 @@
|
||||
<div class="modal" id="userInviteModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</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'] ?>">
|
||||
<div class="modal-body">
|
||||
<?php
|
||||
|
||||
<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" required>
|
||||
</div>
|
||||
</div>
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<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>
|
||||
<option value="">- Role -</option>
|
||||
<!-- //TODO: Pull from roles -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
ob_start();
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
?>
|
||||
<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>×</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'] ?>">
|
||||
<div class="modal-body">
|
||||
|
||||
<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" required>
|
||||
</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>
|
||||
<option value="">- Role -</option>
|
||||
<!-- //TODO: Pull from roles -->
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once "../../../includes/modal_footer.php";
|
||||
|
||||
87
admin/modals/user/user_restore.php
Normal file
87
admin/modals/user/user_restore.php
Normal file
@@ -0,0 +1,87 @@
|
||||
<?php
|
||||
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
$user_id = intval($_GET['id']);
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM users WHERE user_id = $user_id AND user_archived_at IS NOT NULL LIMIT 1");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$user_name = str_replace(" (archived)", "", $row['user_name']); //Removed (archived) from user_name
|
||||
$user_name = nullable_htmlentities($user_name);
|
||||
$user_email = nullable_htmlentities($row['user_email']);
|
||||
$user_avatar = nullable_htmlentities($row['user_avatar']);
|
||||
$user_initials = initials($user_name);
|
||||
$user_role_id = intval($row['user_role_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-redo-alt mr-2"></i>Restoring user:
|
||||
<strong><?php echo $user_name; ?></strong></h5>
|
||||
<button type="button" class="close text-white" data-dismiss="modal">
|
||||
<span>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<input type="hidden" name="user_id" value="<?php echo $user_id; ?>">
|
||||
<div class="modal-body">
|
||||
|
||||
|
||||
<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>Set a 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="Enter a new password" autocomplete="new-password" required>
|
||||
<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>
|
||||
<div class="modal-footer">
|
||||
<button type="submit" name="restore_user" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Restore</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";
|
||||
@@ -1,168 +1,171 @@
|
||||
<div class="modal" id="addVendorTemplateModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<?php
|
||||
|
||||
<input type="hidden" name="client_id" value="<?php if (isset($_GET['client_id'])) { echo $client_id; } else { echo 0; } ?>">
|
||||
require_once '../../../includes/modal_header.php';
|
||||
|
||||
<div class="modal-body">
|
||||
ob_start();
|
||||
|
||||
<ul class="nav nav-pills nav-justified mb-3">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link active" data-toggle="pill" href="#pills-details">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-support">Support</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
|
||||
</li>
|
||||
</ul>
|
||||
?>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-details">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Vendor 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-building"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Vendor Name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Description" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Account Number</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-fingerprint"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="account_number" placeholder="Account number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Account Manager</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="contact_name" placeholder="Account manager's name" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-support">
|
||||
|
||||
<label>Support Phone / <span class="text-secondary">Extension</span></label>
|
||||
<div class="form-row">
|
||||
<div class="col-9">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="extension" placeholder="ext." maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Hours</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="hours" placeholder="Support Hours" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Email</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="Support Email" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Website URL</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="text" class="form-control" name="website" placeholder="Do not include http(s)://" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Pin/Code</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="code" placeholder="Access Code or Pin" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SLA</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-handshake"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="sla" placeholder="SLA Response Time" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-notes">
|
||||
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
<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>×</span>
|
||||
</button>
|
||||
</div>
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
|
||||
<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-details">Details</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-support">Support</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link" data-toggle="pill" href="#pills-notes">Notes</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
|
||||
<div class="tab-content">
|
||||
|
||||
<div class="tab-pane fade show active" id="pills-details">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Vendor 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-building"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="name" placeholder="Vendor Name" maxlength="200" required autofocus>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-angle-right"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="description" placeholder="Description" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Account Number</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-fingerprint"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="account_number" placeholder="Account number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Account Manager</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="contact_name" placeholder="Account manager's name" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-support">
|
||||
|
||||
<label>Support Phone / <span class="text-secondary">Extension</span></label>
|
||||
<div class="form-row">
|
||||
<div class="col-9">
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
|
||||
</div>
|
||||
<input type="tel" class="form-control col-2" name="phone_country_code" placeholder="+" maxlength="4">
|
||||
<input type="tel" class="form-control" name="phone" placeholder="Phone Number" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-3">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="extension" placeholder="ext." maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Hours</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="hours" placeholder="Support Hours" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Email</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="Support Email" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Support Website URL</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="text" class="form-control" name="website" placeholder="Do not include http(s)://" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Pin/Code</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="code" placeholder="Access Code or Pin" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SLA</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-handshake"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="sla" placeholder="SLA Response Time" maxlength="200">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="pills-notes">
|
||||
|
||||
<div class="form-group">
|
||||
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"></textarea>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<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>
|
||||
</form>
|
||||
|
||||
<?php
|
||||
require_once '../../../includes/modal_footer.php';
|
||||
|
||||
113
admin/modules.php
Normal file
113
admin/modules.php
Normal file
@@ -0,0 +1,113 @@
|
||||
<?php
|
||||
|
||||
// Default Column Sortby Filter
|
||||
$sort = "module_name";
|
||||
$order = "DESC";
|
||||
|
||||
require_once "includes/inc_all_admin.php";
|
||||
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM modules
|
||||
WHERE (module_name LIKE '%$q%' OR module_description LIKE '%$q%')
|
||||
ORDER BY $sort $order LIMIT $record_from, $record_to"
|
||||
);
|
||||
|
||||
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-puzzle-piece mr-2"></i>Access Modules</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/module/module_add.php">
|
||||
<i class="fas fa-fw fa-plus mr-2"></i>New Module
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form class="mb-4" autocomplete="off">
|
||||
<div class="row">
|
||||
<div class="col-md-4">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {echo stripslashes(nullable_htmlentities($q));} ?>" placeholder="Search Modules">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=module_name&order=<?php echo $disp; ?>">
|
||||
Module <?php if ($sort == 'module_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$module_id = intval($row['module_id']);
|
||||
$module_name = nullable_htmlentities($row['module_name']);
|
||||
$module_description = nullable_htmlentities($row['module_description']);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<a href="#" <?php if ($module_id > 6) { ?> class="ajax-modal" data-modal-url="modals/modules/module_edit.php?id=<?= $module_id ?>" <?php } ?>>
|
||||
<strong class="text-dark"><?= $module_name ?></strong>
|
||||
</a>
|
||||
<div class="text-secondary"><?= $module_description ?></div>
|
||||
</td>
|
||||
<td>
|
||||
<?php if ($module_id > 6) { ?>
|
||||
<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/module/module_edit.php?id=<?= $module_id ?>">
|
||||
<i class="fas fa-fw fa-user-edit mr-2"></i>Edit
|
||||
</a>
|
||||
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_module=<?= $module_id ?>&csrf_token=<?= $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-archive mr-2"></i>Delete
|
||||
</a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<?php } else { echo "<p class='text-center'>N/A Predefined</p>"; } ?>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php require_once "../includes/filter_footer.php";
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
require_once "../includes/footer.php";
|
||||
@@ -16,7 +16,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||
<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>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/payment_method/payment_method_add.php"><i class="fas fa-plus mr-2"></i>Add Payment Method</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -98,5 +98,4 @@ $num_rows = mysqli_num_rows($sql);
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/payment_method/payment_method_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -21,7 +21,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||
<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>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/payment_provider/payment_provider_add.php"><i class="fas fa-plus mr-2"></i>Add Provider</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -55,7 +55,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark">Fee</a>
|
||||
<a class="text-dark">Expensed Fee</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark">Saved Payment Methods</a>
|
||||
@@ -93,7 +93,7 @@ $num_rows = mysqli_num_rows($sql);
|
||||
<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 $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">
|
||||
@@ -106,8 +106,13 @@ $num_rows = mysqli_num_rows($sql);
|
||||
<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 class="dropdown-item text-danger confirm-link" href="post.php?delete_payment_provider=<?= $provider_id ?>&csrf_token=<?= $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i><strong>Delete Provider and</strong>
|
||||
<ul class="text-xs">
|
||||
<li>Related Recurring Payments</li>
|
||||
<li>Related Saved cards</li>
|
||||
<li>Client Provider Relations</li>
|
||||
</ul>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
@@ -132,5 +137,4 @@ $num_rows = mysqli_num_rows($sql);
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/payment_provider/payment_provider_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -36,7 +36,4 @@ if (isset($session_is_admin) && $session_is_admin) {
|
||||
require_once "../post/logout.php";
|
||||
|
||||
// TODO: Find a home for these
|
||||
|
||||
require_once "../post/ai.php";
|
||||
require_once "../post/misc.php";
|
||||
|
||||
|
||||
@@ -2,185 +2,304 @@
|
||||
|
||||
/*
|
||||
* ITFlow - GET/POST request handler for DB / master key backup
|
||||
* Rewritten with streaming SQL dump, component checksums, safer zipping, and better headers.
|
||||
*/
|
||||
|
||||
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
|
||||
|
||||
require_once "../includes/app_version.php";
|
||||
|
||||
// --- Optional performance levers for big backups ---
|
||||
@set_time_limit(0);
|
||||
if (function_exists('ini_set')) {
|
||||
@ini_set('memory_limit', '1024M');
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a line to a file handle with newline.
|
||||
*/
|
||||
function fwrite_ln($fh, string $s): void {
|
||||
fwrite($fh, $s);
|
||||
fwrite($fh, PHP_EOL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Stream a SQL dump of schema and data into $sqlFile.
|
||||
* - Tables first (DROP + CREATE + INSERTs)
|
||||
* - Views (DROP VIEW + CREATE VIEW)
|
||||
* - Triggers (DROP TRIGGER + CREATE TRIGGER)
|
||||
*
|
||||
* NOTE: Routines/events are not dumped here. Add if needed.
|
||||
*/
|
||||
function dump_database_streaming(mysqli $mysqli, string $sqlFile): void {
|
||||
$fh = fopen($sqlFile, 'wb');
|
||||
if (!$fh) {
|
||||
http_response_code(500);
|
||||
exit("Cannot open dump file");
|
||||
}
|
||||
|
||||
// Preamble
|
||||
fwrite_ln($fh, "-- UTF-8 + Foreign Key Safe Dump");
|
||||
fwrite_ln($fh, "SET NAMES 'utf8mb4';");
|
||||
fwrite_ln($fh, "SET FOREIGN_KEY_CHECKS = 0;");
|
||||
fwrite_ln($fh, "SET UNIQUE_CHECKS = 0;");
|
||||
fwrite_ln($fh, "SET AUTOCOMMIT = 0;");
|
||||
fwrite_ln($fh, "");
|
||||
|
||||
// Gather tables and views
|
||||
$tables = [];
|
||||
$views = [];
|
||||
|
||||
$res = $mysqli->query("SHOW FULL TABLES");
|
||||
if (!$res) {
|
||||
fclose($fh);
|
||||
error_log("MySQL Error (SHOW FULL TABLES): " . $mysqli->error);
|
||||
http_response_code(500);
|
||||
exit("Error retrieving tables.");
|
||||
}
|
||||
while ($row = $res->fetch_array(MYSQLI_NUM)) {
|
||||
$name = $row[0];
|
||||
$type = strtoupper($row[1] ?? '');
|
||||
if ($type === 'VIEW') {
|
||||
$views[] = $name;
|
||||
} else {
|
||||
$tables[] = $name;
|
||||
}
|
||||
}
|
||||
$res->close();
|
||||
|
||||
// --- TABLES: structure and data ---
|
||||
foreach ($tables as $table) {
|
||||
$createRes = $mysqli->query("SHOW CREATE TABLE `{$mysqli->real_escape_string($table)}`");
|
||||
if (!$createRes) {
|
||||
error_log("MySQL Error (SHOW CREATE TABLE $table): " . $mysqli->error);
|
||||
// continue to next table
|
||||
continue;
|
||||
}
|
||||
$createRow = $createRes->fetch_assoc();
|
||||
$createSQL = array_values($createRow)[1] ?? '';
|
||||
$createRes->close();
|
||||
|
||||
fwrite_ln($fh, "-- ----------------------------");
|
||||
fwrite_ln($fh, "-- Table structure for `{$table}`");
|
||||
fwrite_ln($fh, "-- ----------------------------");
|
||||
fwrite_ln($fh, "DROP TABLE IF EXISTS `{$table}`;");
|
||||
fwrite_ln($fh, $createSQL . ";");
|
||||
fwrite_ln($fh, "");
|
||||
|
||||
// Dump data in a streaming fashion
|
||||
$dataRes = $mysqli->query("SELECT * FROM `{$mysqli->real_escape_string($table)}`", MYSQLI_USE_RESULT);
|
||||
if ($dataRes) {
|
||||
$wroteHeader = false;
|
||||
while ($row = $dataRes->fetch_assoc()) {
|
||||
if (!$wroteHeader) {
|
||||
fwrite_ln($fh, "-- Dumping data for table `{$table}`");
|
||||
$wroteHeader = true;
|
||||
}
|
||||
$cols = array_map(fn($c) => '`' . $mysqli->real_escape_string($c) . '`', array_keys($row));
|
||||
$vals = array_map(
|
||||
function ($v) use ($mysqli) {
|
||||
return is_null($v) ? "NULL" : "'" . $mysqli->real_escape_string($v) . "'";
|
||||
},
|
||||
array_values($row)
|
||||
);
|
||||
fwrite_ln($fh, "INSERT INTO `{$table}` (" . implode(", ", $cols) . ") VALUES (" . implode(", ", $vals) . ");");
|
||||
}
|
||||
$dataRes->close();
|
||||
if ($wroteHeader) fwrite_ln($fh, "");
|
||||
}
|
||||
}
|
||||
|
||||
// --- VIEWS ---
|
||||
foreach ($views as $view) {
|
||||
$escView = $mysqli->real_escape_string($view);
|
||||
$cRes = $mysqli->query("SHOW CREATE VIEW `{$escView}`");
|
||||
if ($cRes) {
|
||||
$row = $cRes->fetch_assoc();
|
||||
$createView = $row['Create View'] ?? '';
|
||||
$cRes->close();
|
||||
|
||||
fwrite_ln($fh, "-- ----------------------------");
|
||||
fwrite_ln($fh, "-- View structure for `{$view}`");
|
||||
fwrite_ln($fh, "-- ----------------------------");
|
||||
fwrite_ln($fh, "DROP VIEW IF EXISTS `{$view}`;");
|
||||
// Ensure statement ends with semicolon
|
||||
if (!str_ends_with($createView, ';')) $createView .= ';';
|
||||
fwrite_ln($fh, $createView);
|
||||
fwrite_ln($fh, "");
|
||||
}
|
||||
}
|
||||
|
||||
// --- TRIGGERS ---
|
||||
$tRes = $mysqli->query("SHOW TRIGGERS");
|
||||
if ($tRes) {
|
||||
while ($t = $tRes->fetch_assoc()) {
|
||||
$triggerName = $t['Trigger'];
|
||||
$escTrig = $mysqli->real_escape_string($triggerName);
|
||||
$crt = $mysqli->query("SHOW CREATE TRIGGER `{$escTrig}`");
|
||||
if ($crt) {
|
||||
$row = $crt->fetch_assoc();
|
||||
$createTrig = $row['SQL Original Statement'] ?? ($row['Create Trigger'] ?? '');
|
||||
$crt->close();
|
||||
|
||||
fwrite_ln($fh, "-- ----------------------------");
|
||||
fwrite_ln($fh, "-- Trigger for `{$triggerName}`");
|
||||
fwrite_ln($fh, "-- ----------------------------");
|
||||
fwrite_ln($fh, "DROP TRIGGER IF EXISTS `{$triggerName}`;");
|
||||
if (!str_ends_with($createTrig, ';')) $createTrig .= ';';
|
||||
fwrite_ln($fh, $createTrig);
|
||||
fwrite_ln($fh, "");
|
||||
}
|
||||
}
|
||||
$tRes->close();
|
||||
}
|
||||
|
||||
// Postamble
|
||||
fwrite_ln($fh, "SET FOREIGN_KEY_CHECKS = 1;");
|
||||
fwrite_ln($fh, "SET UNIQUE_CHECKS = 1;");
|
||||
fwrite_ln($fh, "COMMIT;");
|
||||
|
||||
fclose($fh);
|
||||
}
|
||||
|
||||
/**
|
||||
* Zip a folder to $zipFilePath, skipping symlinks and dot-entries.
|
||||
*/
|
||||
function zipFolderStrict(string $folderPath, string $zipFilePath): void {
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
|
||||
error_log("Failed to open zip file: $zipFilePath");
|
||||
http_response_code(500);
|
||||
exit("Internal Server Error: Cannot open zip archive.");
|
||||
}
|
||||
|
||||
$folderReal = realpath($folderPath);
|
||||
if (!$folderReal || !is_dir($folderReal)) {
|
||||
// Create an empty archive if uploads folder doesn't exist yet
|
||||
$zip->close();
|
||||
return;
|
||||
}
|
||||
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($folderReal, FilesystemIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $file) {
|
||||
/** @var SplFileInfo $file */
|
||||
if ($file->isDir()) continue;
|
||||
if ($file->isLink()) continue; // skip symlinks
|
||||
$filePath = $file->getRealPath();
|
||||
if ($filePath === false) continue;
|
||||
|
||||
// ensure path is inside the folder boundary
|
||||
if (strpos($filePath, $folderReal . DIRECTORY_SEPARATOR) !== 0 && $filePath !== $folderReal) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$relativePath = substr($filePath, strlen($folderReal) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
}
|
||||
|
||||
if (isset($_GET['download_backup'])) {
|
||||
|
||||
validateCSRFToken($_GET['csrf_token']);
|
||||
|
||||
$timestamp = date('YmdHis');
|
||||
$baseName = "itflow_$timestamp";
|
||||
$timestamp = date('YmdHis');
|
||||
$baseName = "itflow_{$timestamp}";
|
||||
$downloadName = $baseName . ".zip";
|
||||
|
||||
// === 0. Scoped cleanup ===
|
||||
// === Scoped cleanup of temp files ===
|
||||
$cleanupFiles = [];
|
||||
|
||||
$registerTempFileForCleanup = function ($file) use (&$cleanupFiles) {
|
||||
$cleanupFiles[] = $file;
|
||||
};
|
||||
|
||||
register_shutdown_function(function () use (&$cleanupFiles) {
|
||||
foreach ($cleanupFiles as $file) {
|
||||
if (is_file($file)) {
|
||||
@unlink($file);
|
||||
}
|
||||
if (is_file($file)) { @unlink($file); }
|
||||
}
|
||||
});
|
||||
|
||||
// === 1. Local helper function: zipFolder
|
||||
$zipFolder = function ($folderPath, $zipFilePath) {
|
||||
$zip = new ZipArchive();
|
||||
if ($zip->open($zipFilePath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
|
||||
error_log("Failed to open zip file: $zipFilePath");
|
||||
http_response_code(500);
|
||||
exit("Internal Server Error: Cannot open zip archive.");
|
||||
}
|
||||
|
||||
$folderPath = realpath($folderPath);
|
||||
if (!$folderPath) {
|
||||
error_log("Invalid folder path: $folderPath");
|
||||
http_response_code(500);
|
||||
exit("Internal Server Error: Invalid folder path.");
|
||||
}
|
||||
|
||||
$files = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($folderPath),
|
||||
RecursiveIteratorIterator::LEAVES_ONLY
|
||||
);
|
||||
|
||||
foreach ($files as $file) {
|
||||
if (!$file->isDir()) {
|
||||
$filePath = $file->getRealPath();
|
||||
$relativePath = substr($filePath, strlen($folderPath) + 1);
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
}
|
||||
}
|
||||
|
||||
$zip->close();
|
||||
};
|
||||
|
||||
// === 2. Create all temp files
|
||||
$sqlFile = tempnam(sys_get_temp_dir(), $baseName . "_sql_");
|
||||
$uploadsZip = tempnam(sys_get_temp_dir(), $baseName . "_uploads_");
|
||||
// === Create temp files ===
|
||||
$sqlFile = tempnam(sys_get_temp_dir(), $baseName . "_sql_");
|
||||
$uploadsZip = tempnam(sys_get_temp_dir(), $baseName . "_uploads_");
|
||||
$versionFile = tempnam(sys_get_temp_dir(), $baseName . "_version_");
|
||||
$finalZip = tempnam(sys_get_temp_dir(), $baseName . "_backup_");
|
||||
$finalZip = tempnam(sys_get_temp_dir(), $baseName . "_backup_");
|
||||
|
||||
foreach ([$sqlFile, $uploadsZip, $versionFile, $finalZip] as $f) {
|
||||
$registerTempFileForCleanup($f);
|
||||
chmod($f, 0600);
|
||||
@chmod($f, 0600);
|
||||
}
|
||||
|
||||
// === 3. Generate SQL Dump
|
||||
$sqlContent = "-- UTF-8 + Foreign Key Safe Dump\n";
|
||||
$sqlContent .= "SET NAMES 'utf8mb4';\n";
|
||||
$sqlContent .= "SET foreign_key_checks = 0;\n\n";
|
||||
// === Generate SQL Dump (streaming) ===
|
||||
dump_database_streaming($mysqli, $sqlFile);
|
||||
|
||||
$tables = [];
|
||||
$res = $mysqli->query("SHOW TABLES");
|
||||
if (!$res) {
|
||||
error_log("MySQL Error: " . $mysqli->error);
|
||||
exit("Error retrieving tables.");
|
||||
}
|
||||
// === Zip the uploads folder (strict) ===
|
||||
zipFolderStrict("../uploads", $uploadsZip);
|
||||
|
||||
while ($row = $res->fetch_row()) {
|
||||
$tables[] = $row[0];
|
||||
}
|
||||
// === Gather metadata & checksums ===
|
||||
$commitHash = (function_exists('shell_exec') ? trim(shell_exec('git log -1 --format=%H 2>/dev/null')) : '') ?: 'N/A';
|
||||
$gitBranch = (function_exists('shell_exec') ? trim(shell_exec('git rev-parse --abbrev-ref HEAD 2>/dev/null')) : '') ?: 'N/A';
|
||||
|
||||
foreach ($tables as $table) {
|
||||
$createRes = $mysqli->query("SHOW CREATE TABLE `$table`");
|
||||
if (!$createRes) {
|
||||
error_log("MySQL Error: " . $mysqli->error);
|
||||
continue;
|
||||
}
|
||||
$dbSha = hash_file('sha256', $sqlFile) ?: 'N/A';
|
||||
$upSha = hash_file('sha256', $uploadsZip) ?: 'N/A';
|
||||
|
||||
$createRow = $createRes->fetch_assoc();
|
||||
$createSQL = array_values($createRow)[1];
|
||||
|
||||
$sqlContent .= "\n-- ----------------------------\n";
|
||||
$sqlContent .= "-- Table structure for `$table`\n";
|
||||
$sqlContent .= "-- ----------------------------\n";
|
||||
$sqlContent .= "DROP TABLE IF EXISTS `$table`;\n";
|
||||
$sqlContent .= $createSQL . ";\n\n";
|
||||
|
||||
$dataRes = $mysqli->query("SELECT * FROM `$table`");
|
||||
if ($dataRes && $dataRes->num_rows > 0) {
|
||||
$sqlContent .= "-- Dumping data for table `$table`\n";
|
||||
while ($row = $dataRes->fetch_assoc()) {
|
||||
$columns = array_map(fn($col) => '`' . $mysqli->real_escape_string($col) . '`', array_keys($row));
|
||||
$values = array_map(function ($val) use ($mysqli) {
|
||||
return is_null($val) ? "NULL" : "'" . $mysqli->real_escape_string($val) . "'";
|
||||
}, array_values($row));
|
||||
$sqlContent .= "INSERT INTO `$table` (" . implode(", ", $columns) . ") VALUES (" . implode(", ", $values) . ");\n";
|
||||
}
|
||||
$sqlContent .= "\n";
|
||||
}
|
||||
}
|
||||
|
||||
$sqlContent .= "SET foreign_key_checks = 1;\n";
|
||||
file_put_contents($sqlFile, $sqlContent);
|
||||
|
||||
// === 4. Zip the uploads folder
|
||||
$zipFolder("../uploads", $uploadsZip);
|
||||
|
||||
// === 5. Create version.txt
|
||||
$commitHash = trim(shell_exec('git log -1 --format=%H')) ?: 'N/A';
|
||||
$gitBranch = trim(shell_exec('git rev-parse --abbrev-ref HEAD')) ?: 'N/A';
|
||||
|
||||
$versionContent = "ITFlow Backup Metadata\n";
|
||||
$versionContent = "ITFlow Backup Metadata\n";
|
||||
$versionContent .= "-----------------------------\n";
|
||||
$versionContent .= "Generated: " . date('Y-m-d H:i:s') . "\n";
|
||||
$versionContent .= "Backup File: " . basename($finalZip) . "\n";
|
||||
$versionContent .= "Generated By: $session_name\n";
|
||||
$versionContent .= "Backup File: " . $downloadName . "\n";
|
||||
$versionContent .= "Generated By: " . ($session_name ?? 'Unknown User') . "\n";
|
||||
$versionContent .= "Host: " . gethostname() . "\n";
|
||||
$versionContent .= "Git Branch: $gitBranch\n";
|
||||
$versionContent .= "Git Commit: $commitHash\n";
|
||||
$versionContent .= "ITFlow Version: " . (defined('APP_VERSION') ? APP_VERSION : 'Unknown') . "\n";
|
||||
$versionContent .= "Database Version: " . (defined('CURRENT_DATABASE_VERSION') ? CURRENT_DATABASE_VERSION : 'Unknown') . "\n";
|
||||
$versionContent .= "Checksum (SHA256): \n";
|
||||
$versionContent .= "Checksums (SHA256):\n";
|
||||
$versionContent .= " db.sql: $dbSha\n";
|
||||
$versionContent .= " uploads.zip: $upSha\n";
|
||||
|
||||
file_put_contents($versionFile, $versionContent);
|
||||
@chmod($versionFile, 0600);
|
||||
|
||||
// === 6. Build final ZIP
|
||||
// === Build final ZIP ===
|
||||
$final = new ZipArchive();
|
||||
if ($final->open($finalZip, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== TRUE) {
|
||||
error_log("Failed to create final zip: $finalZip");
|
||||
http_response_code(500);
|
||||
exit("Internal Server Error: Unable to create backup archive.");
|
||||
}
|
||||
|
||||
$final->addFile($sqlFile, "db.sql");
|
||||
$final->addFile($uploadsZip, "uploads.zip");
|
||||
$final->addFile($versionFile, "version.txt");
|
||||
$final->close();
|
||||
|
||||
chmod($finalZip, 0600);
|
||||
@chmod($finalZip, 0600);
|
||||
|
||||
$checksum = hash_file('sha256', $finalZip);
|
||||
file_put_contents($versionFile, $versionContent . "$checksum\n");
|
||||
|
||||
// === 7. Serve final ZIP
|
||||
// === Serve final ZIP with a stable filename ===
|
||||
header('Content-Type: application/zip');
|
||||
header('Content-Disposition: attachment; filename="' . basename($finalZip) . '"');
|
||||
header('X-Content-Type-Options: nosniff');
|
||||
header('Content-Disposition: attachment; filename="' . $downloadName . '"');
|
||||
header('Content-Length: ' . filesize($finalZip));
|
||||
header('Pragma: public');
|
||||
header('Expires: 0');
|
||||
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
|
||||
header('Content-Transfer-Encoding: binary');
|
||||
|
||||
// Push file
|
||||
flush();
|
||||
$fp = fopen($finalZip, 'rb');
|
||||
fpassthru($fp);
|
||||
fclose($fp);
|
||||
|
||||
logAction("System", "Backup Download", "$session_name downloaded full backup.");
|
||||
// Log + UX
|
||||
logAction("System", "Backup Download", ($session_name ?? 'Unknown User') . " downloaded full backup.");
|
||||
flash_alert("Full backup downloaded.");
|
||||
exit;
|
||||
}
|
||||
|
||||
|
||||
if (isset($_POST['backup_master_key'])) {
|
||||
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
157
admin/post/contract_template.php
Normal file
157
admin/post/contract_template.php
Normal file
@@ -0,0 +1,157 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* ITFlow - GET/POST request handler for Contract Templates
|
||||
*/
|
||||
|
||||
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
|
||||
|
||||
if (isset($_POST['add_contract_template'])) {
|
||||
|
||||
// Sanitize text inputs
|
||||
$name = sanitizeInput($_POST['name']);
|
||||
$description = sanitizeInput($_POST['description']);
|
||||
$type = sanitizeInput($_POST['type']);
|
||||
$renewal_frequency = sanitizeInput($_POST['renewal_frequency']);
|
||||
$support_hours = sanitizeInput($_POST['support_hours']);
|
||||
$details = mysqli_escape_string($mysqli, $_POST['details']);
|
||||
|
||||
// Numeric fields cast to integer
|
||||
$sla_low_resp = intval($_POST['sla_low_response_time']);
|
||||
$sla_med_resp = intval($_POST['sla_medium_response_time']);
|
||||
$sla_high_resp = intval($_POST['sla_high_response_time']);
|
||||
$sla_low_res = intval($_POST['sla_low_resolution_time']);
|
||||
$sla_med_res = intval($_POST['sla_medium_resolution_time']);
|
||||
$sla_high_res = intval($_POST['sla_high_resolution_time']);
|
||||
$rate_standard = intval($_POST['rate_standard']);
|
||||
$rate_after_hours = intval($_POST['hourly_rate_after_hours']);
|
||||
$net_terms = intval($_POST['net_terms']);
|
||||
|
||||
// Insert into database (numbers not quoted)
|
||||
mysqli_query($mysqli, "
|
||||
INSERT INTO contract_templates SET
|
||||
contract_template_name = '$name',
|
||||
contract_template_description = '$description',
|
||||
contract_template_details = '$details',
|
||||
contract_template_type = '$type',
|
||||
contract_template_renewal_frequency = '$renewal_frequency',
|
||||
contract_template_sla_low_response_time = $sla_low_resp,
|
||||
contract_template_sla_medium_response_time = $sla_med_resp,
|
||||
contract_template_sla_high_response_time = $sla_high_resp,
|
||||
contract_template_sla_low_resolution_time = $sla_low_res,
|
||||
contract_template_sla_medium_resolution_time = $sla_med_res,
|
||||
contract_template_sla_high_resolution_time = $sla_high_res,
|
||||
contract_template_rate_standard = $rate_standard,
|
||||
contract_template_rate_after_hours = $rate_after_hours,
|
||||
contract_template_support_hours = '$support_hours',
|
||||
contract_template_net_terms = $net_terms
|
||||
");
|
||||
|
||||
$contract_template_id = mysqli_insert_id($mysqli);
|
||||
|
||||
// Log action
|
||||
logAction("Contract Template", "Create", "$session_name created contract template $name", 0, $contract_template_id);
|
||||
|
||||
// Flash message
|
||||
flash_alert("Contract Template <strong>$name</strong> created");
|
||||
|
||||
// Redirect back
|
||||
redirect();
|
||||
}
|
||||
|
||||
if (isset($_POST['edit_contract_template'])) {
|
||||
|
||||
$contract_template_id = intval($_POST['contract_template_id']);
|
||||
$name = sanitizeInput($_POST['name']);
|
||||
$description = sanitizeInput($_POST['description']);
|
||||
$type = sanitizeInput($_POST['type']);
|
||||
$renewal_frequency= sanitizeInput($_POST['renewal_frequency']);
|
||||
$support_hours = sanitizeInput($_POST['support_hours']);
|
||||
$details = mysqli_escape_string($mysqli, $_POST['details']);
|
||||
$sla_low_resp = intval($_POST['sla_low_response_time']);
|
||||
$sla_med_resp = intval($_POST['sla_medium_response_time']);
|
||||
$sla_high_resp = intval($_POST['sla_high_response_time']);
|
||||
$sla_low_res = intval($_POST['sla_low_resolution_time']);
|
||||
$sla_med_res = intval($_POST['sla_medium_resolution_time']);
|
||||
$sla_high_res = intval($_POST['sla_high_resolution_time']);
|
||||
$rate_standard = intval($_POST['rate_standard']);
|
||||
$rate_after_hours = intval($_POST['rate_after_hours']);
|
||||
$net_terms = intval($_POST['net_terms']);
|
||||
|
||||
mysqli_query($mysqli, "
|
||||
UPDATE contract_templates SET
|
||||
contract_template_name = '$name',
|
||||
contract_template_description = '$description',
|
||||
contract_template_details = '$details',
|
||||
contract_template_type = '$type',
|
||||
contract_template_renewal_frequency = '$renewal_frequency',
|
||||
contract_template_sla_low_response_time = $sla_low_resp,
|
||||
contract_template_sla_medium_response_time = $sla_med_resp,
|
||||
contract_template_sla_high_response_time = $sla_high_resp,
|
||||
contract_template_sla_low_resolution_time = $sla_low_res,
|
||||
contract_template_sla_medium_resolution_time = $sla_med_res,
|
||||
contract_template_sla_high_resolution_time = $sla_high_res,
|
||||
contract_template_rate_standard = $rate_standard,
|
||||
contract_template_rate_after_hours = $rate_after_hours,
|
||||
contract_template_support_hours = '$support_hours',
|
||||
contract_template_net_terms = $net_terms
|
||||
WHERE contract_template_id = $contract_template_id
|
||||
");
|
||||
|
||||
// Log action
|
||||
logAction("Contract Template", "Update", "$session_name updated contract template $name", 0, $contract_template_id);
|
||||
|
||||
// Flash + redirect
|
||||
flash_alert("Contract Template <strong>$name</strong> updated");
|
||||
redirect();
|
||||
}
|
||||
|
||||
if (isset($_GET['archive_contract_template'])) {
|
||||
$contract_template_id = intval($_GET['archive_contract_template']);
|
||||
|
||||
$name = getFieldById('contract_templates', $contract_template_id, 'contract_template_name');
|
||||
|
||||
mysqli_query($mysqli, "
|
||||
UPDATE contract_templates SET contract_template_archived_at = NOW()
|
||||
WHERE contract_template_id = $contract_template_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
logAction("Contract Template", "Archive", "$session_name archived contract template $name", 0, $contract_template_id);
|
||||
flash_alert("Contract Template <strong>$name</strong> archived", "danger");
|
||||
redirect();
|
||||
}
|
||||
|
||||
if (isset($_GET['restore_contract_template'])) {
|
||||
$contract_template_id = intval($_GET['restore_contract_template']);
|
||||
|
||||
$name = getFieldById('contract_templates', $contract_template_id, 'contract_template_name');
|
||||
|
||||
mysqli_query($mysqli, "
|
||||
UPDATE contract_templates SET contract_template_archived_at = NULL
|
||||
WHERE contract_template_id = $contract_template_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
logAction("Contract Template", "Restore", "$session_name restored contract template $name", 0, $contract_template_id);
|
||||
flash_alert("Contract Template <strong>$name</strong> restored");
|
||||
redirect();
|
||||
}
|
||||
|
||||
if (isset($_GET['delete_contract_template'])) {
|
||||
$contract_template_id = intval($_GET['delete_contract_template']);
|
||||
|
||||
$name = getFieldById('contract_templates', $contract_template_id, 'contract_template_name');
|
||||
|
||||
mysqli_query($mysqli, "
|
||||
DELETE FROM contract_templates
|
||||
WHERE contract_template_id = $contract_template_id
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
logAction("Contract Template", "Delete", "$session_name deleted contract template $name", 0, $contract_template_id);
|
||||
flash_alert("Contract Template <strong>$name</strong> deleted", "danger");
|
||||
redirect();
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -8,12 +8,24 @@ if (isset($_POST['add_document_template'])) {
|
||||
|
||||
$name = sanitizeInput($_POST['name']);
|
||||
$description = sanitizeInput($_POST['description']);
|
||||
$content = mysqli_real_escape_string($mysqli,$_POST['content']);
|
||||
|
||||
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");
|
||||
mysqli_query($mysqli,"INSERT INTO document_templates SET document_template_name = '$name', document_template_description = '$description', document_template_content = '', document_template_created_by = $session_user_id");
|
||||
|
||||
$document_template_id = mysqli_insert_id($mysqli);
|
||||
|
||||
$processed_content = mysqli_escape_string(
|
||||
$mysqli,
|
||||
saveBase64Images(
|
||||
$_POST['content'],
|
||||
$_SERVER['DOCUMENT_ROOT'] . "/uploads/document_templates/",
|
||||
"uploads/document_templates/",
|
||||
$document_template_id
|
||||
)
|
||||
);
|
||||
|
||||
// Document template update content
|
||||
mysqli_query($mysqli,"UPDATE document_templates SET document_template_content = '$processed_content' WHERE document_template_id = $document_template_id");
|
||||
|
||||
logAction("Document Template", "Create", "$session_name created document template $name", 0, $document_template_id);
|
||||
|
||||
flash_alert("Document template <strong>$name</strong> created");
|
||||
@@ -27,10 +39,25 @@ if (isset($_POST['edit_document_template'])) {
|
||||
$document_template_id = intval($_POST['document_template_id']);
|
||||
$name = sanitizeInput($_POST['name']);
|
||||
$description = sanitizeInput($_POST['description']);
|
||||
$content = mysqli_real_escape_string($mysqli,$_POST['content']);
|
||||
|
||||
$processed_content = saveBase64Images(
|
||||
$_POST['content'],
|
||||
$_SERVER['DOCUMENT_ROOT'] . "/uploads/document_templates/",
|
||||
"uploads/document_templates/",
|
||||
$document_template_id
|
||||
);
|
||||
|
||||
$processed_content_escaped = mysqli_escape_string($mysqli, $processed_content);
|
||||
|
||||
// CLEAN UP unused images
|
||||
cleanupUnusedImages(
|
||||
$processed_content,
|
||||
$_SERVER['DOCUMENT_ROOT'] . "/uploads/document_templates/" . $document_template_id,
|
||||
"/uploads/document_templates/" . $document_template_id
|
||||
);
|
||||
|
||||
// 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");
|
||||
mysqli_query($mysqli,"UPDATE document_templates SET document_template_name = '$name', document_template_description = '$description', document_template_content = '$processed_content_escaped', document_template_updated_by = $session_user_id WHERE document_template_id = $document_template_id");
|
||||
|
||||
logAction("Document Template", "Edit", "$session_name edited document template $name", 0, $document_template_id);
|
||||
|
||||
@@ -48,6 +75,9 @@ if (isset($_GET['delete_document_template'])) {
|
||||
|
||||
mysqli_query($mysqli,"DELETE FROM document_templates WHERE document_template_id = $document_template_id");
|
||||
|
||||
// Delete uploads/document_templates/$document_template_id if exists
|
||||
removeDirectory($_SERVER['DOCUMENT_ROOT'] . "/uploads/document_templates/" . $document_template_id);
|
||||
|
||||
logAction("Document Template", "Delete", "$session_name deleted document template $document_template_name");
|
||||
|
||||
flash_alert("Document Template <strong>$document_template_name</strong> deleted", 'error');
|
||||
|
||||
@@ -10,10 +10,17 @@ if (isset($_POST['add_payment_method'])) {
|
||||
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
$name = sanitizeInput($_POST['name']);
|
||||
$description = sanitizeInput($_POST['description']);
|
||||
$name = cleanInput($_POST['name']);
|
||||
$description = cleanInput($_POST['description']);
|
||||
|
||||
mysqli_query($mysqli,"INSERT INTO payment_methods SET payment_method_name = '$name', payment_method_description = '$description'");
|
||||
$query = mysqli_prepare(
|
||||
$mysqli, "INSERT INTO payment_methods
|
||||
SET payment_method_name = ?, payment_method_description = ?"
|
||||
);
|
||||
|
||||
mysqli_stmt_bind_param($query, "ss", $name, $description);
|
||||
|
||||
mysqli_stmt_execute($query);
|
||||
|
||||
logAction("Payment Method", "Create", "$session_name created Payment Method $name");
|
||||
|
||||
@@ -28,10 +35,19 @@ 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']);
|
||||
$name = cleanInput($_POST['name']);
|
||||
$description = cleanInput($_POST['description']);
|
||||
|
||||
mysqli_query($mysqli,"UPDATE payment_methods SET payment_method_name = '$name', payment_method_description = '$description' WHERE payment_method_id = $payment_method_id");
|
||||
$query = mysqli_prepare(
|
||||
$mysqli,
|
||||
"UPDATE payment_methods
|
||||
SET payment_method_name = ?, payment_method_description = ?
|
||||
WHERE payment_method_id = ?"
|
||||
);
|
||||
|
||||
mysqli_stmt_bind_param($query, "ssi", $name, $description, $payment_method_id);
|
||||
|
||||
mysqli_stmt_execute($query);
|
||||
|
||||
logAction("Payment Method", "Edit", "$session_name edited Payment Method $name");
|
||||
|
||||
|
||||
@@ -15,10 +15,10 @@ if (isset($_POST['add_payment_provider'])) {
|
||||
$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']);
|
||||
$percentage_fee = floatval($_POST['percentage_fee']) / 100 ?? 0;
|
||||
$flat_fee = floatval($_POST['flat_fee']) ?? 0;
|
||||
|
||||
// Check to make sure Provider isnt added Twice
|
||||
// Check to ensure provider isn't 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) {
|
||||
@@ -26,7 +26,7 @@ if (isset($_POST['add_payment_provider'])) {
|
||||
redirect();
|
||||
}
|
||||
|
||||
// Check for Stripe Account if not create it
|
||||
// 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);
|
||||
@@ -35,6 +35,10 @@ if (isset($_POST['add_payment_provider'])) {
|
||||
$account_id = intval($row['account_id']);
|
||||
}
|
||||
|
||||
// Expense defaults
|
||||
$category_id = 0;
|
||||
$vendor_id = 0;
|
||||
|
||||
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");
|
||||
@@ -45,10 +49,10 @@ if (isset($_POST['add_payment_provider'])) {
|
||||
$row = mysqli_fetch_array($sql_category);
|
||||
$category_id = intval($row['category_id']);
|
||||
}
|
||||
//Vendor
|
||||
// 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");
|
||||
mysqli_query($mysqli,"INSERT INTO vendors SET vendor_name = '$provider', vendor_description = 'Payment Processor Provider', vendor_client_id = 0");
|
||||
$vendor_id = mysqli_insert_id($mysqli);
|
||||
} else {
|
||||
$row = mysqli_fetch_array($sql_vendor);
|
||||
@@ -56,7 +60,7 @@ if (isset($_POST['add_payment_provider'])) {
|
||||
}
|
||||
}
|
||||
|
||||
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");
|
||||
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_threshold = $threshold, 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);
|
||||
|
||||
@@ -81,7 +85,7 @@ if (isset($_POST['edit_payment_provider'])) {
|
||||
$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");
|
||||
mysqli_query($mysqli,"UPDATE payment_providers SET payment_provider_public_key = '$public_key', payment_provider_private_key = '$private_key', payment_provider_threshold = $threshold, 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");
|
||||
|
||||
@@ -93,10 +97,18 @@ if (isset($_POST['edit_payment_provider'])) {
|
||||
|
||||
if (isset($_GET['delete_payment_provider'])) {
|
||||
|
||||
validateCSRFToken($_GET['csrf_token']);
|
||||
|
||||
$provider_id = intval($_GET['delete_payment_provider']);
|
||||
|
||||
$provider_name = sanitizeInput(getFieldById('provider_providers', $provider_id, 'provider_name'));
|
||||
// When deleted it cascades deletes
|
||||
// all Recurring paymentes related to payment provider
|
||||
// Delete all Saved Cards related
|
||||
// Delete Client Payment Provider Releation
|
||||
|
||||
$provider_name = sanitizeInput(getFieldById('payment_providers', $provider_id, 'provider_name'));
|
||||
|
||||
// Delete provider
|
||||
mysqli_query($mysqli,"DELETE FROM payment_providers WHERE payment_provider_id = $provider_id");
|
||||
|
||||
logAction("Payment Provider", "Delete", "$session_name deleted Payment Provider $provider_name");
|
||||
|
||||
@@ -37,12 +37,12 @@ if (isset($_GET['delete_saved_payment'])) {
|
||||
|
||||
$private_key = $row['payment_provider_private_key'];
|
||||
|
||||
// Seperate logic for each Payment Provider
|
||||
// Separate logic for each Payment Provider
|
||||
if ($payment_provider_name == 'Stripe') {
|
||||
|
||||
try {
|
||||
// Initialize stripe
|
||||
require_once 'plugins/stripe-php/init.php';
|
||||
require_once '../plugins/stripe-php/init.php';
|
||||
$stripe = new \Stripe\StripeClient($private_key);
|
||||
|
||||
// Detach PM
|
||||
@@ -56,7 +56,7 @@ if (isset($_GET['delete_saved_payment'])) {
|
||||
|
||||
}
|
||||
|
||||
// Remove payment method from ITFlow
|
||||
// Remove payment method from ITFlow. This will also cascade delete related recurring payments setup
|
||||
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.
|
||||
|
||||
@@ -6,15 +6,37 @@ if (isset($_POST['edit_mail_smtp_settings'])) {
|
||||
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
$config_smtp_host = sanitizeInput($_POST['config_smtp_host']);
|
||||
$config_smtp_port = intval($_POST['config_smtp_port']);
|
||||
$config_smtp_encryption = sanitizeInput($_POST['config_smtp_encryption']);
|
||||
$config_smtp_username = sanitizeInput($_POST['config_smtp_username']);
|
||||
$config_smtp_password = sanitizeInput($_POST['config_smtp_password']);
|
||||
$config_smtp_provider = sanitizeInput($_POST['config_smtp_provider']);
|
||||
$config_smtp_host = sanitizeInput($_POST['config_smtp_host']);
|
||||
$config_smtp_port = intval($_POST['config_smtp_port'] ?? 0);
|
||||
$config_smtp_encryption = sanitizeInput($_POST['config_smtp_encryption']);
|
||||
$config_smtp_username = sanitizeInput($_POST['config_smtp_username']);
|
||||
$config_smtp_password = sanitizeInput($_POST['config_smtp_password']);
|
||||
|
||||
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");
|
||||
// Shared OAuth fields
|
||||
$config_mail_oauth_client_id = sanitizeInput($_POST['config_mail_oauth_client_id']);
|
||||
$config_mail_oauth_client_secret = sanitizeInput($_POST['config_mail_oauth_client_secret']);
|
||||
$config_mail_oauth_tenant_id = sanitizeInput($_POST['config_mail_oauth_tenant_id']);
|
||||
$config_mail_oauth_refresh_token = sanitizeInput($_POST['config_mail_oauth_refresh_token']);
|
||||
$config_mail_oauth_access_token = sanitizeInput($_POST['config_mail_oauth_access_token']);
|
||||
|
||||
logAction("Settings", "Edit", "$session_name edited SMTP mail settings");
|
||||
mysqli_query($mysqli, "
|
||||
UPDATE settings SET
|
||||
config_smtp_provider = '$config_smtp_provider',
|
||||
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',
|
||||
config_mail_oauth_client_id = '$config_mail_oauth_client_id',
|
||||
config_mail_oauth_client_secret = '$config_mail_oauth_client_secret',
|
||||
config_mail_oauth_tenant_id = '$config_mail_oauth_tenant_id',
|
||||
config_mail_oauth_refresh_token = '$config_mail_oauth_refresh_token',
|
||||
config_mail_oauth_access_token = '$config_mail_oauth_access_token'
|
||||
WHERE company_id = 1
|
||||
");
|
||||
|
||||
logAction("Settings", "Edit", "$session_name edited SMTP settings");
|
||||
|
||||
flash_alert("SMTP Mail Settings updated");
|
||||
|
||||
@@ -26,15 +48,37 @@ if (isset($_POST['edit_mail_imap_settings'])) {
|
||||
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
$config_imap_host = sanitizeInput($_POST['config_imap_host']);
|
||||
$config_imap_username = sanitizeInput($_POST['config_imap_username']);
|
||||
$config_imap_password = sanitizeInput($_POST['config_imap_password']);
|
||||
$config_imap_port = intval($_POST['config_imap_port']);
|
||||
$config_imap_encryption = sanitizeInput($_POST['config_imap_encryption']);
|
||||
$config_imap_provider = sanitizeInput($_POST['config_imap_provider']);
|
||||
$config_imap_host = sanitizeInput($_POST['config_imap_host']);
|
||||
$config_imap_port = intval($_POST['config_imap_port'] ?? 0);
|
||||
$config_imap_encryption = sanitizeInput($_POST['config_imap_encryption']);
|
||||
$config_imap_username = sanitizeInput($_POST['config_imap_username']);
|
||||
$config_imap_password = sanitizeInput($_POST['config_imap_password']);
|
||||
|
||||
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");
|
||||
// Shared OAuth fields
|
||||
$config_mail_oauth_client_id = sanitizeInput($_POST['config_mail_oauth_client_id']);
|
||||
$config_mail_oauth_client_secret = sanitizeInput($_POST['config_mail_oauth_client_secret']);
|
||||
$config_mail_oauth_tenant_id = sanitizeInput($_POST['config_mail_oauth_tenant_id']);
|
||||
$config_mail_oauth_refresh_token = sanitizeInput($_POST['config_mail_oauth_refresh_token']);
|
||||
$config_mail_oauth_access_token = sanitizeInput($_POST['config_mail_oauth_access_token']);
|
||||
|
||||
logAction("Settings", "Edit", "$session_name edited IMAP mail settings");
|
||||
mysqli_query($mysqli, "
|
||||
UPDATE settings SET
|
||||
config_imap_provider = '$config_imap_provider',
|
||||
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',
|
||||
config_mail_oauth_client_id = '$config_mail_oauth_client_id',
|
||||
config_mail_oauth_client_secret = '$config_mail_oauth_client_secret',
|
||||
config_mail_oauth_tenant_id = '$config_mail_oauth_tenant_id',
|
||||
config_mail_oauth_refresh_token = '$config_mail_oauth_refresh_token',
|
||||
config_mail_oauth_access_token = '$config_mail_oauth_access_token'
|
||||
WHERE company_id = 1
|
||||
");
|
||||
|
||||
logAction("Settings", "Edit", "$session_name edited IMAP settings");
|
||||
|
||||
flash_alert("IMAP Mail Settings updated");
|
||||
|
||||
@@ -106,7 +150,7 @@ if (isset($_POST['test_email_smtp'])) {
|
||||
$mail = addToMailQueue($data);
|
||||
|
||||
if ($mail === true) {
|
||||
flash_alert("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='mail_queue.php'>Check Admin > Mail queue</a>");
|
||||
} else {
|
||||
flash_alert("Failed to add test mail to queue", 'error');
|
||||
}
|
||||
@@ -119,24 +163,125 @@ if (isset($_POST['test_email_imap'])) {
|
||||
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
// 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;
|
||||
$host = $config_imap_host;
|
||||
$port = (int) $config_imap_port;
|
||||
$encryption = strtolower(trim($config_imap_encryption)); // e.g. "ssl", "tls", "none"
|
||||
$username = $config_imap_username;
|
||||
$password = $config_imap_password;
|
||||
|
||||
// Build remote socket (implicit SSL vs plain TCP)
|
||||
$transport = 'tcp';
|
||||
if ($encryption === 'ssl') {
|
||||
$transport = 'ssl';
|
||||
}
|
||||
|
||||
$remote_socket = $transport . '://' . $host . ':' . $port;
|
||||
|
||||
// Stream context (you can tighten these if you want strict validation)
|
||||
$contextOptions = [];
|
||||
if (in_array($encryption, ['ssl', 'tls'], true)) {
|
||||
$contextOptions['ssl'] = [
|
||||
'verify_peer' => false,
|
||||
'verify_peer_name' => false,
|
||||
'allow_self_signed' => true,
|
||||
];
|
||||
}
|
||||
|
||||
$context = stream_context_create($contextOptions);
|
||||
|
||||
try {
|
||||
$inbox = @imap_open($hostname, $username, $password);
|
||||
$errno = 0;
|
||||
$errstr = '';
|
||||
|
||||
if ($inbox) {
|
||||
imap_close($inbox);
|
||||
// 10-second timeout, adjust as needed
|
||||
$fp = @stream_socket_client(
|
||||
$remote_socket,
|
||||
$errno,
|
||||
$errstr,
|
||||
10,
|
||||
STREAM_CLIENT_CONNECT,
|
||||
$context
|
||||
);
|
||||
|
||||
if (!$fp) {
|
||||
throw new Exception("Could not connect to IMAP server: [$errno] $errstr");
|
||||
}
|
||||
|
||||
stream_set_timeout($fp, 10);
|
||||
|
||||
// Read server greeting (IMAP servers send something like: * OK Dovecot ready)
|
||||
$greeting = fgets($fp, 1024);
|
||||
if ($greeting === false || strpos($greeting, '* OK') !== 0) {
|
||||
fclose($fp);
|
||||
throw new Exception("Invalid IMAP greeting: " . trim((string) $greeting));
|
||||
}
|
||||
|
||||
// If you really want STARTTLS for "tls" (port 143), you can do it here
|
||||
if ($encryption === 'tls' && stripos($greeting, 'STARTTLS') !== false) {
|
||||
// Request STARTTLS
|
||||
fwrite($fp, "A0001 STARTTLS\r\n");
|
||||
$line = fgets($fp, 1024);
|
||||
if ($line === false || stripos($line, 'A0001 OK') !== 0) {
|
||||
fclose($fp);
|
||||
throw new Exception("STARTTLS failed: " . trim((string) $line));
|
||||
}
|
||||
|
||||
// Enable crypto on the stream
|
||||
if (!stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
|
||||
fclose($fp);
|
||||
throw new Exception("Unable to enable TLS encryption on IMAP connection.");
|
||||
}
|
||||
}
|
||||
|
||||
// --- Do LOGIN command ---
|
||||
$tag = 'A0002';
|
||||
|
||||
// Simple quoting; this may fail with some special chars in username/password.
|
||||
$loginCmd = sprintf(
|
||||
"%s LOGIN \"%s\" \"%s\"\r\n",
|
||||
$tag,
|
||||
addcslashes($username, "\\\""),
|
||||
addcslashes($password, "\\\"")
|
||||
);
|
||||
|
||||
fwrite($fp, $loginCmd);
|
||||
|
||||
$success = false;
|
||||
$errorLine = '';
|
||||
|
||||
while (!feof($fp)) {
|
||||
$line = fgets($fp, 2048);
|
||||
if ($line === false) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Look for tagged response for our LOGIN
|
||||
if (strpos($line, $tag . ' ') === 0) {
|
||||
if (stripos($line, $tag . ' OK') === 0) {
|
||||
$success = true;
|
||||
} else {
|
||||
$errorLine = trim($line);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Always logout / close
|
||||
fwrite($fp, "A0003 LOGOUT\r\n");
|
||||
fclose($fp);
|
||||
|
||||
if ($success) {
|
||||
flash_alert("Connected successfully");
|
||||
} else {
|
||||
throw new Exception(imap_last_error());
|
||||
if (!$errorLine) {
|
||||
$errorLine = 'Unknown IMAP authentication error';
|
||||
}
|
||||
throw new Exception($errorLine);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
flash_alert("<strong>IMAP connection failed:</strong> " . $e->getMessage(), 'error');
|
||||
flash_alert("<strong>IMAP connection failed:</strong> " . htmlspecialchars($e->getMessage()), 'error');
|
||||
}
|
||||
|
||||
redirect();
|
||||
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ if (isset($_POST['edit_tag'])) {
|
||||
|
||||
$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");
|
||||
mysqli_query($mysqli,"UPDATE tags SET tag_name = '$name', tag_color = '$color', tag_icon = '$icon' WHERE tag_id = $tag_id");
|
||||
|
||||
logAction("Tag", "Edit", "$session_name edited tag $name", 0, $tag_id);
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
|
||||
|
||||
// Import shared code from user-side tickets/tasks as we reuse functions
|
||||
require_once '../user/post/ticket.php';
|
||||
require_once '../user/post/task.php';
|
||||
require_once '../agent/post/ticket.php';
|
||||
require_once '../agent/post/task.php';
|
||||
|
||||
if (isset($_POST['add_ticket_template'])) {
|
||||
|
||||
|
||||
@@ -236,16 +236,20 @@ if (isset($_GET['revoke_remember_me'])) {
|
||||
|
||||
}
|
||||
|
||||
if (isset($_GET['archive_user'])) {
|
||||
if (isset($_POST['archive_user'])) {
|
||||
|
||||
validateCSRFToken($_GET['csrf_token']);
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
// Variables from GET
|
||||
$user_id = intval($_GET['archive_user']);
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$ticket_assign = intval($_POST['ticket_assign']);
|
||||
$password = password_hash(randomString(), PASSWORD_DEFAULT);
|
||||
|
||||
$user_name = sanitizeInput(getFieldById('users', $user_id, 'user_name'));
|
||||
|
||||
// Un-assign / Re-assign tickets
|
||||
mysqli_query($mysqli, "UPDATE tickets SET ticket_assigned_to = $ticket_assign WHERE ticket_assigned_to = $user_id AND ticket_closed_at IS NULL AND ticket_resolved_at IS NULL");
|
||||
mysqli_query($mysqli, "UPDATE recurring_tickets SET recurring_ticket_assigned_to = $ticket_assign WHERE recurring_ticket_assigned_to = $user_id");
|
||||
|
||||
// Archive user query
|
||||
mysqli_query($mysqli, "UPDATE users SET user_name = '$user_name (archived)', user_password = '$password', user_status = 0, user_specific_encryption_ciphertext = '', user_archived_at = NOW() WHERE user_id = $user_id");
|
||||
|
||||
@@ -257,6 +261,36 @@ if (isset($_GET['archive_user'])) {
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['restore_user'])) {
|
||||
|
||||
validateCSRFToken($_POST['csrf_token']);
|
||||
|
||||
$user_id = intval($_POST['user_id']);
|
||||
$new_password = trim($_POST['new_password']);
|
||||
$role = intval($_POST['role']);
|
||||
|
||||
$user_name = getFieldById('users', $user_id, 'user_name');
|
||||
$user_name = sanitizeInput(str_replace(" (archived)", "", $user_name)); //Removed (archived) from user_name
|
||||
|
||||
// Restore user query
|
||||
mysqli_query($mysqli, "UPDATE users SET user_name = '$user_name', user_status = 1, user_role_id = $role, user_archived_at = NULL WHERE user_id = $user_id");
|
||||
|
||||
if (!empty($new_password)) {
|
||||
$new_password = password_hash($new_password, PASSWORD_DEFAULT);
|
||||
$user_specific_encryption_ciphertext = encryptUserSpecificKey(trim($_POST['new_password']));
|
||||
mysqli_query($mysqli, "UPDATE users SET user_password = '$new_password', user_specific_encryption_ciphertext = '$user_specific_encryption_ciphertext' WHERE user_id = $user_id");
|
||||
//Extended Logging
|
||||
$extended_log_description .= ", password changed";
|
||||
}
|
||||
|
||||
logAction("User", "Restored", "$session_name restored user $user_name", 0, $user_id);
|
||||
|
||||
flash_alert("User <strong>$user_name</strong> restored");
|
||||
|
||||
redirect();
|
||||
|
||||
}
|
||||
|
||||
if (isset($_POST['export_users_csv'])) {
|
||||
|
||||
//get records from database
|
||||
@@ -266,6 +300,8 @@ if (isset($_POST['export_users_csv'])) {
|
||||
|
||||
if ($count > 0) {
|
||||
$delimiter = ",";
|
||||
$enclosure = '"';
|
||||
$escape = '\\'; // backslash
|
||||
$filename = "Users-" . date('Y-m-d') . ".csv";
|
||||
|
||||
//create a file pointer
|
||||
@@ -273,7 +309,7 @@ if (isset($_POST['export_users_csv'])) {
|
||||
|
||||
//set column headers
|
||||
$fields = array('Name', 'Email', 'Role', 'Status', 'Creation Date');
|
||||
fputcsv($f, $fields, $delimiter);
|
||||
fputcsv($f, $fields, $delimiter, $enclosure, $escape);
|
||||
|
||||
//output each row of the data, format line as csv and write to file pointer
|
||||
while($row = $sql->fetch_assoc()) {
|
||||
@@ -288,7 +324,7 @@ if (isset($_POST['export_users_csv'])) {
|
||||
}
|
||||
|
||||
$lineData = array($row['user_name'], $row['user_email'], $row['role_name'], $user_status_display, $row['user_created_at']);
|
||||
fputcsv($f, $lineData, $delimiter);
|
||||
fputcsv($f, $lineData, $delimiter, $enclosure, $escape);
|
||||
}
|
||||
|
||||
//move back to beginning of file
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
defined('FROM_POST_HANDLER') || die("Direct file access is not allowed");
|
||||
|
||||
// Import shared code from user-side vendor management as we reuse functions
|
||||
require_once '../user/post/vendor.php';
|
||||
require_once '../agent/post/vendor.php';
|
||||
|
||||
if (isset($_POST['add_vendor_template'])) {
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-project-diagram mr-2"></i>Project Templates</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addProjectTemplateModal"><i class="fas fa-plus mr-2"></i>New Project Template</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/project_template/project_template_add.php"><i class="fas fa-plus mr-2"></i>New Project Template</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -87,7 +87,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<a class="text-dark" href="#" data-toggle="modal" data-target="#editProjectTemplateModal<?php echo $project_template_id; ?>">
|
||||
<a class="text-dark ajax-modal" href="#" data-modal-url="modals/project_template/project_template_edit.php?project_template_id=<?= $project_template_id ?>">
|
||||
<div class="media">
|
||||
<i class="fa fa-fw fa-2x fa-project-diagram mr-3"></i>
|
||||
<div class="media-body">
|
||||
@@ -109,7 +109,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="modal" data-target="#editProjectTemplateModal<?php echo $project_template_id; ?>">
|
||||
<a class="dropdown-item ajax-modal" href="#" data-modal-url="modals/project_template/project_template_edit.php?project_template_id=<?= $project_template_id ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<?php if($session_user_role == 3) { ?>
|
||||
@@ -123,9 +123,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
require "modals/project_template/project_template_edit.php";
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
@@ -134,12 +132,9 @@ $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/project_template/project_template_add.php";
|
||||
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -13,9 +13,9 @@ if (isset($_GET['project_template_id'])) {
|
||||
);
|
||||
|
||||
if (mysqli_num_rows($sql_project_templates) == 0) {
|
||||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='admin_project_template.php'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='javascript:history.back()'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
|
||||
include_once "footer.php";
|
||||
require_once "../includes/footer.php";
|
||||
exit;
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ if (isset($_GET['project_template_id'])) {
|
||||
|
||||
<div class="col-sm-2">
|
||||
<div class="btn-group float-right">
|
||||
<button type="button" class="btn btn-primary btn-sm" href="#" data-toggle="modal" data-target="#addProjectTemplateTicketTemplateModal">
|
||||
<button type="button" class="btn btn-primary btn-sm ajax-modal" href="#" data-modal-url="modals/project_template/project_template_ticket_template_add.php?project_template_id=<?= $project_template_id ?>">
|
||||
<i class="fas fa-fw fa-plus mr-2"></i>Add Ticket Template
|
||||
</button>
|
||||
<div class="dropdown dropleft text-center ml-3">
|
||||
@@ -99,7 +99,7 @@ if (isset($_GET['project_template_id'])) {
|
||||
<i class="fas fa-fw fa-ellipsis-v"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editProjectTemplateModal<?php echo $project_template_id; ?>">
|
||||
<a class="dropdown-item ajax-modal" href="#" data-modal-url="modals/project_template/project_template_edit.php?project_template_id=<?= $project_template_id ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit Template
|
||||
</a>
|
||||
<?php if ($session_user_role == 3) { ?>
|
||||
@@ -221,9 +221,6 @@ if (isset($_GET['project_template_id'])) {
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/project_template/project_template_edit.php";
|
||||
require_once "modals/project_template/project_template_ticket_template_add.php";
|
||||
|
||||
}
|
||||
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -24,7 +24,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-user-shield mr-2"></i>Roles</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addRoleModal">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/role/role_add.php">
|
||||
<i class="fas fa-fw fa-user-plus mr-2"></i>New Role
|
||||
</button>
|
||||
</div>
|
||||
@@ -143,6 +143,4 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/role/role_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -214,7 +214,7 @@ require_once "includes/inc_all_admin.php";
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="hourly_rate" value="<?php echo number_format($config_default_hourly_rate, 2, '.', ''); ?>" placeholder="0.00" required>
|
||||
<input type="text" class="form-control" inputmode="decimal" pattern="[0-9]*\.?[0-9]{0,2}" name="hourly_rate" value="<?php echo number_format($config_default_hourly_rate, 2, '.', ''); ?>" placeholder="0.00" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -10,61 +10,87 @@ require_once "includes/inc_all_admin.php";
|
||||
<form action="post.php" method="post" autocomplete="off">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<!-- SMTP Provider -->
|
||||
<div class="form-group">
|
||||
<label>SMTP Host</label>
|
||||
<label>SMTP Provider</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-server"></i></span>
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="config_smtp_host" placeholder="Mail Server Address" value="<?php echo nullable_htmlentities($config_smtp_host); ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SMTP Port</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-plug"></i></span>
|
||||
</div>
|
||||
<input type="number" min="0" class="form-control" name="config_smtp_port" placeholder="Mail Server Port Number" value="<?php echo intval($config_smtp_port); ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Encryption</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>
|
||||
<select class="form-control" name="config_smtp_encryption">
|
||||
<option value=''>None</option>
|
||||
<option <?php if ($config_smtp_encryption == 'tls') { echo "selected"; } ?> value="tls">TLS</option>
|
||||
<option <?php if ($config_smtp_encryption == 'ssl') { echo "selected"; } ?> value="ssl">SSL</option>
|
||||
<select class="form-control" name="config_smtp_provider" id="config_smtp_provider">
|
||||
<option value="" <?php if(empty($config_smtp_provider)) { echo 'selected'; } ?>>None (Disabled)</option>
|
||||
<option value="standard_smtp" <?php if($config_smtp_provider === 'standard_smtp') { echo 'selected'; } ?>>Standard SMTP (Username/Password)</option>
|
||||
<option value="google_oauth" <?php if($config_smtp_provider === 'google_oauth') { echo 'selected'; } ?>>Google Workspace (OAuth)</option>
|
||||
<option value="microsoft_oauth" <?php if($config_smtp_provider === 'microsoft_oauth') { echo 'selected'; } ?>>Microsoft 365 (OAuth)</option>
|
||||
</select>
|
||||
</div>
|
||||
<small class="text-secondary d-block mt-1" id="smtp_provider_hint">
|
||||
Choose your SMTP provider. OAuth options ignore the SMTP password here.
|
||||
</small>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SMTP Username</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="config_smtp_username" placeholder="Username (Leave blank if no auth is required)" value="<?php echo nullable_htmlentities($config_smtp_username); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SMTP Password</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="password" class="form-control" data-toggle="password" name="config_smtp_password" placeholder="Password (Leave blank if no auth is required)" value="<?php echo nullable_htmlentities($config_smtp_password); ?>" autocomplete="new-password">
|
||||
<div class="input-group-append">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
|
||||
<!-- Standard SMTP fields (show only for standard_smtp) -->
|
||||
<div id="smtp_standard_fields">
|
||||
<div class="form-group">
|
||||
<label>SMTP Host</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-server"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="config_smtp_host" placeholder="Mail Server Address" value="<?php echo nullable_htmlentities($config_smtp_host); ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SMTP Port</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-plug"></i></span>
|
||||
</div>
|
||||
<input type="number" min="0" class="form-control" name="config_smtp_port" placeholder="Mail Server Port Number" value="<?php echo intval($config_smtp_port); ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Encryption</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>
|
||||
<select class="form-control" name="config_smtp_encryption">
|
||||
<option value=''>None</option>
|
||||
<option <?php if ($config_smtp_encryption == 'tls') { echo "selected"; } ?> value="tls">TLS</option>
|
||||
<option <?php if ($config_smtp_encryption == 'ssl') { echo "selected"; } ?> value="ssl">SSL</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>SMTP Username</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="config_smtp_username" placeholder="Username (Leave blank if no auth is required)" value="<?php echo nullable_htmlentities($config_smtp_username); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="smtp_password_group">
|
||||
<div class="form-group">
|
||||
<label>SMTP Password</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="password" class="form-control" data-toggle="password" name="config_smtp_password" placeholder="Password (Leave blank if no auth is required)" value="<?php echo nullable_htmlentities($config_smtp_password); ?>" 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>
|
||||
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
@@ -84,37 +110,56 @@ require_once "includes/inc_all_admin.php";
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
|
||||
<div class="form-group">
|
||||
<label>IMAP Host</label>
|
||||
<label>IMAP Provider</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-server"></i></span>
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-cloud"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="config_imap_host" placeholder="Incoming Mail Server Address (for email to ticket parsing)" value="<?php echo nullable_htmlentities($config_imap_host); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IMAP Port</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-plug"></i></span>
|
||||
</div>
|
||||
<input type="number" min="0" class="form-control" name="config_imap_port" placeholder="Incoming Mail Server Port Number (993)" value="<?php echo intval($config_imap_port); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IMAP Encryption</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>
|
||||
<select class="form-control" name="config_imap_encryption">
|
||||
<option value=''>None</option>
|
||||
<option <?php if ($config_imap_encryption == 'tls') { echo "selected"; } ?> value="tls">TLS</option>
|
||||
<option <?php if ($config_imap_encryption == 'ssl') { echo "selected"; } ?> value="ssl">SSL</option>
|
||||
<select class="form-control" name="config_imap_provider" id="config_imap_provider">
|
||||
<option value="" <?php if(empty($config_imap_provider)) { echo 'selected'; } ?>>None (Disabled)</option>
|
||||
<option value="standard_imap" <?php if($config_imap_provider === 'standard_imap') { echo 'selected'; } ?>>Standard IMAP (Username/Password)</option>
|
||||
<option value="google_oauth" <?php if($config_imap_provider === 'google_oauth') { echo 'selected'; } ?>>Google Workspace (OAuth)</option>
|
||||
<option value="microsoft_oauth" <?php if($config_imap_provider === 'microsoft_oauth') { echo 'selected'; } ?>>Microsoft 365 (OAuth)</option>
|
||||
</select>
|
||||
</div>
|
||||
<small class="text-secondary d-block mt-1" id="imap_provider_hint">
|
||||
Select your mailbox provider. OAuth options ignore the IMAP password here.
|
||||
</small>
|
||||
</div>
|
||||
<div id="standard_fields" style="display:none;">
|
||||
<div class="form-group">
|
||||
<label>IMAP Host</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-server"></i></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" name="config_imap_host" placeholder="Incoming Mail Server Address (for email to ticket parsing)" value="<?php echo nullable_htmlentities($config_imap_host); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IMAP Port</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text"><i class="fa fa-fw fa-plug"></i></span>
|
||||
</div>
|
||||
<input type="number" min="0" class="form-control" name="config_imap_port" placeholder="Incoming Mail Server Port Number (993)" value="<?php echo intval($config_imap_port); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>IMAP Encryption</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>
|
||||
<select class="form-control" name="config_imap_encryption">
|
||||
<option value=''>None</option>
|
||||
<option <?php if ($config_imap_encryption == 'tls') { echo "selected"; } ?> value="tls">TLS</option>
|
||||
<option <?php if ($config_imap_encryption == 'ssl') { echo "selected"; } ?> value="ssl">SSL</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='form-group'>
|
||||
@@ -123,25 +168,81 @@ require_once "includes/inc_all_admin.php";
|
||||
<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='config_imap_username' placeholder='Username' value="<?php
|
||||
echo nullable_htmlentities($config_imap_username); ?>" required>
|
||||
<input type='text' class='form-control' name='config_imap_username' placeholder='Username (email address)' value="<?php echo nullable_htmlentities($config_imap_username); ?>" required>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class='form-group'>
|
||||
<div class='form-group' id="imap_password_group">
|
||||
<label>IMAP Password</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='password' class='form-control' data-toggle='password' name='config_imap_password' placeholder='Password' value="<?php
|
||||
echo nullable_htmlentities($config_imap_password); ?>" autocomplete='new-password' required>
|
||||
<input type='password' class='form-control' data-toggle='password' name='config_imap_password' placeholder='Password (not used for OAuth)' value="<?php echo nullable_htmlentities($config_imap_password); ?>" 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>
|
||||
|
||||
<!-- OAuth shared fields (show for google_oauth / microsoft_oauth) -->
|
||||
<div id="smtp_oauth_fields" style="display:none;">
|
||||
<hr>
|
||||
<h5 class="mb-2">OAuth Settings (shared for IMAP & SMTP)</h5>
|
||||
<p class="text-secondary" id="oauth_hint">
|
||||
Configure OAuth credentials for the selected provider.
|
||||
</p>
|
||||
|
||||
<div class="form-group">
|
||||
<label>OAuth Client ID</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend"><span class="input-group-text"><i class="fa fa-fw fa-id-badge"></i></span></div>
|
||||
<input type="text" class="form-control" name="config_mail_oauth_client_id"
|
||||
value="<?php echo nullable_htmlentities($config_mail_oauth_client_id ?? ''); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>OAuth Client Secret</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="password" class="form-control" data-toggle="password" name="config_mail_oauth_client_secret"
|
||||
value="<?php echo nullable_htmlentities($config_mail_oauth_client_secret ?? ''); ?>" 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" id="tenant_row" style="display:none;">
|
||||
<label>Tenant ID (Microsoft 365 only)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend"><span class="input-group-text"><i class="fa fa-fw fa-building"></i></span></div>
|
||||
<input type="text" class="form-control" name="config_mail_oauth_tenant_id"
|
||||
value="<?php echo nullable_htmlentities($config_mail_oauth_tenant_id ?? ''); ?>">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Refresh Token</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend"><span class="input-group-text"><i class="fa fa-fw fa-sync-alt"></i></span></div>
|
||||
<textarea class="form-control" name="config_mail_oauth_refresh_token" rows="2"
|
||||
placeholder="Paste refresh token"><?php echo nullable_htmlentities($config_mail_oauth_refresh_token ?? ''); ?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Access Token (optional – will refresh if expired)</label>
|
||||
<div class="input-group">
|
||||
<div class="input-group-prepend"><span class="input-group-text"><i class="fa fa-fw fa-shield-alt"></i></span></div>
|
||||
<textarea class="form-control" name="config_mail_oauth_access_token" rows="2"
|
||||
placeholder="Can be left blank; system refreshes using the refresh token"><?php echo nullable_htmlentities($config_mail_oauth_access_token ?? ''); ?></textarea>
|
||||
</div>
|
||||
<small class="text-secondary">
|
||||
Expires at: <?php echo !empty($config_mail_oauth_access_token_expires_at) ? htmlspecialchars($config_mail_oauth_access_token_expires_at) : 'n/a'; ?>
|
||||
</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<button type="submit" name="edit_mail_imap_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
|
||||
@@ -327,5 +428,68 @@ require_once "includes/inc_all_admin.php";
|
||||
|
||||
<?php } ?>
|
||||
|
||||
<?php require_once "../includes/footer.php";
|
||||
<script>
|
||||
(function(){
|
||||
function setDisabled(container, disabled){
|
||||
if(!container) return;
|
||||
container.querySelectorAll('input, select, textarea').forEach(el => el.disabled = !!disabled);
|
||||
}
|
||||
|
||||
function wireProvider(selectId, standardWrapId, passwordGroupId, oauthWrapId, tenantRowId, hintId, oauthHintId){
|
||||
const sel = document.getElementById(selectId);
|
||||
const std = document.getElementById(standardWrapId);
|
||||
const pwd = document.getElementById(passwordGroupId);
|
||||
const oauth = document.getElementById(oauthWrapId);
|
||||
const ten = document.getElementById(tenantRowId);
|
||||
const hint = document.getElementById(hintId);
|
||||
const ohint = document.getElementById(oauthHintId);
|
||||
|
||||
function toggle(){
|
||||
const v = (sel && sel.value) || '';
|
||||
const isNone = (v === 'none' || v === '');
|
||||
const isStd = v === 'standard_smtp' || v === 'standard_imap';
|
||||
const isG = v === 'google_oauth';
|
||||
const isM = v === 'microsoft_oauth';
|
||||
const isOAuth = isG || isM;
|
||||
|
||||
if (std) std.style.display = isStd ? '' : 'none';
|
||||
if (pwd) pwd.style.display = isStd ? '' : 'none';
|
||||
if (oauth) oauth.style.display = isOAuth ? '' : 'none';
|
||||
if (ten) ten.style.display = isM ? '' : 'none';
|
||||
|
||||
setDisabled(std, !isStd);
|
||||
setDisabled(pwd, !isStd);
|
||||
setDisabled(oauth, !isOAuth);
|
||||
|
||||
if (hint) {
|
||||
hint.textContent = isNone
|
||||
? 'Disabled.'
|
||||
: isStd
|
||||
? 'Standard: provide host, port, encryption, username & password.'
|
||||
: isG
|
||||
? 'Google OAuth: set Client ID/Secret; paste a refresh token; username should be the mailbox email.'
|
||||
: 'Microsoft 365 OAuth: set Client ID/Secret/Tenant; paste a refresh token; username should be the mailbox email.';
|
||||
}
|
||||
if (ohint) {
|
||||
ohint.textContent = isG
|
||||
? 'Google Workspace OAuth: Client ID/Secret from Google Cloud; Refresh token via consent.'
|
||||
: isM
|
||||
? 'Microsoft 365 OAuth: Client ID/Secret/Tenant from Entra ID; Refresh token via consent.'
|
||||
: 'Configure OAuth credentials for the selected provider.';
|
||||
}
|
||||
}
|
||||
|
||||
if (sel) { sel.addEventListener('change', toggle); toggle(); }
|
||||
}
|
||||
|
||||
// IMAP (you already have these IDs in your page)
|
||||
wireProvider('config_imap_provider', 'standard_fields', 'imap_password_group',
|
||||
'oauth_fields', 'tenant_row', 'imap_provider_hint', 'oauth_hint');
|
||||
|
||||
// SMTP (the IDs we just added)
|
||||
wireProvider('config_smtp_provider', 'smtp_standard_fields', 'smtp_password_group',
|
||||
'smtp_oauth_fields', 'smtp_tenant_row', 'smtp_provider_hint', 'smtp_oauth_hint');
|
||||
})();
|
||||
</script>
|
||||
|
||||
<?php require_once "../includes/footer.php";
|
||||
|
||||
@@ -21,7 +21,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-cube mr-2"></i>License Templates</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addSoftwareTemplateModal"><i class="fas fa-plus mr-2"></i>New License Template</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/software_template/software_template_add.php"><i class="fas fa-plus mr-2"></i>New License Template</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -127,5 +127,4 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/software_template/software_template_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -6,10 +6,31 @@ $order = "ASC";
|
||||
|
||||
require_once "includes/inc_all_admin.php";
|
||||
|
||||
if (isset($_GET['type'])) {
|
||||
$type_filter = intval($_GET['type']);
|
||||
} else {
|
||||
$type_filter = 1;
|
||||
}
|
||||
|
||||
if ($type_filter == 1) {
|
||||
$tag_type_display = "Client";
|
||||
} elseif ( $type_filter == 2) {
|
||||
$tag_type_display = "Location";
|
||||
} elseif ( $type_filter == 3) {
|
||||
$tag_type_display = "Contact";
|
||||
} elseif ( $type_filter == 4) {
|
||||
$tag_type_display = "Credential";
|
||||
} elseif ( $type_filter == 5) {
|
||||
$tag_type_display = "Asset";
|
||||
} else {
|
||||
$tag_type_display = "Unknown";
|
||||
}
|
||||
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM tags
|
||||
WHERE tag_name LIKE '%$q%'
|
||||
AND tag_type = $type_filter
|
||||
ORDER BY $sort $order LIMIT $record_from, $record_to"
|
||||
);
|
||||
|
||||
@@ -19,9 +40,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-tags mr-2"></i>Tags</h3>
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-tags mr-2"></i><?= $tag_type_display ?> Tags</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/tag/tag_add.php"><i class="fas fa-plus mr-2"></i>New Tag</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/tag/tag_add.php?type=<?= $type_filter ?>"><i class="fas fa-plus mr-2"></i>New <?= $tag_type_display ?> Tag</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -30,7 +51,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="col-sm-4 mb-2">
|
||||
<form autocomplete="off">
|
||||
<div class="input-group">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Tags">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search <?= $tag_type_display ?> Tags">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
@@ -38,6 +59,45 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</form>
|
||||
</div>
|
||||
<div class="col-sm-8">
|
||||
<div class="btn-group float-right">
|
||||
<a href="?type=1"
|
||||
class="btn <?php if ($type_filter == 1) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Client</a>
|
||||
<a href="?type=2"
|
||||
class="btn <?php if ($type_filter == 2) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Location</a>
|
||||
<a href="?type=3"
|
||||
class="btn <?php if ($type_filter == 3) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Contact</a>
|
||||
<a href="?type=4"
|
||||
class="btn <?php if ($type_filter == 4) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Credential</a>
|
||||
<a href="?type=5"
|
||||
class="btn <?php if ($type_filter == 5) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>">Asset</a>
|
||||
<a href="?<?= $url_query_strings_sort ?>&archived=1"
|
||||
class="btn <?php if (isset($_GET['archived'])) {
|
||||
echo 'btn-primary';
|
||||
} else {
|
||||
echo 'btn-default';
|
||||
} ?>"><i
|
||||
class="fas fa-fw fa-archive mr-2"></i>Archived</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -51,11 +111,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
Name <?php if ($sort == 'tag_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tag_type&order=<?php echo $disp; ?>">
|
||||
Type <?php if ($sort == 'tag_type') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -65,18 +120,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$tag_id = intval($row['tag_id']);
|
||||
$tag_name = nullable_htmlentities($row['tag_name']);
|
||||
$tag_type = intval($row['tag_type']);
|
||||
if ( $tag_type == 1) {
|
||||
$tag_type_display = "Client Tag";
|
||||
} elseif ( $tag_type == 2) {
|
||||
$tag_type_display = "Location Tag";
|
||||
} elseif ( $tag_type == 3) {
|
||||
$tag_type_display = "Contact Tag";
|
||||
} elseif ( $tag_type == 4) {
|
||||
$tag_type_display = "Credential Tag";
|
||||
} else {
|
||||
$tag_type_display = "Unknown Tag";
|
||||
}
|
||||
$tag_color = nullable_htmlentities($row['tag_color']);
|
||||
$tag_icon = nullable_htmlentities($row['tag_icon']);
|
||||
|
||||
@@ -88,7 +131,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<span class='badge text-light p-2 mr-1' style="background-color: <?php echo $tag_color; ?>"><i class="fa fa-fw fa-<?php echo $tag_icon; ?> mr-2"></i><?php echo $tag_name; ?></span>
|
||||
</a>
|
||||
</td>
|
||||
<td><?php echo $tag_type_display; ?></td>
|
||||
<td>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
|
||||
@@ -117,8 +159,7 @@ $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>
|
||||
|
||||
|
||||
151
admin/tax.php
151
admin/tax.php
@@ -17,84 +17,83 @@ $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-balance-scale mr-2"></i>Taxes</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addTaxModal"><i class="fas fa-plus mr-2"></i>New Tax</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=tax_name&order=<?php echo $disp; ?>">
|
||||
Name <?php if ($sort == 'tax_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tax_percent&order=<?php echo $disp; ?>">
|
||||
Percent <?php if ($sort == 'tax_percent') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$tax_id = intval($row['tax_id']);
|
||||
$tax_name = nullable_htmlentities($row['tax_name']);
|
||||
$tax_percent = floatval($row['tax_percent']);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<a class="text-dark text-bold ajax-modal" href="#"
|
||||
data-modal-url="modals/tax/tax_edit.php?id=<?= $tax_id ?>">
|
||||
<?php echo $tax_name; ?>
|
||||
</a>
|
||||
</td>
|
||||
<td><?php echo "$tax_percent%"; ?></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/tax/tax_edit.php?id=<?= $tax_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?archive_tax=<?php echo $tax_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-archive mr-2"></i>Archive
|
||||
</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 class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-balance-scale mr-2"></i>Taxes</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/tax/tax_add.php"><i class="fas fa-plus mr-2"></i>New Tax</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=tax_name&order=<?php echo $disp; ?>">
|
||||
Name <?php if ($sort == 'tax_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tax_percent&order=<?php echo $disp; ?>">
|
||||
Percent <?php if ($sort == 'tax_percent') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$tax_id = intval($row['tax_id']);
|
||||
$tax_name = nullable_htmlentities($row['tax_name']);
|
||||
$tax_percent = floatval($row['tax_percent']);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td>
|
||||
<a class="text-dark text-bold ajax-modal" href="#"
|
||||
data-modal-url="modals/tax/tax_edit.php?id=<?= $tax_id ?>">
|
||||
<?php echo $tax_name; ?>
|
||||
</a>
|
||||
</td>
|
||||
<td><?php echo "$tax_percent%"; ?></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/tax/tax_edit.php?id=<?= $tax_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?archive_tax=<?php echo $tax_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<i class="fas fa-fw fa-archive mr-2"></i>Archive
|
||||
</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/tax/tax_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -21,7 +21,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-info-circle mr-2"></i>Tickets Statuses</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addTicketStatusModal"><i class="fas fa-plus mr-2"></i>New Ticket Status</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/ticket_status/ticket_status_add.php"><i class="fas fa-plus mr-2"></i>New Ticket Status</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -120,13 +120,9 @@ $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/ticket_status/ticket_status_add.php";
|
||||
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
|
||||
@@ -8,10 +8,15 @@ require_once "includes/inc_all_admin.php";
|
||||
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM ticket_templates
|
||||
WHERE (ticket_template_name LIKE '%$q%' OR ticket_template_description LIKE '%$q%')
|
||||
AND ticket_template_archived_at IS NULL
|
||||
ORDER BY $sort $order LIMIT $record_from, $record_to"
|
||||
"SELECT SQL_CALC_FOUND_ROWS *,
|
||||
COUNT(task_template_id) AS task_count
|
||||
FROM ticket_templates
|
||||
LEFT JOIN task_templates ON task_template_ticket_template_id = ticket_template_id
|
||||
WHERE (ticket_template_name LIKE '%$q%' OR ticket_template_description LIKE '%$q%')
|
||||
AND ticket_template_archived_at IS NULL
|
||||
GROUP BY ticket_template_id
|
||||
ORDER BY $sort $order
|
||||
LIMIT $record_from, $record_to"
|
||||
);
|
||||
|
||||
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
@@ -22,7 +27,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Ticket Templates</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addTicketTemplateModal"><i class="fas fa-plus mr-2"></i>New Ticket Template</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/ticket_template/ticket_template_add.php" data-modal-size="lg"><i class="fas fa-plus mr-2"></i>New Ticket Template</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -46,14 +51,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<hr>
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if($num_rows[0] == 0){ echo "d-none"; } ?>">
|
||||
<thead class="text-dark <?php if($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_template_name&order=<?php echo $disp; ?>">
|
||||
<a class="text-secondary" href="?<?= $url_query_strings_sort ?>&sort=ticket_template_name&order=<?= $disp ?>">
|
||||
Template <?php if ($sort == 'ticket_template_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>Tasks</th>
|
||||
<th>
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=task_count&order=<?php echo $disp; ?>">
|
||||
Tasks <?php if ($sort == 'task_count') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
@@ -66,6 +75,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
|
||||
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
|
||||
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
|
||||
$task_count = intval($row['task_count']);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
@@ -75,23 +85,23 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
|
||||
<div class="media-body">
|
||||
<div>
|
||||
<a href="ticket_template_details.php?ticket_template_id=<?php echo $ticket_template_id; ?>">
|
||||
<?php echo $ticket_template_name; ?>
|
||||
<a href="ticket_template_details.php?ticket_template_id=<?= $ticket_template_id ?>">
|
||||
<?= $ticket_template_name ?>
|
||||
</a>
|
||||
</div>
|
||||
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
|
||||
<div><small class="text-secondary"><?= $ticket_template_description ?></small></div>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
</td>
|
||||
<td>0</td>
|
||||
<td><?= $task_count ?></td>
|
||||
<td>
|
||||
<div class="dropdown dropleft text-center">
|
||||
<button class="btn btn-secondary btn-sm" data-toggle="dropdown">
|
||||
<i class="fas fa-ellipsis-h"></i>
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_template=<?php echo $ticket_template_id; ?>">
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_template=<?= $ticket_template_id ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
</div>
|
||||
@@ -110,6 +120,4 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/ticket_template/ticket_template_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
|
||||
@@ -15,9 +15,15 @@ if (isset($_GET['ticket_template_id'])) {
|
||||
$ticket_template_id = intval($_GET['ticket_template_id']);
|
||||
}
|
||||
|
||||
$sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates WHERE ticket_template_id = $ticket_template_id");
|
||||
$sql_ticket_template = mysqli_query($mysqli, "SELECT * FROM ticket_templates WHERE ticket_template_id = $ticket_template_id LIMIT 1");
|
||||
|
||||
$row = mysqli_fetch_array($sql_ticket_templates);
|
||||
if (mysqli_num_rows($sql_ticket_template) == 0) {
|
||||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='javascript:history.back()'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
require_once "../includes/footer.php";
|
||||
exit();
|
||||
}
|
||||
|
||||
$row = mysqli_fetch_array($sql_ticket_template);
|
||||
|
||||
$ticket_template_name = nullable_htmlentities($row['ticket_template_name']);
|
||||
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
|
||||
|
||||
@@ -56,8 +56,6 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
|
||||
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
|
||||
</div>
|
||||
|
||||
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?no"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>TEST</h5></a>
|
||||
|
||||
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
|
||||
<a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ $sql = mysqli_query(
|
||||
LEFT JOIN user_settings ON users.user_id = user_settings.user_id
|
||||
WHERE (user_name LIKE '%$q%' OR user_email LIKE '%$q%')
|
||||
AND user_type = 1
|
||||
AND user_archived_at IS NULL
|
||||
AND user_$archive_query
|
||||
ORDER BY $sort $order LIMIT $record_from, $record_to"
|
||||
);
|
||||
|
||||
@@ -26,16 +26,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-users mr-2"></i>Users</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addUserModal">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/user/user_add.php">
|
||||
<i class="fas fa-fw fa-user-plus mr-2"></i>New User
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
<div class="dropdown-menu">
|
||||
<!--<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#userInviteModal"><i class="fas fa-paper-plane mr-2"></i>Invite User</a>-->
|
||||
<!--<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/user/user_invite.php"><i class="fas fa-paper-plane mr-2"></i>Invite User</a>-->
|
||||
<?php if ($num_rows[0] > 1) { ?>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#exportUserModal"><i class="fa fa-fw fa-download mr-2"></i>Export</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="#" data-toggle="modal" data-target="#resetAllUserPassModal"><i class="fas fa-skull-crossbones mr-2"></i>IR</a>
|
||||
<a class="dropdown-item text-danger ajax-modal" href="#" data-modal-url="modals/user/user_all_reset_password.php" data-modal-size="lg"><i class="fas fa-skull-crossbones mr-2"></i>IR</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
@@ -53,6 +53,12 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<div class="btn-group float-right">
|
||||
<a href="?archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
|
||||
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">
|
||||
<i class="fa fa-fw fa-archive mr-2"></i>Archived
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
@@ -113,8 +119,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
$user_config_force_mfa = intval($row['user_config_force_mfa']);
|
||||
$user_role = intval($row['user_role_id']);
|
||||
$user_role_display = nullable_htmlentities($row['role_name']);
|
||||
$user_archived_at = nullable_htmlentities($row['user_archived_at']);
|
||||
$user_initials = nullable_htmlentities(initials($user_name));
|
||||
|
||||
|
||||
$sql_last_login = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT * FROM logs
|
||||
@@ -148,7 +156,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
?>
|
||||
<tr>
|
||||
<td class="text-center">
|
||||
<a href="#"
|
||||
<a href="#" title="UserID: <?= $user_id ?>"
|
||||
<?php if ($user_id !== $session_user_id) { // Prevent modifying self ?>
|
||||
class="ajax-modal"
|
||||
data-modal-url="modals/user/user_edit.php?id=<?= $user_id ?>"
|
||||
@@ -196,10 +204,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<i class="fas fa-fw fa-user-slash mr-2"></i>Disable
|
||||
</a>
|
||||
<?php } ?>
|
||||
<?php if ($user_archived_at) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger" href="#" data-toggle="modal" data-target="#archiveUserModal<?php echo $user_id; ?>">
|
||||
<a class="dropdown-item text-info ajax-modal" href="#" data-modal-url="modals/user/user_restore.php?id=<?= $user_id ?>">
|
||||
<i class="fas fa-fw fa-redo-alt mr-2"></i>Restore
|
||||
</a>
|
||||
<?php } else { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger ajax-modal" href="#" data-modal-url="modals/user/user_archive.php?id=<?= $user_id ?>">
|
||||
<i class="fas fa-fw fa-archive mr-2"></i>Archive
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
@@ -207,9 +222,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
require "modals/user/user_archive.php";
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
@@ -221,15 +233,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
function generatePassword() {
|
||||
document.getElementById("password").value = "<?php echo randomString() ?>"
|
||||
}
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once "modals/user/user_add.php";
|
||||
require_once "modals/user/user_invite.php";
|
||||
require_once "modals/user/user_export.php";
|
||||
require_once "modals/user/user_all_reset_password.php";
|
||||
require_once "../includes/footer.php";
|
||||
@@ -16,153 +16,151 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
?>
|
||||
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2">
|
||||
<i class="fas fa-fw fa-building mr-2"></i>Vendor Templates
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addVendorTemplateModal">
|
||||
<i class="fas fa-plus mr-2"></i>New Vendor Template
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Vendors Templates">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_template_name&order=<?php echo $disp; ?>">
|
||||
Vendor <?php if ($sort == 'vendor_template_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_template_description&order=<?php echo $disp; ?>">
|
||||
Description <?php if ($sort == 'vendor_template_description') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>Contact</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$vendor_template_id = intval($row['vendor_template_id']);
|
||||
$vendor_template_name = nullable_htmlentities($row['vendor_template_name']);
|
||||
$vendor_template_description = nullable_htmlentities($row['vendor_template_description']);
|
||||
if (empty($vendor_template_description)) {
|
||||
$vendor_template_description_display = "-";
|
||||
} else {
|
||||
$vendor_template_description_display = $vendor_template_description;
|
||||
}
|
||||
$vendor_template_account_number = nullable_htmlentities($row['vendor_template_account_number']);
|
||||
$vendor_template_contact_name = nullable_htmlentities($row['vendor_template_contact_name']);
|
||||
if (empty($vendor_template_contact_name)) {
|
||||
$vendor_template_contact_name_display = "-";
|
||||
} else {
|
||||
$vendor_template_contact_name_display = $vendor_template_contact_name;
|
||||
}
|
||||
$vendor_template_phone = formatPhoneNumber($row['vendor_template_phone']);
|
||||
$vendor_template_extension = nullable_htmlentities($row['vendor_template_extension']);
|
||||
$vendor_template_email = nullable_htmlentities($row['vendor_template_email']);
|
||||
$vendor_template_website = nullable_htmlentities($row['vendor_template_website']);
|
||||
$vendor_template_hours = nullable_htmlentities($row['vendor_template_hours']);
|
||||
$vendor_template_sla = nullable_htmlentities($row['vendor_template_sla']);
|
||||
$vendor_template_code = nullable_htmlentities($row['vendor_template_code']);
|
||||
$vendor_template_notes = nullable_htmlentities($row['vendor_template_notes']);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark ajax-modal" href="#"
|
||||
data-modal-url="modals/vendor_template/vendor_template_edit.php?id=<?= $vendor_template_id ?>">
|
||||
<i class="fa fa-fw fa-building text-secondary mr-2"></i><?php echo $vendor_template_name; ?>
|
||||
</a>
|
||||
<?php
|
||||
if (!empty($vendor_template_account_number)) {
|
||||
?>
|
||||
<br>
|
||||
<small class="text-secondary"><?php echo $vendor_template_account_number; ?></small>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</th>
|
||||
<td><?php echo $vendor_template_description_display; ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if (!empty($vendor_template_contact_name)) {
|
||||
?>
|
||||
<i class="fa fa-fw fa-user text-secondary mr-2 mb-2"></i><?php echo $vendor_template_contact_name_display; ?>
|
||||
<br>
|
||||
<?php
|
||||
} else {
|
||||
echo $vendor_template_contact_name_display;
|
||||
}
|
||||
|
||||
if (!empty($vendor_template_phone)) { ?>
|
||||
<i class="fa fa-fw fa-phone text-secondary mr-2 mb-2"></i><?php echo $vendor_template_phone; ?>
|
||||
<br>
|
||||
<?php }
|
||||
|
||||
if (!empty($vendor_template_email)) { ?>
|
||||
<i class="fa fa-fw fa-envelope text-secondary mr-2 mb-2"></i><?php echo $vendor_template_email; ?>
|
||||
<br>
|
||||
<?php } ?>
|
||||
|
||||
</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/vendor_template/vendor_template_edit.php?id=<?= $vendor_template_id ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<?php if ($session_user_role == 3) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_vendor=<?php echo $vendor_template_id; ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php require_once "../includes/filter_footer.php";
|
||||
?>
|
||||
<div class="card card-dark">
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2">
|
||||
<i class="fas fa-fw fa-building mr-2"></i>Vendor Templates
|
||||
</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/vendor_template/vendor_template_add.php">
|
||||
<i class="fas fa-plus mr-2"></i>New Vendor Template
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<form autocomplete="off">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Vendors Templates">
|
||||
<div class="input-group-append">
|
||||
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped table-borderless table-hover">
|
||||
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_template_name&order=<?php echo $disp; ?>">
|
||||
Vendor <?php if ($sort == 'vendor_template_name') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>
|
||||
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=vendor_template_description&order=<?php echo $disp; ?>">
|
||||
Description <?php if ($sort == 'vendor_template_description') { echo $order_icon; } ?>
|
||||
</a>
|
||||
</th>
|
||||
<th>Contact</th>
|
||||
<th class="text-center">Action</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
|
||||
while ($row = mysqli_fetch_array($sql)) {
|
||||
$vendor_template_id = intval($row['vendor_template_id']);
|
||||
$vendor_template_name = nullable_htmlentities($row['vendor_template_name']);
|
||||
$vendor_template_description = nullable_htmlentities($row['vendor_template_description']);
|
||||
if (empty($vendor_template_description)) {
|
||||
$vendor_template_description_display = "-";
|
||||
} else {
|
||||
$vendor_template_description_display = $vendor_template_description;
|
||||
}
|
||||
$vendor_template_account_number = nullable_htmlentities($row['vendor_template_account_number']);
|
||||
$vendor_template_contact_name = nullable_htmlentities($row['vendor_template_contact_name']);
|
||||
if (empty($vendor_template_contact_name)) {
|
||||
$vendor_template_contact_name_display = "-";
|
||||
} else {
|
||||
$vendor_template_contact_name_display = $vendor_template_contact_name;
|
||||
}
|
||||
$vendor_template_phone = formatPhoneNumber($row['vendor_template_phone']);
|
||||
$vendor_template_extension = nullable_htmlentities($row['vendor_template_extension']);
|
||||
$vendor_template_email = nullable_htmlentities($row['vendor_template_email']);
|
||||
$vendor_template_website = nullable_htmlentities($row['vendor_template_website']);
|
||||
$vendor_template_hours = nullable_htmlentities($row['vendor_template_hours']);
|
||||
$vendor_template_sla = nullable_htmlentities($row['vendor_template_sla']);
|
||||
$vendor_template_code = nullable_htmlentities($row['vendor_template_code']);
|
||||
$vendor_template_notes = nullable_htmlentities($row['vendor_template_notes']);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th>
|
||||
<a class="text-dark ajax-modal" href="#"
|
||||
data-modal-url="modals/vendor_template/vendor_template_edit.php?id=<?= $vendor_template_id ?>">
|
||||
<i class="fa fa-fw fa-building text-secondary mr-2"></i><?php echo $vendor_template_name; ?>
|
||||
</a>
|
||||
<?php
|
||||
if (!empty($vendor_template_account_number)) {
|
||||
?>
|
||||
<br>
|
||||
<small class="text-secondary"><?php echo $vendor_template_account_number; ?></small>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
</th>
|
||||
<td><?php echo $vendor_template_description_display; ?></td>
|
||||
<td>
|
||||
<?php
|
||||
if (!empty($vendor_template_contact_name)) {
|
||||
?>
|
||||
<i class="fa fa-fw fa-user text-secondary mr-2 mb-2"></i><?php echo $vendor_template_contact_name_display; ?>
|
||||
<br>
|
||||
<?php
|
||||
} else {
|
||||
echo $vendor_template_contact_name_display;
|
||||
}
|
||||
|
||||
if (!empty($vendor_template_phone)) { ?>
|
||||
<i class="fa fa-fw fa-phone text-secondary mr-2 mb-2"></i><?php echo $vendor_template_phone; ?>
|
||||
<br>
|
||||
<?php }
|
||||
|
||||
if (!empty($vendor_template_email)) { ?>
|
||||
<i class="fa fa-fw fa-envelope text-secondary mr-2 mb-2"></i><?php echo $vendor_template_email; ?>
|
||||
<br>
|
||||
<?php } ?>
|
||||
|
||||
</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/vendor_template/vendor_template_edit.php?id=<?= $vendor_template_id ?>">
|
||||
<i class="fas fa-fw fa-edit mr-2"></i>Edit
|
||||
</a>
|
||||
<?php if ($session_user_role == 3) { ?>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_vendor_template=<?= $vendor_template_id ?>">
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</a>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<?php
|
||||
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/vendor_template/vendor_template_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
|
||||
@@ -25,7 +25,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-piggy-bank mr-2"></i>Accounts</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAccountModal"><i class="fas fa-plus mr-2"></i>New Account</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/account/account_add.php"><i class="fas fa-plus mr-2"></i>New Account</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -123,6 +123,4 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/account/account_add.php";
|
||||
require_once "../includes/footer.php";
|
||||
@@ -432,7 +432,7 @@ if (isset($_GET['get_totp_token_via_id'])) {
|
||||
}
|
||||
|
||||
if (isset($_GET['get_readable_pass'])) {
|
||||
echo json_encode(GenerateReadablePassword(4));
|
||||
echo json_encode(GenerateReadablePassword(1));
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -675,3 +675,320 @@ if (isset($_POST['update_recurring_invoice_items_order'])) {
|
||||
echo json_encode(['status' => 'success']);
|
||||
exit;
|
||||
}
|
||||
|
||||
if (isset($_GET['client_duplicate_check'])) {
|
||||
enforceUserPermission('module_client', 2);
|
||||
|
||||
$name = sanitizeInput($_GET['name']);
|
||||
|
||||
$response['message'] = ""; // default
|
||||
|
||||
if (strlen($name) >= 5) {
|
||||
$sql_clients = mysqli_query($mysqli, "SELECT client_name FROM clients
|
||||
WHERE client_archived_at IS NULL
|
||||
AND client_name LIKE '%$name%'
|
||||
ORDER BY client_id DESC LIMIT 1"
|
||||
);
|
||||
|
||||
if (mysqli_num_rows($sql_clients) > 0) {
|
||||
while ($row = mysqli_fetch_array($sql_clients)) {
|
||||
$response['message'] = "<i class='fas fa-fw fa-copy mr-2'></i> Potential duplicate: <i>" . nullable_htmlentities($row['client_name']) . "</i> already exists.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
if (isset($_GET['contact_email_check'])) {
|
||||
enforceUserPermission('module_client', 2);
|
||||
|
||||
$email = sanitizeInput($_GET['email']);
|
||||
$domain = sanitizeInput(substr($_GET['email'], strpos($_GET['email'], '@') + 1));
|
||||
|
||||
$response['message'] = ""; // default
|
||||
|
||||
if (strlen($email) >= 3) {
|
||||
|
||||
// 1. Duplicate check
|
||||
$sql_contacts = mysqli_query($mysqli, "SELECT contact_email FROM contacts WHERE contact_email = '$email' LIMIT 1");
|
||||
if (mysqli_num_rows($sql_contacts) > 0) {
|
||||
while ($row = mysqli_fetch_array($sql_contacts)) {
|
||||
$response['message'] = "<i class='fas fa-fw fa-copy mr-2'></i> Potential duplicate: <i>" . nullable_htmlentities($row['contact_email']) . "</i> already exists.";
|
||||
}
|
||||
}
|
||||
|
||||
// 2. MX record check
|
||||
if (!checkdnsrr($domain, 'MX')) {
|
||||
$response['message'] = "<i class='fas fa-fw fa-exclamation-triangle mr-2'></i> E-mail domain invalid.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
}
|
||||
|
||||
if (isset($_GET['ai_reword'])) {
|
||||
|
||||
header('Content-Type: application/json');
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM ai_models LEFT JOIN ai_providers ON ai_model_ai_provider_id = ai_provider_id WHERE ai_model_use_case = 'General' LIMIT 1");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$model_name = $row['ai_model_name'];
|
||||
$promptText = $row['ai_model_prompt'];
|
||||
$url = $row['ai_provider_api_url'];
|
||||
$key = $row['ai_provider_api_key'];
|
||||
|
||||
// Collecting the input data from the AJAX request.
|
||||
$inputJSON = file_get_contents('php://input');
|
||||
$input = json_decode($inputJSON, TRUE); // Convert JSON into array.
|
||||
|
||||
$userText = $input['text'];
|
||||
|
||||
// Preparing the data for the OpenAI Chat API request.
|
||||
$data = [
|
||||
"model" => "$model_name", // Specify the model
|
||||
"messages" => [
|
||||
["role" => "system", "content" => $promptText],
|
||||
["role" => "user", "content" => $userText],
|
||||
],
|
||||
"temperature" => 0.5
|
||||
];
|
||||
|
||||
// Initialize cURL session to the OpenAI Chat API.
|
||||
$ch = curl_init("$url");
|
||||
|
||||
// Set cURL options for the request.
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $key,
|
||||
]);
|
||||
|
||||
// Execute the cURL session and capture the response.
|
||||
$response = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
|
||||
// Decode the JSON response.
|
||||
$responseData = json_decode($response, true);
|
||||
|
||||
// Check if the response contains the expected data and return it.
|
||||
if (isset($responseData['choices'][0]['message']['content'])) {
|
||||
// Get the response content.
|
||||
$content = $responseData['choices'][0]['message']['content'];
|
||||
|
||||
// Clean any leading "html" word or other unwanted text at the beginning.
|
||||
$content = preg_replace('/^html/i', '', $content); // Remove any occurrence of 'html' at the start
|
||||
|
||||
// Clean the response content to remove backticks or code block markers.
|
||||
$cleanedContent = str_replace('```', '', $content); // Remove backticks if they exist.
|
||||
|
||||
// Trim any leading/trailing whitespace.
|
||||
$cleanedContent = trim($cleanedContent);
|
||||
|
||||
// Return the cleaned response.
|
||||
echo json_encode(['rewordedText' => $cleanedContent]);
|
||||
} else {
|
||||
// Handle errors or unexpected response structure.
|
||||
echo json_encode(['rewordedText' => 'Failed to get a response from the AI API.']);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (isset($_GET['ai_create_document_template'])) {
|
||||
// get_ai_document_template.php
|
||||
|
||||
header('Content-Type: text/html; charset=UTF-8');
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM ai_models LEFT JOIN ai_providers ON ai_model_ai_provider_id = ai_provider_id WHERE ai_model_use_case = 'General' LIMIT 1");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$model_name = $row['ai_model_name'];
|
||||
$url = $row['ai_provider_api_url'];
|
||||
$key = $row['ai_provider_api_key'];
|
||||
|
||||
$prompt = $_POST['prompt'] ?? '';
|
||||
|
||||
// Basic validation
|
||||
if(empty($prompt)){
|
||||
echo "No prompt provided.";
|
||||
exit;
|
||||
}
|
||||
|
||||
// Prepare prompt
|
||||
$system_message = "You are a helpful IT documentation assistant. You will create a well-structured HTML template for IT documentation based on a given prompt. Include headings, subheadings, bullet points, and possibly tables for clarity. No Lorem Ipsum, use realistic placeholders and professional language.";
|
||||
$user_message = "Create an HTML formatted IT documentation template based on the following request:\n\n\"$prompt\"\n\nThe template should be structured, professional, and useful for IT staff. Include relevant sections, instructions, prerequisites, and best practices.";
|
||||
|
||||
$post_data = [
|
||||
"model" => "$model_name",
|
||||
"messages" => [
|
||||
["role" => "system", "content" => $system_message],
|
||||
["role" => "user", "content" => $user_message]
|
||||
],
|
||||
"temperature" => 0.5
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $key
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
|
||||
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
echo "Error: " . curl_error($ch);
|
||||
exit;
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$response_data = json_decode($response, true);
|
||||
$template = $response_data['choices'][0]['message']['content'] ?? "<p>No content returned from AI.</p>";
|
||||
|
||||
// Print the generated HTML template directly
|
||||
echo $template;
|
||||
}
|
||||
|
||||
if (isset($_GET['ai_ticket_summary'])) {
|
||||
|
||||
header('Content-Type: text/html; charset=UTF-8');
|
||||
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM ai_models LEFT JOIN ai_providers ON ai_model_ai_provider_id = ai_provider_id WHERE ai_model_use_case = 'General' LIMIT 1");
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$model_name = $row['ai_model_name'];
|
||||
$url = $row['ai_provider_api_url'];
|
||||
$key = $row['ai_provider_api_key'];
|
||||
|
||||
// Retrieve the ticket_id from POST
|
||||
$ticket_id = intval($_POST['ticket_id']);
|
||||
|
||||
// Query the database for ticket details
|
||||
$sql = mysqli_query($mysqli, "
|
||||
SELECT ticket_subject, ticket_details, ticket_source, ticket_priority, ticket_status_name, category_name
|
||||
FROM tickets
|
||||
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
|
||||
LEFT JOIN categories ON ticket_category = category_id
|
||||
WHERE ticket_id = $ticket_id
|
||||
LIMIT 1
|
||||
");
|
||||
$row = mysqli_fetch_assoc($sql);
|
||||
$ticket_subject = $row['ticket_subject'];
|
||||
$ticket_details = strip_tags($row['ticket_details']); // strip HTML for cleaner prompt
|
||||
$ticket_status = $row['ticket_status_name'];
|
||||
$ticket_category = $row['category_name'];
|
||||
$ticket_source = $row['ticket_source'];
|
||||
$ticket_priority = $row['ticket_priority'];
|
||||
|
||||
// Get ticket replies
|
||||
$sql_replies = mysqli_query($mysqli, "
|
||||
SELECT ticket_reply, ticket_reply_type, user_name
|
||||
FROM ticket_replies
|
||||
LEFT JOIN users ON ticket_reply_by = user_id
|
||||
WHERE ticket_reply_ticket_id = $ticket_id
|
||||
AND ticket_reply_archived_at IS NULL
|
||||
ORDER BY ticket_reply_id ASC
|
||||
");
|
||||
|
||||
$all_replies_text = "";
|
||||
while ($reply = mysqli_fetch_assoc($sql_replies)) {
|
||||
$reply_type = $reply['ticket_reply_type'];
|
||||
$reply_text = strip_tags($reply['ticket_reply']);
|
||||
$reply_by = $reply['user_name'];
|
||||
$all_replies_text .= "\nReply Type: $reply_type Reply By: $reply_by: Reply Text: $reply_text";
|
||||
}
|
||||
|
||||
$prompt = "
|
||||
Summarize the following IT support ticket and its responses in a concise, clear, and professional manner.
|
||||
The summary should include:
|
||||
|
||||
1. Main Issue: What was the problem reported by the user?
|
||||
2. Actions Taken: What steps were taken to address the issue?
|
||||
3. Resolution or Next Steps: Was the issue resolved or is it ongoing?
|
||||
|
||||
Please ensure:
|
||||
- If there are multiple issues, summarize each separately.
|
||||
- Urgency: If the ticket or replies express urgency or escalation, highlight it.
|
||||
- Attachments: If mentioned in the ticket, note any relevant attachments or files.
|
||||
- Avoid extra explanations or unnecessary information.
|
||||
|
||||
Ticket Data:
|
||||
- Ticket Source: $ticket_source
|
||||
- Current Ticket Status: $ticket_status
|
||||
- Ticket Priority: $ticket_priority
|
||||
- Ticket Category: $ticket_category
|
||||
- Ticket Subject: $ticket_subject
|
||||
- Ticket Details: $ticket_details
|
||||
- Replies:
|
||||
$all_replies_text
|
||||
|
||||
Formatting instructions:
|
||||
- Use valid HTML tags only.
|
||||
- Use <h3> for section headers (Main Issue, Actions Taken, Resolution).
|
||||
- Use <ul><li> for bullet points under each section.
|
||||
- Do NOT wrap the output in ```html or any other code fences.
|
||||
- Do NOT include <html>, <head>, or <body>.
|
||||
- Output only the summary content in pure HTML.
|
||||
If any part of the ticket or replies is unclear or ambiguous, mention it in the summary and suggest if further clarification is needed.
|
||||
";
|
||||
|
||||
// Prepare the POST data
|
||||
$post_data = [
|
||||
"model" => "$model_name",
|
||||
"messages" => [
|
||||
["role" => "system", "content" => "Your task is to summarize IT support tickets with clear, concise details."],
|
||||
["role" => "user", "content" => $prompt]
|
||||
],
|
||||
"temperature" => 0.3
|
||||
];
|
||||
|
||||
$ch = curl_init();
|
||||
curl_setopt($ch, CURLOPT_URL, $url);
|
||||
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
|
||||
curl_setopt($ch, CURLOPT_POST, true);
|
||||
curl_setopt($ch, CURLOPT_HTTPHEADER, [
|
||||
'Content-Type: application/json',
|
||||
'Authorization: Bearer ' . $key
|
||||
]);
|
||||
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($post_data));
|
||||
|
||||
$response = curl_exec($ch);
|
||||
if (curl_errno($ch)) {
|
||||
echo "Error: " . curl_error($ch);
|
||||
exit;
|
||||
}
|
||||
curl_close($ch);
|
||||
|
||||
$response_data = json_decode($response, true);
|
||||
$summary = $response_data['choices'][0]['message']['content'] ?? "No summary available.";
|
||||
|
||||
|
||||
echo $summary; // nl2br to convert newlines to <br>, htmlspecialchars to prevent XSS
|
||||
}
|
||||
|
||||
// Stops people trying to use sub-domains in the domains tracker
|
||||
if (isset($_GET['apex_domain_check'])) {
|
||||
enforceUserPermission('module_support', 2);
|
||||
|
||||
$domain = sanitizeInput($_GET['domain']);
|
||||
|
||||
$response['message'] = ""; // default
|
||||
|
||||
if (strlen($domain) >= 4) {
|
||||
|
||||
// SOA record check
|
||||
// This isn't 100%, as sub-domains can have their own SOA but will capture 99%
|
||||
if (!checkdnsrr($domain, 'SOA')) {
|
||||
$response['message'] = "<i class='fas fa-fw fa-exclamation-triangle mr-2'></i> Domain name is invalid.";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
echo json_encode($response);
|
||||
}
|
||||
1256
agent/asset_details.php
Normal file
1256
agent/asset_details.php
Normal file
File diff suppressed because it is too large
Load Diff
@@ -37,17 +37,23 @@ enforceUserPermission('module_support');
|
||||
//Asset Type from GET
|
||||
if (isset($_GET['type']) && ($_GET['type']) == 'workstation') {
|
||||
$type_query = "asset_type = 'desktop' OR asset_type = 'laptop'";
|
||||
$type_filter = "workstation";
|
||||
} elseif (isset($_GET['type']) && ($_GET['type']) == 'server') {
|
||||
$type_query = "asset_type = 'server'";
|
||||
$type_filter = "server";
|
||||
} elseif (isset($_GET['type']) && ($_GET['type']) == 'virtual') {
|
||||
$type_query = "asset_type = 'Virtual Machine'";
|
||||
$type_filter = "virtual";
|
||||
} elseif (isset($_GET['type']) && ($_GET['type']) == 'network') {
|
||||
$type_query = "asset_type = 'Firewall/Router' OR asset_type = 'Switch' OR asset_type = 'Access Point'";
|
||||
$type_filter = "network";
|
||||
} elseif (isset($_GET['type']) && ($_GET['type']) == 'other') {
|
||||
$type_query = "asset_type NOT LIKE 'laptop' AND asset_type NOT LIKE 'desktop' AND asset_type NOT LIKE 'server' AND asset_type NOT LIKE 'virtual machine' AND asset_type NOT LIKE 'firewall/router' AND asset_type NOT LIKE 'switch' AND asset_type NOT LIKE 'access point'";
|
||||
$type_filter = "other";
|
||||
} else {
|
||||
$type_query = "asset_type LIKE '%'";
|
||||
$_GET['type'] = '';
|
||||
$type_filter = '';
|
||||
}
|
||||
|
||||
if (!$client_url) {
|
||||
@@ -72,6 +78,18 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
|
||||
$location_filter = 0;
|
||||
}
|
||||
|
||||
// Tags Filter
|
||||
if (isset($_GET['tags']) && is_array($_GET['tags']) && !empty($_GET['tags'])) {
|
||||
// Sanitize each element of the tags array
|
||||
$sanitizedTags = array_map('intval', $_GET['tags']);
|
||||
// Convert the sanitized tags into a comma-separated string
|
||||
$tag_filter = implode(",", $sanitizedTags);
|
||||
$tag_query = "AND tag_id IN ($tag_filter)";
|
||||
} else {
|
||||
$tag_filter = 0;
|
||||
$tag_query = '';
|
||||
}
|
||||
|
||||
//Get Asset Counts
|
||||
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "
|
||||
SELECT
|
||||
@@ -87,9 +105,13 @@ $row = mysqli_fetch_assoc(mysqli_query($mysqli, "
|
||||
LEFT JOIN contacts ON asset_contact_id = contact_id
|
||||
LEFT JOIN locations ON asset_location_id = location_id
|
||||
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
|
||||
LEFT JOIN asset_tags ON asset_tag_asset_id = asset_id
|
||||
LEFT JOIN tags ON tag_id = asset_tag_tag_id
|
||||
WHERE $archive_query
|
||||
$tag_query
|
||||
$access_permission_query
|
||||
$client_query
|
||||
GROUP BY asset_id
|
||||
) AS filtered_assets;
|
||||
"));
|
||||
|
||||
@@ -111,9 +133,6 @@ $network_count = intval($row['network_count']);
|
||||
//Other Count
|
||||
$other_count = intval($row['other_count']);
|
||||
|
||||
//Rebuild URL
|
||||
$url_query_strings_sort = http_build_query($get_copy);
|
||||
|
||||
$sql = mysqli_query(
|
||||
$mysqli,
|
||||
"SELECT SQL_CALC_FOUND_ROWS * FROM assets
|
||||
@@ -121,31 +140,21 @@ $sql = mysqli_query(
|
||||
LEFT JOIN contacts ON asset_contact_id = contact_id
|
||||
LEFT JOIN locations ON asset_location_id = location_id
|
||||
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
|
||||
LEFT JOIN asset_tags ON asset_tag_asset_id = asset_id
|
||||
LEFT JOIN tags ON tag_id = asset_tag_tag_id
|
||||
WHERE $archive_query
|
||||
AND (asset_name LIKE '%$q%' OR asset_description LIKE '%$q%' OR asset_type LIKE '%$q%' OR interface_ip LIKE '%$q%' OR interface_ipv6 LIKE '%$q%' OR interface_mac LIKE '%$q%' OR asset_make LIKE '%$q%' OR asset_model LIKE '%$q%' OR asset_serial LIKE '%$q%' OR asset_os LIKE '%$q%' OR contact_name LIKE '%$q%' OR location_name LIKE '%$q%' OR client_name LIKE '%$q%')
|
||||
$tag_query
|
||||
AND (asset_name LIKE '%$q%' OR asset_description LIKE '%$q%' OR asset_type LIKE '%$q%' OR interface_ip LIKE '%$q%' OR interface_ipv6 LIKE '%$q%' OR interface_mac LIKE '%$q%' OR asset_make LIKE '%$q%' OR asset_model LIKE '%$q%' OR asset_serial LIKE '%$q%' OR asset_os LIKE '%$q%' OR contact_name LIKE '%$q%' OR location_name LIKE '%$q%' OR client_name LIKE '%$q%' OR tag_name LIKE '%$q%')
|
||||
AND ($type_query)
|
||||
$access_permission_query
|
||||
$location_query
|
||||
$client_query
|
||||
|
||||
GROUP BY asset_id
|
||||
ORDER BY $sort $order LIMIT $record_from, $record_to"
|
||||
);
|
||||
|
||||
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
|
||||
// OS typeahead suggestions
|
||||
$os_sql = mysqli_query($mysqli, "SELECT DISTINCT asset_os AS label FROM assets WHERE asset_archived_at IS NULL");
|
||||
if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
$os_arr = [];
|
||||
while ($row = mysqli_fetch_assoc($os_sql)) {
|
||||
// jQuery UI Autocomplete expects {label: "...", value: "..."}
|
||||
$label = $row['label'];
|
||||
$os_arr[] = ['label' => $label, 'value' => $label];
|
||||
}
|
||||
$json_os = json_encode($os_arr);
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
<div class="col-sm-12 mb-3">
|
||||
@@ -185,8 +194,8 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
<div class="card-tools">
|
||||
<?php if (lookupUserPermission("module_support") >= 2) { ?>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAssetModal">
|
||||
<i class="fas fa-plus mr-2"></i>New <?php if (!empty($_GET['type'])) { echo ucwords(strip_tags(nullable_htmlentities($_GET['type']))); } else { echo "Asset"; } ?>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/asset/asset_add.php?<?= $client_url ?>&type=<?= $type_filter ?>">
|
||||
<i class="fas fa-plus mr-2"></i>New <?php if ($type_filter) { echo ucwords($type_filter); } else { echo "Asset"; } ?>
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
<div class="dropdown-menu">
|
||||
@@ -277,7 +286,32 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
</div>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-2">
|
||||
<div class="input-group mb-3 mb-md-0">
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
|
||||
|
||||
<?php
|
||||
$sql_tags_filter = mysqli_query($mysqli, "
|
||||
SELECT tag_id, tag_name
|
||||
FROM tags
|
||||
LEFT JOIN asset_tags ON asset_tag_tag_id = tag_id
|
||||
LEFT JOIN assets ON asset_tag_asset_id = asset_id
|
||||
WHERE tag_type = 5
|
||||
$client_query OR tag_id IN ($tag_filter)
|
||||
GROUP BY tag_id
|
||||
HAVING COUNT(asset_tag_asset_id) > 0 OR tag_id IN ($tag_filter)
|
||||
");
|
||||
while ($row = mysqli_fetch_array($sql_tags_filter)) {
|
||||
$tag_id = intval($row['tag_id']);
|
||||
$tag_name = nullable_htmlentities($row['tag_name']); ?>
|
||||
|
||||
<option value="<?php echo $tag_id ?>" <?php if (isset($_GET['tags']) && in_array($tag_id, $_GET['tags'])) { echo 'selected'; } ?>> <?php echo $tag_name ?> </option>
|
||||
|
||||
<?php } ?>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="show_column[]" data-placeholder="- Show Additional Columns -" multiple>
|
||||
<option
|
||||
@@ -298,7 +332,7 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-3">
|
||||
<div class="col-md-2">
|
||||
<div class="btn-group float-right">
|
||||
<a href="?<?php echo $client_url; ?>&archived=<?php if($archived == 1){ echo 0; } else { echo 1; } ?>"
|
||||
class="btn btn-<?php if($archived == 1){ echo "primary"; } else { echo "default"; } ?>">
|
||||
@@ -310,27 +344,47 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if ($client_url) { ?>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignContactModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_assign_contact.php?<?= $client_url ?>"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-user mr-2"></i>Assign Contact
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignLocationModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_assign_location.php?<?= $client_url ?>"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-map-marker-alt mr-2"></i>Assign Location
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<?php } ?>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignPhysicalLocationModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_assign_tags.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-tags mr-2"></i>Assign Tags
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_assign_physical_location.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-map-marker-alt mr-2"></i>Set Physical Location
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditStatusModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_edit_status.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-info mr-2"></i>Set Status
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAddTicketModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_add_ticket.php"
|
||||
data-modal-size="lg"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-life-ring mr-2"></i>Create Tickets
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkTransferAssetClientModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/asset/asset_bulk_transfer_client.php?<?= $client_url ?>"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-arrow-right mr-2"></i>Transfer to Client
|
||||
</a>
|
||||
<?php if ($archived) { ?>
|
||||
@@ -570,20 +624,48 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
$sql_credentials = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_asset_id = $asset_id");
|
||||
$credential_count = mysqli_num_rows($sql_credentials);
|
||||
|
||||
// Tags
|
||||
$asset_tag_name_display_array = array();
|
||||
$asset_tag_id_array = array();
|
||||
$sql_asset_tags = mysqli_query($mysqli, "SELECT * FROM asset_tags LEFT JOIN tags ON asset_tag_tag_id = tag_id WHERE asset_tag_asset_id = $asset_id ORDER BY tag_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql_asset_tags)) {
|
||||
|
||||
$asset_tag_id = intval($row['tag_id']);
|
||||
$asset_tag_name = nullable_htmlentities($row['tag_name']);
|
||||
$asset_tag_color = nullable_htmlentities($row['tag_color']);
|
||||
if (empty($asset_tag_color)) {
|
||||
$asset_tag_color = "dark";
|
||||
}
|
||||
$asset_tag_icon = nullable_htmlentities($row['tag_icon']);
|
||||
if (empty($asset_tag_icon)) {
|
||||
$asset_tag_icon = "tag";
|
||||
}
|
||||
|
||||
$asset_tag_id_array[] = $asset_tag_id;
|
||||
$asset_tag_name_display_array[] = "<a href='assets.php?$client_url tags[]=$asset_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $asset_tag_color;'><i class='fa fa-fw fa-$asset_tag_icon mr-2'></i>$asset_tag_name</span></a>";
|
||||
}
|
||||
$asset_tags_display = implode('', $asset_tag_name_display_array);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td class="pr-0 bg-light">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input bulk-select" type="checkbox" name="asset_ids[]" value="<?php echo $asset_id ?>">
|
||||
<input class="form-check-input bulk-select" type="checkbox" name="asset_ids[]" value="<?= $asset_id ?>">
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<a class="text-dark" href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">
|
||||
<a class="text-dark" href="asset_details.php?client_id=<?= $client_id ?>&asset_id=<?= $asset_id ?>">
|
||||
<div class="media">
|
||||
<i class="fa fa-fw fa-2x fa-<?php echo $device_icon; ?> mr-3 mt-1"></i>
|
||||
<i class="fa fa-fw fa-2x fa-<?= $device_icon ?> mr-3 mt-1"></i>
|
||||
<div class="media-body">
|
||||
<div><?php echo $asset_name; ?></div>
|
||||
<div><small class="text-secondary"><?php echo $asset_description; ?></small></div>
|
||||
<div><?= $asset_name ?></div>
|
||||
<div><small class="text-secondary"><?= $asset_description ?></small></div>
|
||||
<?php
|
||||
if ($asset_tags_display) { ?>
|
||||
<div class="mt-1">
|
||||
<?= $asset_tags_display ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</a>
|
||||
@@ -699,16 +781,6 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
if ($client_url) {
|
||||
require_once "modals/asset/asset_bulk_assign_contact.php";
|
||||
require_once "modals/asset/asset_bulk_assign_location.php";
|
||||
}
|
||||
?>
|
||||
<?php require_once "modals/asset/asset_bulk_assign_physical_location.php"; ?>
|
||||
<?php require_once "modals/asset/asset_bulk_transfer_client.php"; ?>
|
||||
<?php require_once "modals/asset/asset_bulk_edit_status.php"; ?>
|
||||
<?php require_once "modals/asset/asset_bulk_add_ticket.php"; ?>
|
||||
</form>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
@@ -716,24 +788,7 @@ if ($os_sql && mysqli_num_rows($os_sql) > 0) {
|
||||
|
||||
<script src="../js/bulk_actions.js"></script>
|
||||
|
||||
<!-- JSON Autocomplete / type ahead -->
|
||||
<link rel="stylesheet" href="../plugins/jquery-ui/jquery-ui.min.css">
|
||||
<script src="../plugins/jquery-ui/jquery-ui.min.js"></script>
|
||||
<script>
|
||||
$(function() {
|
||||
var operatingSystems = <?php echo $json_os; ?>;
|
||||
$("#os").autocomplete({
|
||||
source: operatingSystems, // Should be an array of objects with 'label' and 'value'
|
||||
select: function(event, ui) {
|
||||
$("#os").val(ui.item.label); // Set the input field value to the selected label
|
||||
return false;
|
||||
}
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
<?php
|
||||
require_once "modals/asset/asset_add.php";
|
||||
require_once "modals/asset/asset_export.php";
|
||||
if ($client_url) {
|
||||
require_once "modals/asset/asset_import.php";
|
||||
@@ -33,7 +33,7 @@ if (isset($_GET['calendar_id'])) {
|
||||
<div class="card-header py-2">
|
||||
<h3 class="card-title mt-1">Calendars</h3>
|
||||
<div class="card-tools">
|
||||
<button type="button" class="btn btn-dark btn-sm" data-toggle="modal" data-target="#addCalendarModal"><i class="fas fa-plus"></i></button>
|
||||
<button type="button" class="btn btn-dark btn-sm ajax-modal" data-modal-url="modals/calendar/calendar_add.php"><i class="fas fa-plus"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
@@ -82,8 +82,6 @@ if (isset($_GET['calendar_id'])) {
|
||||
<?php
|
||||
|
||||
require_once "modals/calendar/calendar_event_add.php";
|
||||
require_once "modals/calendar/calendar_add.php";
|
||||
|
||||
|
||||
//loop through IDs and create a modal for each
|
||||
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
|
||||
@@ -106,7 +104,7 @@ while ($row = mysqli_fetch_array($sql)) {
|
||||
<?php require_once "../includes/footer.php";
|
||||
?>
|
||||
|
||||
<script src='../plugins/fullcalendar/dist/index.global.js'></script>
|
||||
<script src='/plugins/fullcalendar/dist/index.global.js'></script>
|
||||
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@@ -64,7 +64,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title mt-2"><i class="fas fa-fw fa-lock mr-2"></i>Certificates</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addCertificateModal"><i class="fas fa-plus mr-2"></i>New Certificate</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/certificate/certificate_add.php?<?= $client_url ?>"><i class="fas fa-plus mr-2"></i>New Certificate</button>
|
||||
<?php if ($num_rows[0] > 0) { ?>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
<div class="dropdown-menu">
|
||||
@@ -249,8 +249,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<td><?php echo $certificate_issued_by; ?></td>
|
||||
|
||||
<td>
|
||||
<div><?php echo $certificate_expire; ?></div>
|
||||
<div><small><?php echo $certificate_expire_ago; ?></small></div>
|
||||
<div><?php echo $certificate_expire ?: '-'; ?></div>
|
||||
<?php if (!empty($certificate_expire)) { ?>
|
||||
<div><small><?php echo $certificate_expire_ago; ?></small></div>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<?php if (!$client_url) { ?>
|
||||
<td><a href="certificates.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
|
||||
@@ -303,11 +305,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/certificate/certificate_add.php";
|
||||
require_once "modals/certificate/certificate_export.php";
|
||||
?>
|
||||
|
||||
<script src="../js/bulk_actions.js"></script>
|
||||
<script src="js/certificate_fetch_ssl.js"></script>
|
||||
|
||||
<?php require_once "../includes/footer.php";
|
||||
@@ -86,7 +86,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-tools">
|
||||
<?php if (lookupUserPermission("module_client") >= 2) { ?>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addClientModal">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/client/client_add.php<?php if ($leads_filter) { echo "?lead=1"; } ?>">
|
||||
<i class="fas fa-plus mr-2"></i>New
|
||||
<?php if ($leads_filter == 0) { echo "Client"; } else { echo "Lead"; } ?>
|
||||
</button>
|
||||
@@ -137,23 +137,41 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<i class="fas fa-fw fa-layer-group"></i><span class="d-none d-sm-inline ml-2">Action</span> (<span id="selectedCount">0</span>)
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditHourlyRateModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/client/client_bulk_add_ticket.php"
|
||||
data-modal-size="lg"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-life-ring mr-2"></i>Open Tickets
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/client/client_bulk_edit_hourly_rate.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-clock mr-2"></i>Set Hourly Rate
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditIndustryModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/client/client_bulk_edit_industry.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-briefcase mr-2"></i>Set Industry
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditReferralModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/client/client_bulk_edit_referral.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-link mr-2"></i>Set Referral
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignTagsModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/client/client_bulk_assign_tags.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-tags mr-2"></i>Assign Tags
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkSendEmailModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/client/client_bulk_email.php"
|
||||
data-modal-size="lg"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send Email
|
||||
</a>
|
||||
<?php if ($archived) { ?>
|
||||
@@ -178,49 +196,27 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div
|
||||
class="collapse
|
||||
<?php
|
||||
if (
|
||||
isset($_GET['dtf'])
|
||||
|| $industry_filter
|
||||
|| $referral_filter
|
||||
|| (isset($_GET['tags']) && is_array($_GET['tags']))
|
||||
|| $_GET['canned_date'] !== "custom" )
|
||||
{
|
||||
echo "show";
|
||||
}
|
||||
if (isset($_GET['dtf']) && $_GET['dtf'] !== '1970-01-01'
|
||||
|| $industry_filter
|
||||
|| $referral_filter
|
||||
|| (isset($_GET['tags']) && is_array($_GET['tags']))
|
||||
)
|
||||
{ echo "show"; }
|
||||
?>
|
||||
"
|
||||
id="advancedFilter"
|
||||
>
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Canned date</label>
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
|
||||
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="custom">Custom</option>
|
||||
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
|
||||
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
|
||||
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
|
||||
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
|
||||
</select>
|
||||
<label>Date range</label>
|
||||
<input type="text" id="dateFilter" class="form-control" autocomplete="off">
|
||||
<input type="hidden" name="canned_date" id="canned_date" value="<?php echo nullable_htmlentities($_GET['canned_date']) ?? ''; ?>">
|
||||
<input type="hidden" name="dtf" id="dtf" value="<?php echo nullable_htmlentities($dtf ?? ''); ?>">
|
||||
<input type="hidden" name="dtt" id="dtt" value="<?php echo nullable_htmlentities($dtt ?? ''); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date from</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="form-group">
|
||||
<label>Date to</label>
|
||||
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-2">
|
||||
<div class="col-md-3">
|
||||
<div class="form-group">
|
||||
<label>Tag</label>
|
||||
<select onchange="this.form.submit()" class="form-control select2" name="tags[]" data-placeholder="- Select Tags -" multiple>
|
||||
@@ -286,7 +282,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</form>
|
||||
</div>
|
||||
|
||||
<form id="bulkActions" action="post.php" method="post" enctype="multipart/form-data">
|
||||
<form id="bulkActions" action="post.php" method="post">
|
||||
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
|
||||
<div class="table-responsive-sm">
|
||||
<table class="table table-hover mb-0 text-nowrap">
|
||||
@@ -504,7 +500,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<?php } ?>
|
||||
<?php
|
||||
if (!empty($client_tags_display)) { ?>
|
||||
<div class="mt-1">
|
||||
<div class="mt-1 text-wrap">
|
||||
<?php echo $client_tags_display; ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
@@ -566,10 +562,12 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<span class="text-secondary">Paid</span>
|
||||
<span><?php echo numfmt_format_currency($currency_format, $amount_paid, $session_company_currency); ?></span>
|
||||
</div>
|
||||
<?php if ($credit_balance > 0) { ?>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="text-secondary">Credit</span>
|
||||
<span class="text-success"><?php echo numfmt_format_currency($currency_format, $credit_balance, $session_company_currency); ?></span>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="d-flex justify-content-between">
|
||||
<span class="text-secondary">Monthly</span>
|
||||
<span><?php echo numfmt_format_currency($currency_format, $recurring_monthly, $session_company_currency); ?></span>
|
||||
@@ -616,13 +614,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php
|
||||
require_once "modals/client/client_bulk_edit_industry.php";
|
||||
require_once "modals/client/client_bulk_edit_referral.php";
|
||||
require_once "modals/client/client_bulk_edit_hourly_rate.php";
|
||||
require_once "modals/client/client_bulk_assign_tags.php";
|
||||
require_once "modals/client/client_bulk_email.php";
|
||||
?>
|
||||
</form>
|
||||
<!-- Ends Card Body -->
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
@@ -632,7 +623,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<script src="../js/bulk_actions.js"></script>
|
||||
|
||||
<?php
|
||||
require_once "modals/client/client_add.php";
|
||||
require_once "modals/client/client_import.php";
|
||||
require_once "modals/client/client_export.php";
|
||||
require_once "../includes/footer.php";
|
||||
@@ -20,8 +20,15 @@ if (isset($_GET['contact_id'])) {
|
||||
LEFT JOIN users ON user_id = contact_user_id
|
||||
WHERE contact_id = $contact_id
|
||||
$client_query
|
||||
LIMIT 1
|
||||
");
|
||||
|
||||
if (mysqli_num_rows($sql) == 0) {
|
||||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='javascript:history.back()'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
require_once "../includes/footer.php";
|
||||
exit();
|
||||
}
|
||||
|
||||
$row = mysqli_fetch_array($sql);
|
||||
$client_id = intval($row['client_id']);
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
@@ -57,7 +64,14 @@ if (isset($_GET['contact_id'])) {
|
||||
}
|
||||
|
||||
// Related Assets Query - 1 to 1 relationship
|
||||
$sql_related_assets = mysqli_query($mysqli, "SELECT * FROM assets LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1 WHERE asset_contact_id = $contact_id ORDER BY asset_name DESC");
|
||||
$sql_related_assets = mysqli_query($mysqli, "SELECT * FROM assets
|
||||
LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1
|
||||
LEFT JOIN asset_tags ON asset_tag_asset_id = asset_id
|
||||
LEFT JOIN tags ON tag_id = asset_tag_tag_id
|
||||
WHERE asset_contact_id = $contact_id
|
||||
GROUP BY asset_id
|
||||
ORDER BY asset_name ASC"
|
||||
);
|
||||
$asset_count = mysqli_num_rows($sql_related_assets);
|
||||
|
||||
// Linked Software Licenses
|
||||
@@ -83,7 +97,7 @@ if (isset($_GET['contact_id'])) {
|
||||
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
|
||||
WHERE credential_contact_id = $contact_id
|
||||
GROUP BY credentials.credential_id
|
||||
ORDER BY credential_name DESC
|
||||
ORDER BY credential_name ASC
|
||||
");
|
||||
$credential_count = mysqli_num_rows($sql_related_credentials);
|
||||
|
||||
@@ -255,27 +269,27 @@ if (isset($_GET['contact_id'])) {
|
||||
<div class="dropdown dropleft mr-2">
|
||||
<button type="button" class="btn btn-primary" data-toggle="dropdown"><i class="fas fa-plus mr-2"></i>New</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addTicketModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/ticket/ticket_add.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>" data-modal-size="lg">
|
||||
<i class="fa fa-fw fa-life-ring mr-2"></i>New Ticket
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addRecurringTicketModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/recurring_ticket/recurring_ticket_add.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>" data-modal-size="lg">
|
||||
<i class="fa fa-fw fa-recycle mr-2"></i>New Recurring Ticket
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addAssetModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/asset/asset_add.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>">
|
||||
<i class="fa fa-fw fa-desktop mr-2"></i>New Asset
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addCredentialModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/credential/credential_add.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>">
|
||||
<i class="fa fa-fw fa-key mr-2"></i>New Credential
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addDocumentModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/document/document_add.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>" data-modal-size="lg">
|
||||
<i class="fa fa-fw fa-file-alt mr-2"></i>New Document
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#uploadFilesModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/file/file_upload.php?<?= $client_url ?>&contact_id=<?= $contact_id ?>">
|
||||
<i class="fa fa-fw fa-upload mr-2"></i>Upload file(s)
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
@@ -394,6 +408,28 @@ if (isset($_GET['contact_id'])) {
|
||||
$asset_created_at = nullable_htmlentities($row['asset_created_at']);
|
||||
$device_icon = getAssetIcon($asset_type);
|
||||
|
||||
// Tags
|
||||
$asset_tag_name_display_array = array();
|
||||
$asset_tag_id_array = array();
|
||||
$sql_asset_tags = mysqli_query($mysqli, "SELECT * FROM asset_tags LEFT JOIN tags ON asset_tag_tag_id = tag_id WHERE asset_tag_asset_id = $asset_id ORDER BY tag_name ASC");
|
||||
while ($row = mysqli_fetch_array($sql_asset_tags)) {
|
||||
|
||||
$asset_tag_id = intval($row['tag_id']);
|
||||
$asset_tag_name = nullable_htmlentities($row['tag_name']);
|
||||
$asset_tag_color = nullable_htmlentities($row['tag_color']);
|
||||
if (empty($asset_tag_color)) {
|
||||
$asset_tag_color = "dark";
|
||||
}
|
||||
$asset_tag_icon = nullable_htmlentities($row['tag_icon']);
|
||||
if (empty($asset_tag_icon)) {
|
||||
$asset_tag_icon = "tag";
|
||||
}
|
||||
|
||||
$asset_tag_id_array[] = $asset_tag_id;
|
||||
$asset_tag_name_display_array[] = "<a href='assets.php?$client_url tags[]=$asset_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $asset_tag_color;'><i class='fa fa-fw fa-$asset_tag_icon mr-2'></i>$asset_tag_name</span></a>";
|
||||
}
|
||||
$asset_tags_display = implode('', $asset_tag_name_display_array);
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<th>
|
||||
@@ -406,6 +442,12 @@ if (isset($_GET['contact_id'])) {
|
||||
<div class="mt-0">
|
||||
<small class="text-muted"><?php echo $asset_description; ?></small>
|
||||
</div>
|
||||
<?php
|
||||
if ($asset_tags_display) { ?>
|
||||
<div class="mt-1">
|
||||
<?= $asset_tags_display ?>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</th>
|
||||
<td><?php echo $asset_type; ?></td>
|
||||
<td>
|
||||
@@ -1172,12 +1214,4 @@ if (isset($_GET['contact_id'])) {
|
||||
<script src="js/credential_show_otp_via_id.js"></script>
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/ticket/ticket_add.php";
|
||||
require_once "modals/recurring_ticket/recurring_ticket_add.php";
|
||||
require_once "modals/asset/asset_add.php";
|
||||
require_once "modals/credential/credential_add.php";
|
||||
require_once "modals/document/document_add.php";
|
||||
require_once "modals/file/file_upload.php";
|
||||
|
||||
require_once "../includes/footer.php";
|
||||
@@ -90,7 +90,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-address-book mr-2"></i>Contacts</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addContactModal">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/contact/contact_add.php?client_id=<?= $client_id ?>">
|
||||
<i class="fas fa-plus mr-2"></i>New Contact
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
@@ -220,28 +220,41 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<?php if ($client_url) { ?>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignLocationModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/contact/contact_bulk_assign_location.php?<?= $client_url ?>"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-map-marker-alt mr-2"></i>Assign Location
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<?php } ?>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditPhoneModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/contact/contact_bulk_edit_phone.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-phone-alt mr-2"></i>Set Phone Number
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditDepartmentModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/contact/contact_bulk_edit_department.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-users mr-2"></i>Set Department
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkEditRoleModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/contact/contact_bulk_edit_role.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-user-shield mr-2"></i>Set Roles
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignTagsModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/contact/contact_bulk_assign_tags.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-tags mr-2"></i>Assign Tags
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkSendEmailModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/contact/contact_bulk_email.php"
|
||||
data-modal-size="lg"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send Email
|
||||
</a>
|
||||
<?php if ($archived) { ?>
|
||||
@@ -545,63 +558,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php if ($client_url) { require_once "modals/contact/contact_bulk_assign_location.php"; } ?>
|
||||
<?php require_once "modals/contact/contact_bulk_edit_phone.php"; ?>
|
||||
<?php require_once "modals/contact/contact_bulk_edit_department.php"; ?>
|
||||
<?php require_once "modals/contact/contact_bulk_edit_role.php"; ?>
|
||||
<?php require_once "modals/contact/contact_bulk_assign_tags.php"; ?>
|
||||
<?php require_once "modals/contact/contact_bulk_email.php"; ?>
|
||||
</form>
|
||||
<?php require_once "../includes/filter_footer.php";
|
||||
?>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- JavaScript to Show/Hide Password Form Group -->
|
||||
<script>
|
||||
|
||||
function generatePassword(type, id) {
|
||||
// Send a GET request to ajax.php as ajax.php?get_readable_pass=true
|
||||
jQuery.get(
|
||||
"ajax.php", {
|
||||
get_readable_pass: 'true'
|
||||
},
|
||||
function(data) {
|
||||
//If we get a response from post.php, parse it as JSON
|
||||
const password = JSON.parse(data);
|
||||
|
||||
// Set the password value to the correct modal, based on the type
|
||||
if (type == "add") {
|
||||
document.getElementById("password-add").value = password;
|
||||
} else if (type == "edit") {
|
||||
document.getElementById("password-edit-"+id.toString()).value = password;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('.authMethod').on('change', function() {
|
||||
var $form = $(this).closest('.authForm');
|
||||
if ($(this).val() === 'local') {
|
||||
$form.find('.passwordGroup').show();
|
||||
} else {
|
||||
$form.find('.passwordGroup').hide();
|
||||
}
|
||||
});
|
||||
$('.authMethod').trigger('change');
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<script src="../js/bulk_actions.js"></script>
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/contact/contact_add.php";
|
||||
require_once "modals/contact/contact_export.php";
|
||||
if ($client_url) {
|
||||
require_once "modals/contact/contact_invite.php";
|
||||
//require_once "modals/contact/contact_invite.php";
|
||||
require_once "modals/contact/contact_import.php";
|
||||
}
|
||||
require_once "../includes/footer.php";
|
||||
@@ -106,7 +106,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<div class="card-tools">
|
||||
<?php if (lookupUserPermission("module_credential") >= 2) { ?>
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addCredentialModal" <?php if (!isset($_COOKIE['user_encryption_session_key'])) { echo "disabled"; } ?>>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/credential/credential_add.php?<?= $client_url ?>" <?php if (!isset($_COOKIE['user_encryption_session_key'])) { echo "disabled"; } ?>>
|
||||
<i class="fas fa-plus mr-2"></i>New Credential
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
@@ -241,7 +241,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<i class="fas fa-fw fa-trash mr-2"></i>Delete
|
||||
</button>
|
||||
<?php } else { ?>
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkAssignTagsModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/credential/credential_bulk_assign_tags.php"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-tags mr-2"></i>Assign Tags
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
@@ -519,10 +521,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<?php require_once "modals/credential/credential_bulk_assign_tags.php"; ?>
|
||||
</form>
|
||||
<?php require_once "../includes/filter_footer.php";
|
||||
?>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -534,7 +534,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
|
||||
<?php
|
||||
|
||||
require_once "modals/credential/credential_add.php";
|
||||
require_once "modals/credential/credential_export.php";
|
||||
if ($client_url) {
|
||||
require_once "modals/credential/credential_import.php";
|
||||
45
agent/custom/includes/custom_side_nav.php
Normal file
45
agent/custom/includes/custom_side_nav.php
Normal file
@@ -0,0 +1,45 @@
|
||||
<!-- Main Sidebar Container -->
|
||||
<aside class="main-sidebar sidebar-dark-primary d-print-none">
|
||||
|
||||
<a class="pb-1 mt-1 brand-link" href="../<?php echo $config_start_page ?>">
|
||||
<p class="h5"><i class="nav-icon fas fa-arrow-left ml-3 mr-2"></i>
|
||||
<span class="brand-text ">Back | <strong>Custom</strong>
|
||||
</p>
|
||||
</a>
|
||||
|
||||
<!-- Sidebar -->
|
||||
<div class="sidebar">
|
||||
|
||||
<!-- Sidebar Menu -->
|
||||
<nav>
|
||||
|
||||
<ul class="nav nav-pills nav-sidebar flex-column mt-2" data-widget="treeview" data-accordion="false">
|
||||
|
||||
<li class="nav-header">CUSTOM HEADER</li>
|
||||
|
||||
<li class="nav-item">
|
||||
<a href="index.php" class="nav-link <?php if (basename($_SERVER["PHP_SELF"]) == "index.php") { echo "active"; } ?>">
|
||||
<i class="far fa-circle nav-icon"></i>
|
||||
<p>custom</p>
|
||||
</a>
|
||||
</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</nav>
|
||||
<!-- /.sidebar-menu -->
|
||||
|
||||
<div class="sidebar-custom mb-3">
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<!-- /.sidebar -->
|
||||
</aside>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
13
agent/custom/includes/inc_all_custom.php
Normal file
13
agent/custom/includes/inc_all_custom.php
Normal file
@@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
require_once "../../config.php";
|
||||
require_once "../../functions.php";
|
||||
require_once "../../includes/check_login.php";
|
||||
require_once "../../includes/page_title.php";
|
||||
require_once "../../includes/header.php";
|
||||
require_once "../../includes/top_nav.php";
|
||||
require_once "includes/custom_side_nav.php";
|
||||
require_once "../../includes/inc_wrapper.php";
|
||||
require_once "../../includes/inc_alert_feedback.php";
|
||||
require_once "../../includes/filter_header.php";
|
||||
|
||||
72
agent/custom/index.php
Normal file
72
agent/custom/index.php
Normal file
@@ -0,0 +1,72 @@
|
||||
<?php require_once "includes/inc_all_custom.php"; ?>
|
||||
|
||||
<!-- Breadcrumbs-->
|
||||
<ol class="breadcrumb">
|
||||
<li class="breadcrumb-item">
|
||||
<a href="index.html">Dashboard</a>
|
||||
</li>
|
||||
<li class="breadcrumb-item active">Blank Page</li>
|
||||
</ol>
|
||||
|
||||
<!-- Page Content -->
|
||||
<h1>Blank Page</h1>
|
||||
<hr>
|
||||
<p>This is a great starting point for new custom pages.</p>
|
||||
<h1><?php echo $session_user_role; ?></h1>
|
||||
<?php validateAdminRole(); ?>
|
||||
|
||||
<?php
|
||||
|
||||
$start_date = date('Y') . "-10-10";
|
||||
|
||||
echo "<H1>$start_date</H1>";
|
||||
|
||||
echo "<H2>User Agent</H2>";
|
||||
echo getUserAgent();
|
||||
|
||||
|
||||
?>
|
||||
<br>
|
||||
|
||||
<input type="tel" name="phone" id="phone">
|
||||
|
||||
<div class="form-group">
|
||||
<label>Minimal</label>
|
||||
<select class="form-control select2 select2-hidden-accessible" style="width: 100%;" data-select2-id="1" tabindex="-1" aria-hidden="true">
|
||||
<option selected="selected" data-select2-id="3">Alabama</option>
|
||||
<option data-select2-id="35">Alaska</option>
|
||||
<option data-select2-id="36">California</option>
|
||||
<option data-select2-id="37">Delaware</option>
|
||||
<option data-select2-id="38">Tennessee</option>
|
||||
<option data-select2-id="39">Texas</option>
|
||||
<option data-select2-id="40">Washington</option>
|
||||
</select><span class="select2 select2-container select2-container--default select2-container--below" dir="ltr" data-select2-id="2" style="width: 100%;"><span class="selection"><span class="select2-selection select2-selection--single" role="combobox" aria-haspopup="true" aria-expanded="false" tabindex="0" aria-disabled="false" aria-labelledby="select2-nbex-container"><span class="select2-selection__rendered" id="select2-nbex-container" role="textbox" aria-readonly="true" title="Alabama">Alabama</span><span class="select2-selection__arrow" role="presentation"><b role="presentation"></b></span></span></span><span class="dropdown-wrapper" aria-hidden="true"></span></span>
|
||||
</div>
|
||||
|
||||
<dl>
|
||||
<dt>Requester</dt>
|
||||
<dd>Sam Adams</dd>
|
||||
|
||||
<dt>Created</dt>
|
||||
<dd><time datetime="2024-04-11T17:52:30+00:00" title="2024-04-11 13:52" data-datetime="calendar">Today at 13:52</time></dd>
|
||||
|
||||
<dt>Last activity</dt>
|
||||
<dd><time datetime="2024-04-11T18:08:55+00:00" title="2024-04-11 14:08" data-datetime="calendar">Today at 14:08</time></dd>
|
||||
</dl>
|
||||
|
||||
<?php echo randomString(100); ?>
|
||||
<br>
|
||||
<textarea class="tinymceTest"></textarea>
|
||||
|
||||
<textarea class="tinymce"></textarea>
|
||||
|
||||
<textarea class="tinymceTicket"></textarea>
|
||||
<?php
|
||||
// show the current Date and Time
|
||||
$date_time = date('Y-m-d H:i:s');
|
||||
echo "Current Date and Time: <strong>$date_time</strong>";
|
||||
?>
|
||||
|
||||
<script>toastr.success('Have Fun Wozz!!')</script>
|
||||
|
||||
<?php require_once "../../includes/footer.php";
|
||||
46
agent/custom/post.php
Normal file
46
agent/custom/post.php
Normal file
@@ -0,0 +1,46 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* ITFlow - User 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
|
||||
|
||||
// Load all module POST logic
|
||||
// Loads everything in post/user/
|
||||
// Eventually, it would be nice to only specifically load what we need like we do for admins
|
||||
|
||||
foreach (glob("post/*.php") as $user_module) {
|
||||
if (!preg_match('/_model\.php$/', basename($user_module))) {
|
||||
require_once $user_module;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// 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";
|
||||
|
||||
@@ -209,7 +209,7 @@ if ($user_config_dashboard_financial_enable == 1) {
|
||||
|
||||
<div class="col-lg-4 col-md-6 col-sm-12">
|
||||
<!-- small box -->
|
||||
<a class="small-box bg-success" href="report_profit_loss.php">
|
||||
<a class="small-box bg-success" href="reports/profit_loss.php">
|
||||
<div class="inner">
|
||||
<h3><?php echo numfmt_format_currency($currency_format, $profit, "$session_company_currency"); ?></h3>
|
||||
<p>Profit</p>
|
||||
@@ -223,7 +223,7 @@ if ($user_config_dashboard_financial_enable == 1) {
|
||||
|
||||
<div class="col-lg-6 col-md-6 col-sm-12">
|
||||
<!-- small box -->
|
||||
<a class="small-box bg-info" href="report_recurring_by_client.php">
|
||||
<a class="small-box bg-info" href="reports/recurring_by_client.php">
|
||||
<div class="inner">
|
||||
<h3><?php echo numfmt_format_currency($currency_format, $recurring_monthly_total, "$session_company_currency"); ?></h3>
|
||||
<p>Monthly Recurring Income</p>
|
||||
@@ -252,7 +252,7 @@ if ($user_config_dashboard_financial_enable == 1) {
|
||||
<?php if ($config_module_enable_ticketing && $config_module_enable_accounting) { ?>
|
||||
<div class="col-lg-2 col-md-6 col-sm-12">
|
||||
<!-- small box -->
|
||||
<a class="small-box bg-secondary" href="report_tickets_unbilled.php">
|
||||
<a class="small-box bg-secondary" href="reports/tickets_unbilled.php">
|
||||
<div class="inner">
|
||||
<h3><?php echo $unbilled_tickets; ?></h3>
|
||||
<p>Unbilled Ticket<?php if ($unbilled_tickets > 1 || $unbilled_tickets == 0) { echo "s"; } ?></p>
|
||||
@@ -338,7 +338,7 @@ if ($user_config_dashboard_financial_enable == 1) {
|
||||
<div class="card-header">
|
||||
<h3 class="card-title"><i class="fas fa-fw fa-chart-area mr-2"></i>Cash Flow</h3>
|
||||
<div class="card-tools">
|
||||
<a href="report_income_summary.php" class="btn btn-tool">
|
||||
<a href="reports/income_summary.php" class="btn btn-tool">
|
||||
<i class="fas fa-eye"></i>
|
||||
</a>
|
||||
<button type="button" class="btn btn-tool" data-card-widget="remove">
|
||||
@@ -660,7 +660,7 @@ if ($user_config_dashboard_technical_enable == 1) {
|
||||
<a class="small-box bg-warning" href="domains.php?sort=domain_expire&order=ASC">
|
||||
<div class="inner">
|
||||
<h3><?php echo $expiring_domains; ?></h3>
|
||||
<p>Expiring Domains</p>
|
||||
<p>Expiring Domains <small>30 Day</small></p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="fa fa-globe"></i>
|
||||
@@ -673,7 +673,7 @@ if ($user_config_dashboard_technical_enable == 1) {
|
||||
<a class="small-box bg-primary" href="certificates.php?sort=certificate_expire&order=ASC">
|
||||
<div class="inner">
|
||||
<h3><?php echo $expiring_certificates; ?></h3>
|
||||
<p>Expiring Certificates</p>
|
||||
<p>Expiring Certificates<small>30 Day</small></p>
|
||||
</div>
|
||||
<div class="icon">
|
||||
<i class="fa fa-lock"></i>
|
||||
@@ -729,13 +729,22 @@ if ($user_config_dashboard_technical_enable == 1) {
|
||||
$client_name = nullable_htmlentities($row['client_name']);
|
||||
$contact_id = intval($row['ticket_contact_id']);
|
||||
$contact_name = nullable_htmlentities($row['contact_name']);
|
||||
if ($client_id) {
|
||||
$has_client = "&client_id=$client_id";
|
||||
} else {
|
||||
$has_client = "";
|
||||
}
|
||||
|
||||
$ticket_priority_color = $ticket_priority == "High" ? "danger" : ($ticket_priority == "Medium" ? "warning" : "info");
|
||||
$contact_display = empty($contact_name) ? "-" : "<a href='contact_details.php?client_id=$client_id&contact_id=$contact_id'>$contact_name</a>";
|
||||
?>
|
||||
<tr class="<?php echo empty($ticket_updated_at) ? 'text-bold' : ''; ?>">
|
||||
<td><a class="text-dark" href="ticket.php?ticket_id=<?php echo $ticket_id; ?>"><?php echo "$ticket_prefix$ticket_number"; ?></a></td>
|
||||
<td><a href="ticket.php?ticket_id=<?php echo $ticket_id; ?>"><?php echo $ticket_subject; ?></a></td>
|
||||
<td>
|
||||
<a class="text-dark"
|
||||
href="ticket.php?ticket_id=<?= "$ticket_id$has_client" ?>"><?= "$ticket_prefix$ticket_number" ?>
|
||||
</a>
|
||||
</td>
|
||||
<td><a href="ticket.php?ticket_id=<?= "$ticket_id$has_client" ?>"><?= $ticket_subject ?></a></td>
|
||||
<td><a href="tickets.php?client_id=<?php echo $client_id; ?>"><strong><?php echo $client_name; ?></strong></a></td>
|
||||
<td><?php echo $contact_display; ?></td>
|
||||
<td><span class='p-2 badge badge-pill badge-<?php echo $ticket_priority_color; ?>'><?php echo $ticket_priority; ?></span></td>
|
||||
@@ -20,9 +20,16 @@ $folder_location = 0;
|
||||
$sql_document = mysqli_query($mysqli, "SELECT * FROM documents
|
||||
LEFT JOIN folders ON document_folder_id = folder_id
|
||||
LEFT JOIN users ON document_created_by = user_id
|
||||
WHERE document_client_id = $client_id AND document_id = $document_id"
|
||||
WHERE document_client_id = $client_id AND document_id = $document_id
|
||||
LIMIT 1"
|
||||
);
|
||||
|
||||
if (mysqli_num_rows($sql_document) == 0) {
|
||||
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='javascript:history.back()'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
|
||||
require_once "../includes/footer.php";
|
||||
exit();
|
||||
}
|
||||
|
||||
$row = mysqli_fetch_array($sql_document);
|
||||
|
||||
$folder_name = nullable_htmlentities($row['folder_name']);
|
||||
@@ -97,18 +104,31 @@ $page_title = $row['document_name'];
|
||||
<div class="col-md-9">
|
||||
<div class="card">
|
||||
<div class="card-header bg-dark">
|
||||
|
||||
<h3><?php echo $document_name; ?> <?php if (!empty($document_description)) { ?><span class="h6 text-muted">(<?php echo $document_description; ?>)</span><?php } ?></h3>
|
||||
|
||||
<div class="row">
|
||||
<div class="col"><strong>Date:</strong> <?php echo date('Y-m-d', strtotime($document_created_at)); ?></div>
|
||||
<?php if(!empty($document_created_by_name)){ ?>
|
||||
<div class="col"><strong>Prepared By:</strong> <?php echo $document_created_by_name; ?></div>
|
||||
<?php } ?>
|
||||
<div class="col">
|
||||
<div class="h4 mb-0"><?= $document_name ?></div>
|
||||
<?php if ($document_description) { ?>
|
||||
<div class="text-light"><?= $document_description ?></div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="col">
|
||||
<div class="float-right">
|
||||
<div>
|
||||
Date:
|
||||
<strong><?= date('Y-m-d', strtotime($document_created_at)); ?></strong>
|
||||
</div>
|
||||
<?php if($document_created_by_name) { ?>
|
||||
<div>
|
||||
Prepared By:
|
||||
<strong><?= $document_created_by_name ?></strong>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body prettyContent">
|
||||
<?php echo $document_content; ?>
|
||||
<?= $document_content ?>
|
||||
<hr>
|
||||
<h4>Documentation Revision History</h4>
|
||||
|
||||
@@ -144,11 +164,11 @@ $page_title = $row['document_name'];
|
||||
|
||||
?>
|
||||
<tr>
|
||||
<td><?php echo $document_version_count; ?></td>
|
||||
<td><?php echo $document_version_created_date; ?></td>
|
||||
<td><?php echo $document_version_name; ?></td>
|
||||
<td><?php echo $document_version_description_display; ?></td>
|
||||
<td><?php echo $document_version_author; ?></td>
|
||||
<td><?= $document_version_count ?></td>
|
||||
<td><?= $document_version_created_date ?></td>
|
||||
<td><?= $document_version_name ?></td>
|
||||
<td><?= $document_version_description_display ?></td>
|
||||
<td><?= $document_version_author ?></td>
|
||||
</tr>
|
||||
<?php
|
||||
$document_version_count++; // Increment the counter
|
||||
@@ -163,17 +183,19 @@ $page_title = $row['document_name'];
|
||||
<div class="col-md-3 d-print-none">
|
||||
<div class="row">
|
||||
<div class="col-12 mb-3">
|
||||
<button type="button" class="btn btn-primary ajax-modal mr-2"
|
||||
<button type="button" class="btn btn-primary ajax-modal mr-1"
|
||||
data-modal-size="lg"
|
||||
data-modal-url="modals/document/document_edit.php?id=<?= $document_id ?>">
|
||||
<i class="fas fa-fw fa-edit"></i>
|
||||
<i class="fas fa-fw fa-edit" title="Edit"></i>
|
||||
</button>
|
||||
<button type="button" class="btn btn-secondary mr-2" data-toggle="modal" data-target="#shareModal"
|
||||
onclick="populateShareModal(<?php echo "$client_id, 'Document', $document_id"; ?>)">
|
||||
<i class="fas fa-fw fa-share"></i>
|
||||
<button type="button" class="btn btn-secondary mr-1" data-toggle="modal" data-target="#shareModal"
|
||||
onclick="populateShareModal(<?= "$client_id, 'Document', $document_id"; ?>)">
|
||||
<i class="fas fa-fw fa-share" title="Share"></i>
|
||||
</button>
|
||||
<a class="btn btn-success mr-2" href="post.php?export_document=<?php echo $document_id; ?>"><i class='fas fa-fw fa-file-pdf'></i></a>
|
||||
<button type="button" class="btn btn-secondary" onclick="window.print();"><i class="fas fa-fw fa-print"></i></button>
|
||||
<a class="btn btn-success mr-1" href="post.php?export_document=<?= $document_id ?>"><i class='fas fa-fw fa-file-pdf' title="PDF Export"></i></a>
|
||||
<button type="button" class="btn btn-secondary mr-4" onclick="window.print();"><i class="fas fa-fw fa-print" title="Print"></i></button>
|
||||
<a class="btn btn-warning mr-1 confirm-link" href="post.php?archive_document=<?= $document_id ?>" title="Archive"><i class='fas fa-fw fa-archive'></i></a>
|
||||
<a class="btn btn-danger confirm-link" href="post.php?delete_document=<?= $document_id ?>&from=document_details" title="Delete"><i class='fas fa-fw fa-trash-alt'></i></a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card card-body bg-light">
|
||||
@@ -23,9 +23,6 @@ if (!empty($q)) {
|
||||
$query_snippet = ""; // empty
|
||||
}
|
||||
|
||||
//Rebuild URL
|
||||
$url_query_strings_sort = http_build_query($get_copy);
|
||||
|
||||
// Folder ID
|
||||
$get_folder_id = 0;
|
||||
if (!empty($_GET['folder_id'])) {
|
||||
@@ -92,12 +89,12 @@ while ($folder_id > 0) {
|
||||
<div class="card-tools">
|
||||
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addDocumentModal">
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/document/document_add.php?client_id=<?= $client_id ?>&folder_id=<?= $get_folder_id ?>" data-modal-size="lg">
|
||||
<i class="fas fa-plus mr-2"></i>New Document
|
||||
</button>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#createFolderModal">
|
||||
<a class="dropdown-item text-dark ajax-modal" href="#" data-modal-url="modals/folder/folder_add.php?client_id=<?= $client_id ?>&folder_location=0¤t_folder_id=<?= $get_folder_id ?>">
|
||||
<i class="fa fa-fw fa-folder-plus mr-2"></i>New Folder
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
@@ -130,7 +127,9 @@ while ($folder_id > 0) {
|
||||
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
|
||||
</button>
|
||||
<div class="dropdown-menu">
|
||||
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#bulkMoveDocumentModal">
|
||||
<a class="dropdown-item ajax-modal" href="#"
|
||||
data-modal-url="modals/document/document_bulk_move.php?client_id=<?= $client_id ?>"
|
||||
data-bulk="true">
|
||||
<i class="fas fa-fw fa-exchange-alt mr-2"></i>Move
|
||||
</a>
|
||||
<div class="dropdown-divider"></div>
|
||||
@@ -276,7 +275,6 @@ while ($folder_id > 0) {
|
||||
display_folders(0, $client_id);
|
||||
?>
|
||||
</ul>
|
||||
<?php require_once "modals/folder/folder_add.php"; ?>
|
||||
</div>
|
||||
|
||||
<div class="col-md-9">
|
||||
@@ -466,10 +464,8 @@ while ($folder_id > 0) {
|
||||
</table>
|
||||
<br>
|
||||
</div>
|
||||
<?php require_once "modals/document/document_bulk_move.php"; ?>
|
||||
</form>
|
||||
<?php require_once "../includes/filter_footer.php";
|
||||
?>
|
||||
<?php require_once "../includes/filter_footer.php"; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -479,6 +475,5 @@ while ($folder_id > 0) {
|
||||
|
||||
<?php
|
||||
require_once "modals/share_modal.php";
|
||||
require_once "modals/document/document_add.php";
|
||||
require_once "modals/document/document_add_from_template.php";
|
||||
require_once "../includes/footer.php";
|
||||
@@ -76,7 +76,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<h3 class="card-title mt-2"><i class="fa fa-fw fa-globe mr-2"></i>Domains</h3>
|
||||
<div class="card-tools">
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addDomainModal"><i class="fas fa-plus mr-2"></i>New Domain</button>
|
||||
<button type="button" class="btn btn-primary ajax-modal" data-modal-url="modals/domain/domain_add.php?<?= $client_url ?>"><i class="fas fa-plus mr-2"></i>New Domain</button>
|
||||
<?php if ($num_rows[0] > 0) { ?>
|
||||
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
|
||||
<div class="dropdown-menu">
|
||||
@@ -307,8 +307,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
<td><?php echo $domain_dnshost_name_display; ?></td>
|
||||
<td><?php echo $domain_mailhost_name_display; ?></td>
|
||||
<td>
|
||||
<div><?php echo $domain_expire; ?></div>
|
||||
<div><small><?php echo $domain_expire_ago; ?></small></div>
|
||||
<div><?php echo $domain_expire ?: '-'; ?></div>
|
||||
<?php if (!empty($domain_expire)) { ?>
|
||||
<div><small><?php echo $domain_expire_ago; ?></small></div>
|
||||
<?php } ?>
|
||||
</td>
|
||||
<?php if (!$client_url) { ?>
|
||||
<td><a href="domains.php?client_id=<?php echo $client_id; ?>"><?php echo $client_name; ?></a></td>
|
||||
@@ -361,7 +363,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
|
||||
</div>
|
||||
|
||||
<?php
|
||||
require_once "modals/domain/domain_add.php";
|
||||
require_once "modals/domain/domain_export.php";
|
||||
?>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user