373 Commits

Author SHA1 Message Date
Johnny
ed8a576ac3 Merge pull request #1223 from itflow-org/develop
25.06 Release
2025-06-20 15:34:32 -04:00
johnnyq
5c6a7acb7d Fix Updated at date in Documents 2025-06-20 15:25:42 -04:00
johnnyq
850db54a3b Bump ITFlow version to 25.6 and updated changelog 2025-06-20 15:10:46 -04:00
johnnyq
985593b7c2 Add Confirm Modal to Accept Decline Quote 2025-06-19 16:39:22 -04:00
johnnyq
857b5d1bfd Remove redundant php open tag 2025-06-19 00:27:33 -04:00
johnnyq
498e86aa7a Refactor Restore ITFlow Backup code in setup to utilize Sys Temp Directory 2025-06-19 00:26:23 -04:00
johnnyq
79d0fd28b0 Fix Backup function 2025-06-19 00:17:52 -04:00
johnnyq
426ca90515 Add Function to cleanup temp backup files if backup times out or error out 2025-06-19 00:13:56 -04:00
johnnyq
e7328f1be5 Use tmp directory to zip and backup itflow instance 2025-06-19 00:06:54 -04:00
johnnyq
baccc8051e Fix Extra spacing before Contact Name in client listing 2025-06-18 23:13:06 -04:00
johnnyq
f1c7690270 Also add contact_id to the compact ticket listing 2025-06-18 22:34:27 -04:00
johnnyq
d700d1530b Add missing contact_id in ticket listing 2025-06-18 22:32:55 -04:00
johnnyq
b60f44eede Allow the Contact to be clickable in ticket compact listing too 2025-06-18 18:06:59 -04:00
johnnyq
54ab788e93 Allow the Contact to be clickable in ticket listing and direct to the client contact details page 2025-06-18 18:05:28 -04:00
johnnyq
ac2dd04959 Moved Has Base Vendor Template Icon to the the end of the Vendors Table listing 2025-06-18 16:56:40 -04:00
johnnyq
9a449c35ac Fix No content in Edit Recurring Invoice Note Modal 2025-06-18 16:18:01 -04:00
johnnyq
2ff5d2f87c Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-06-18 15:32:38 -04:00
johnnyq
8f704dade8 Recurring Payments now make the payment on the invoice Due Date instead of when the recurring invoice is generated 2025-06-18 15:32:22 -04:00
wrongecho
3b3e323ce5 Assets - Import CSV now takes purchase date too (MUST be in format YYYY-MM-DD, Excel is annoying and will silently reformat this at random) 2025-06-18 14:48:13 +01:00
wrongecho
43ec144bf0 Fix more debug errors 2025-06-18 14:47:21 +01:00
wrongecho
d5f94819d0 Fix 'Passing null to parameter' debug message 2025-06-18 14:11:18 +01:00
johnnyq
98aa7e4993 Remove url_query_strings_sort var as this functionality has been moved to the filter header that all listing pages share 2025-06-18 01:42:21 -04:00
johnnyq
7c61911dba Added Document Template Delete function 2025-06-18 00:55:57 -04:00
johnnyq
2bb107a5d7 Add Functionality to mark all tasks as complete or incomplete in a ticket 2025-06-18 00:48:18 -04:00
johnnyq
0c4a2aedb7 Show Puzzle Piece Icon if a Vendor has a base vendor template assigned to it 2025-06-18 00:16:19 -04:00
johnnyq
e7e7272002 Migrated Vendor Templates to its own table, lots of code modifications here 2025-06-17 22:44:54 -04:00
johnnyq
f672991089 Remove Document Template field from a few more files 2025-06-17 19:09:43 -04:00
johnnyq
473fa2671d Migrate Document templates to its own table 2025-06-17 19:00:56 -04:00
johnnyq
85e1515080 Move Document Versions to a seperate table much more efficient and allow to reference same document using a link Note this update will delete previous document versions 2025-06-17 17:58:20 -04:00
johnnyq
84437a2732 Bump TCPDF from 6.9.4 to 6.10.0 and TinyMCE from 7.9.0 to 7.9.1 2025-06-17 14:44:06 -04:00
johnnyq
71911f418f Remove Unessesary Code 2025-06-17 14:32:35 -04:00
johnnyq
2741f78bd8 Fully Migrated Quote and Invoice to use TCPDF and elimiated PDFMake 2025-06-17 14:22:57 -04:00
johnnyq
012e54161a Converted PDF Invoice from PDFMake to TCPDF 2025-06-16 18:40:05 -04:00
johnnyq
409084c499 Update UI on Quote, Recurring Invoice and Guest views to match new optimized Invoice UI Layout 2025-06-16 15:49:38 -04:00
johnnyq
27595b2c4a UI Add Ticket to Invoice - Removed Warning about Draf Invoices increase modal size to large and move input to a row to reduce uneessary veritical space being occupied. 2025-06-16 13:13:48 -04:00
johnnyq
62b6535625 UI Invoice make footer text secondary color 2025-06-15 15:42:13 -04:00
johnnyq
e593f438b3 UI Work on Client Overview Increase Quick Notes and Recent Activities width and added contact photos or initials to important contacts 2025-06-15 15:36:54 -04:00
johnnyq
44d46a2cc5 UI Overhaul to invoice Details Page 2025-06-15 15:06:53 -04:00
johnnyq
66e30dd1a8 Added Badge Counts in Client Overview Section 2025-06-13 16:05:49 -04:00
johnnyq
4c74351d21 Added Company Tax ID Field and Option to Show Tax ID on Invoices 2025-06-13 15:51:09 -04:00
johnnyq
5d2b14259c Added Ticket Due Date basic functionality to tickets 2025-06-12 17:13:17 -04:00
johnnyq
878d5444e1 Use Gray Accent color when in client view and use configured theme for Global view, this will help differentiate the view that you are in 2025-06-12 15:00:47 -04:00
johnnyq
ec24ec60c6 Disable Ticket Auto Timer by default 2025-06-12 13:49:11 -04:00
johnnyq
9c096d1f65 Add Setting option to enable or disable ticket autotimer 2025-06-12 13:44:21 -04:00
johnnyq
dba3e895da UI/UX update in ticket details switch to full card stacks with edit icons for the stackable reference items on the right like asset watchers contact etc 2025-06-11 22:28:38 -04:00
johnnyq
07726322df Project Details: Add Bulk Actions to tickets and allow tickets to be sorted 2025-06-11 20:47:27 -04:00
johnnyq
bef18c0d72 Do not Resolved Tickets in Bulk that have Open tasks, display warning and count of ticket not resolved because of open tasks 2025-06-11 18:48:23 -04:00
johnnyq
7c3332570a Add Ticket Category UI for Recurring Tickets 2025-06-11 18:11:08 -04:00
johnnyq
a3d4a52188 Add Mark Sent when invoice is draft to Action Dropdown for invoice listings 2025-06-11 17:29:38 -04:00
johnnyq
5530e89f41 Add one more Non-Billable Check in invoices 2025-06-11 17:18:28 -04:00
johnnyq
a3554b3dfd Add one more Non-Billable Check in invoices 2025-06-11 17:16:03 -04:00
johnnyq
674da36cd1 Do Not calculate Non-Billable Invoices towards a clients balance Convert Add Payment Modal to AJAX and add it as an option from the invoice listing page 2025-06-11 17:12:37 -04:00
johnnyq
18ce12f60d Add Option if visiting a deleted invoice / recurring to return to the listing page and added delete to invoice details page 2025-06-11 15:57:52 -04:00
johnnyq
a462ab36f8 Ticket add / edit / builk sort categories alphabeticaly 2025-06-11 14:56:23 -04:00
Johnny
8aa41edc3e Merge pull request #1222 from itflow-org/functions-ip-addr-leftmost
Update how functions.php gets the remote IP address for logging
2025-06-11 14:01:12 -04:00
wrongecho
4e0252553a rm extra ; 2025-06-11 08:18:32 +01:00
johnnyq
8745d09890 Add sanitize the remaining uris that allow uri type:// refactored service details 2025-06-10 12:11:58 -04:00
wrongecho
ac3a02baea Disallow turning on login key without a secret 2025-06-10 09:19:29 +01:00
wrongecho
f2bbc170da Update how functions.php gets the remote IP address for logging
- Builds on PR #1210 to always get the leftmost IP address
- Cloudflare (HTTP_CF_CONNECTING_IP) must now be explicitly defined, otherwise people could add the HTTP_CF_CONNECTING_IP header to a non-Cloudflare host and spoof IPs
- Tidy up the if/else logic a little
2025-06-10 09:03:00 +01:00
johnnyq
d79a17adb0 Added sanitize_url function to strip out unsupported URI Schemas schema:// if not on the allow list it will show unsupport://URL 2025-06-09 20:28:10 -04:00
johnnyq
680dbb04ce Fix UI Regression with Indenting Columns in Tickets listing when Open and Closed tickets are filters 2025-06-09 13:30:13 -04:00
johnnyq
6c8403fa09 Move MFA Modal out of the Password Reset Form 2025-06-09 12:52:07 -04:00
johnnyq
fec8eaef70 Remove xml from the allowed upload list, if you must zip it up 2025-06-07 01:28:13 -04:00
johnnyq
5f007029b4 Fix Category 2025-06-07 00:58:56 -04:00
johnnyq
4e76ceaa0f Simplify Category filter logic in tickets catrgory is an int not a string duh 2025-06-07 00:46:11 -04:00
johnnyq
08e467baa9 Encode Page Title 2025-06-06 21:48:24 -04:00
Johnny
f78a2250f1 Merge pull request #1221 from itflow-org/develop
Develop to Master for 25.05.1 Release
2025-06-02 14:39:50 -04:00
johnnyq
84e8a459c8 update Changelog 2025-06-02 14:24:52 -04:00
johnnyq
b777f80249 Increment Minor Version and update Changelog 2025-06-02 14:19:04 -04:00
johnnyq
73da203dbb Added Cards for Account Balance, Recurring Monthly for Billing Contacts and Domains Expiring for Technical Contacts to Client Portal 2025-05-31 17:47:08 -04:00
johnnyq
55a31865d0 Updated Client Overview Entities to not show Archived client's Entities even though the entity may not be archived, also added Archive Searching to network and certificates also added unarchive capabilities to them as well 2025-05-30 16:15:12 -04:00
wrongecho
350697869b Fix invoice top banner not showing 2025-05-30 17:31:54 +01:00
Johnny
939b07422d Merge pull request #1220 from itflow-org/develop
Merge Develop into Master for 25.05 Release
2025-05-29 14:30:25 -04:00
wrongecho
88369d480a Reword changelog 2025-05-29 18:42:25 +01:00
wrongecho
cf083e94e6 Fix 2025-05-29 18:40:51 +01:00
wrongecho
11e8f5acfc Bump app version 2025-05-29 18:37:39 +01:00
wrongecho
77b3a89eb2 Reword changelog 2025-05-29 18:37:16 +01:00
johnnyq
f572f4265a Updated Changelog 2025-05-29 13:31:40 -04:00
johnnyq
0b66c8e1be Better naming of Indetity Providers instead of Integrations to make way for more Indentity Provider like Google and custom SSO for the future 2025-05-29 13:29:27 -04:00
johnnyq
a8328a3f56 Add more text-nowrap to more table headers 2025-05-29 11:45:45 -04:00
johnnyq
8b42b17121 Added more text no wrap to table headers 2025-05-29 00:18:37 -04:00
johnnyq
db418ce662 Mobile UI/UX - Hide long New Button names and use plus icon only in mobile view, proper form group spacing in mobile as well 2025-05-28 23:39:44 -04:00
johnnyq
96fe566e08 Add location country even when client id uri is not set 2025-05-28 22:03:55 -04:00
johnnyq
a00f26d8a4 UI/UX Draggables now switch to a hand on hover, updated the UI in invoice quote and reccuring invoice so buttons do not wrap and are grouped. Seperated the Dragable button using a button link, did the same for tasks in tickets 2025-05-28 21:22:21 -04:00
johnnyq
eeef63d1c3 Updated Changelog 2025-05-28 19:36:52 -04:00
johnnyq
0b88ea85ae Display Country in Invoices, Quotes, Recurring Invoices, Clients, locations, client top head, and allow searching via country in Locations and Clients 2025-05-28 19:27:11 -04:00
johnnyq
c564118156 Fix Dupe GET VARS in tickets Removed extra Rebuild URL as this has been done in the filter header for some time now 2025-05-28 18:34:50 -04:00
johnnyq
01a7dc2068 Allow both Client and Contact to be sorted in same column in ticket list 2025-05-28 18:29:02 -04:00
johnnyq
bb44ecec3f Trips UI/UX - Move Client at the end column for consistency 2025-05-28 18:13:44 -04:00
johnnyq
b7b24d7de6 UI/UX Expenses - Combined Category and Description Column with secondary text seperation and expanded Truncation of Description from 50 chars to 60 chars 2025-05-28 18:08:08 -04:00
johnnyq
dcca93e34f Only show 8 notifications at a time instead of 10 2025-05-28 17:43:03 -04:00
johnnyq
4124188505 Ticket UI/UX allow the ticket toolbar to be a little more Mobile friendly 2025-05-28 17:39:32 -04:00
johnnyq
eb5d59623b Don't show Checkbox columns when ticket is closed, compact ticket list now matches round pills for status and priority 2025-05-28 17:02:50 -04:00
Marcus Hill
8631c06731 Stripe - Remove the locally stored payment identifiers (expiry/last 4) from the database when the client removes the stripe pm 2025-05-27 19:29:03 +01:00
Marcus Hill
40eb40fd86 Cron mail queue - fix $config_smtp_encryption being set to None in IF statement 2025-05-27 14:46:50 +01:00
Marcus Hill
c486682a0e Cron mail queue - fix app_log_type not being one of available enums 2025-05-27 14:05:09 +01:00
Marcus Hill
336da073f1 Admin mail settings
- Disable the IMAP test button as it doesn't work yet
- Remove word 'successfully' when testing SMTP as we're only adding the message to the queue, it wasn't sent yet
2025-05-27 14:00:25 +01:00
Marcus Hill
d2e187a239 Update security supported versions 2025-05-26 20:34:01 +01:00
johnnyq
f69de29353 Get a more accurate count of Tables rows in Debug using count instead of relying on show table status as this is not accurate all the time. 2025-05-24 13:45:27 -04:00
johnnyq
61de8bc792 Redirect to login when itflow restore completes 2025-05-24 13:30:49 -04:00
johnnyq
d31f19707b DB Dump 2025-05-24 13:23:41 -04:00
johnnyq
811312466f If Restore from Backup is chosen show message must configure database first if DB and config dont exist 2025-05-24 13:09:16 -04:00
johnnyq
5ecfb3e962 Update setup to include welcome as an option and do not hide the side nav items if db is already created. 2025-05-24 12:40:33 -04:00
johnnyq
77be5af4e5 Update setup to include restore option but place it in its own nav section for seperation. Also if DB and config is configured skip and do not show checks or database in the side nav 2025-05-24 12:28:34 -04:00
johnnyq
c512a716d2 Fix extra spacing in modal footer in notifications 2025-05-23 19:09:36 -04:00
johnnyq
14f5630caf Fix Invoice Header Button 2025-05-23 18:34:25 -04:00
johnnyq
8532bdc172 More UI updates to Guest Pay 2025-05-23 18:25:09 -04:00
johnnyq
9d74bf8e19 Use cards in Guest Pay Invoice 2025-05-23 17:45:06 -04:00
johnnyq
f75445b4d0 Limit Stripe Payments to just Credit Cards 2025-05-23 17:18:22 -04:00
johnnyq
e04fa1b696 Add stripe_pm_created_at 2025-05-23 17:13:05 -04:00
johnnyq
e07dfb5f67 db structure 2025-05-23 15:42:47 -04:00
johnnyq
3d1af05fc2 Updated DB to store Payment details 2025-05-23 15:41:52 -04:00
johnnyq
0e38925d74 Update Changelog 2025-05-22 18:00:08 -04:00
johnnyq
c0f3343412 Client Portal Add Recurrung Invoices with option to Enable or Disable Auto Pay per recurring Invoice if Stripe is enabled and Client has a payment method. Also when removing saved auto payment methods delete all recurring payments for that client that are Stripe method also added this to the admin settings 2025-05-22 17:58:51 -04:00
johnnyq
6a368840fa Bump stripe-php from 16.4.0 to 17.2.1 2025-05-22 12:37:35 -04:00
johnnyq
5361391b3b Update changelog with the bumps 2025-05-22 12:24:49 -04:00
johnnyq
b80662bb24 Bump FullCalendar from 6.1.15 to 6.1.17 2025-05-22 12:16:16 -04:00
johnnyq
4c272b6b8d Bump DataTables from 2.2.2 to 2.3.1 2025-05-22 12:08:47 -04:00
johnnyq
96abdef3ad Bump TCPDF from 6.8.2 to 6.9.4 2025-05-22 12:04:48 -04:00
johnnyq
0b04bc79e9 Bump tinyMCE from 7.7.1 to 7.9.0 2025-05-22 11:57:54 -04:00
johnnyq
cefbbdc3a8 Bump phpMailer from 6.9.2 to 6.10.0 2025-05-22 11:46:09 -04:00
johnnyq
83ffe05a99 Update Changelog 2025-05-22 11:38:24 -04:00
johnnyq
b6f73083ef SMTP Option Encryption None now works as intended 2025-05-22 11:37:14 -04:00
johnnyq
693736023e Update changelog 2025-05-21 21:02:55 -04:00
johnnyq
fed87c93ab Migrated contact link models to the new ajax models this fixes the issue of the overlapping var contact_name and improves page load and performance in contact details 2025-05-21 12:18:42 -04:00
johnnyq
f53b77b556 Migrated asset link models to the new ajax models this fixes the issue of the overlapping var asset_name and improves page load and performance in asset details 2025-05-21 11:51:18 -04:00
wrongecho
b858d82b0b Show archived categories properly 2025-05-20 14:51:12 +01:00
wrongecho
ccb2af6d17 Fix category name/type logging when archiving/deleting a category 2025-05-20 14:50:27 +01:00
wrongecho
8d937ac8f5 Fix add asset modal icon not showing 2025-05-20 11:39:35 +01:00
wrongecho
2786fb65ed Don't show archived ticket categories in the tickets.php filter options 2025-05-20 11:39:09 +01:00
wrongecho
025532f579 Fix quote top navbar options not showing following perms work 2025-05-20 11:29:26 +01:00
wrongecho
5bd03be1ad Ticket tasks - set maxlength html attribute 2025-05-14 16:05:43 +01:00
wrongecho
40086f1ce0 Quotes / Invoicing - More role/perms enforcement 2025-05-14 11:07:25 +01:00
wrongecho
be66ad9a4c Quotes / Invoicing
- Ability to manually mark a quote as invoiced (weird css fix for this, we can remove the custom css if we make the parent button just a dropdown, but don't want to introduce extra clicks)
- When converting a quote to an invoice, show the new invoice number in the quote history
- Quotes can now be sent from the main Send dropdown, instead of having to use the send button in the options menu / main quotes.php page
2025-05-14 10:41:32 +01:00
Marcus Hill
0df5c01bb7 Project - Require CSRF token to delete a project 2025-05-11 12:25:13 +01:00
Marcus Hill
b85fa38b67 Project - Show client abbreviation in open ticket link modal 2025-05-11 12:19:34 +01:00
Marcus Hill
546246d7c5 Project - Allow editing client after creation 2025-05-11 12:14:20 +01:00
Marcus Hill
d5536e78f4 Ajax contacts - Enforce client access restrictions when getting client contacts 2025-05-11 12:01:23 +01:00
Marcus Hill
908738b7ca Ajax active clients - enforce client access restrictions (e.g. when changing ticket client) 2025-05-11 11:57:16 +01:00
Marcus Hill
797e02bffa Hide Credentials in side nav if no perms to view 2025-05-11 11:48:47 +01:00
Marcus Hill
d856685782 Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-05-11 11:46:00 +01:00
Marcus Hill
1400983d8c Projects/Tickets
- Hide new project button for users that only have support read access
- Hide new ticket button for users that only have support read access
- Enforce client access restrictions for viewing project details based off project client
- Prevent selecting the 'Select tickets' text when linking ticket
2025-05-11 11:45:47 +01:00
johnnyq
2a43c5d868 Remove DB Check 2025-05-08 16:46:25 -04:00
johnnyq
a67675c649 Remove 500 Records per page option to reduce Resource strain, 100 records per page is max 2025-05-08 16:08:28 -04:00
johnnyq
fc344ef636 add notification paging 2025-05-07 19:23:11 -04:00
johnnyq
2ffb2be083 Update the backup code to be a full backup zip file download of uploads and db dump along with version meta data file. Also allow to restore a single file in setup currently hidden 2025-05-07 15:37:57 -04:00
johnnyq
069772f27d Add Upload uploads.zip file to restore files as well 2025-05-07 14:54:25 -04:00
johnnyq
241ec50802 Add hidden option to restore dumped ITFlow Database during Setup 2025-05-07 14:32:51 -04:00
johnnyq
b943c9cd89 Remove Influencer as a referral 2025-05-06 19:50:51 -04:00
johnnyq
80625f8c3f Remove Unused vars in setup, added jpeg to the allow extension for user avatars 2025-05-06 19:36:31 -04:00
johnnyq
58435d3460 Add Next Button if Database is already configured 2025-05-06 17:18:54 -04:00
johnnyq
7a7ac4a47f Fix Edit Blank Recurring ticket in Asset Details 2025-05-06 13:16:56 -04:00
Marcus Hill
429dfa5ca4 Allow file upload extensions: .bat, .stk 2025-05-04 21:38:11 +01:00
wrongecho
e1f212d30d Start recording ticket source (API, Email, Portal, Agent) 2025-04-28 14:51:38 +01:00
wrongecho
670450bcfb Ticket statuses - Allow ordering from admin settings, this can replace the need to move the Kanban columns 2025-04-23 10:22:33 +01:00
Johnny
83e15e9e4a Merge pull request #1216 from itflow-org/develop
Develop to Master 25.03.6
2025-04-21 17:28:14 -04:00
johnnyq
b309081d75 Allow to search by project reference number 2025-04-21 17:16:35 -04:00
johnnyq
f1a7b35aa6 Update Changelog and App Version fix date to 2025-04-21 17:00:32 -04:00
Marcus Hill
469c5ef06d Update client pdf export
- Fix HTML formatting for the cover div, other div styling is still broken
- Adjust layout of cover info and add MSP logo
- Add software purchase and expiry dates
2025-04-19 16:30:00 +01:00
Marcus Hill
07cbe561bd Add stupidly bigger update warning to update page. Add reminder note to check ITFlow backup (one in every ten page loads) 2025-04-19 15:14:40 +01:00
Johnny
b69a70cfc3 Merge pull request #1213 from itflow-org/develop
Develop to Master - 25.03.5 Release
2025-04-18 19:08:18 -04:00
johnnyq
923001928c Update Changelog and version 2025-04-18 18:08:40 -04:00
johnnyq
75ed461c67 Asset and Contact Links now goto the details page instead of the details modal 2025-04-16 18:51:53 -04:00
johnnyq
691aebce91 Revert Fix 2025-04-13 15:15:18 -04:00
johnnyq
846947ff49 Change the button handlebar class 2025-04-13 15:11:37 -04:00
johnnyq
65e107d154 Totally remove Dragula in Favor of the modern SortableJS library, updated the Kanban 2025-04-13 15:01:52 -04:00
johnnyq
19b809b699 Added SortableJS Library, and updated Invoice, Quote and Recurring to use it. Added Grab Bar Icons next to action buttons. Will now sort in Mobile much more efficiently, update ajax vars for recurring invoice 2025-04-13 13:29:16 -04:00
johnnyq
60fe02bb47 Comment 2025-04-13 11:57:26 -04:00
johnnyq
3e708059c6 Fix not showing File folders instead of Document Folders when creating a document. 2025-04-13 11:55:14 -04:00
johnnyq
424104bb66 Default Date between max date to 9999-12-31 instead of current date for filtered listings, this fixes the issue if you post date an entity it would not show in the listing by default unless you selected a a great to date in the filter 2025-04-12 12:08:30 -04:00
johnnyq
62696b9ebe Fix Mobile Country Code in contact list 2025-04-12 11:58:32 -04:00
Johnny
87403e8c2d Merge pull request #1209 from itflow-org/index-redirect
Redirect the blank index page to the start page
2025-04-12 11:54:05 -04:00
wrongecho
7a5a607ff6 Redirect the blank index page to the start page 2025-04-11 14:53:02 +01:00
wrongecho
a195774726 Update README.md
Add JetBrains to sponsors, as they provide FOSS licenses of PhpStorm to us
2025-04-11 14:31:01 +01:00
johnnyq
8d0da7b55b Fix Entity Linking in Asset and contact details 2025-04-09 14:00:51 -04:00
Johnny
58c315cd09 Merge pull request #1207 from TamirSlo/fix-dashboard-db-update-1-9-7
Fix Dashboard following DB Update 1.9.7
2025-04-08 17:00:40 -04:00
Johnny
dd6c4602db Merge pull request #1194 from ssteeltm/develop
fix: missing kanban ticket settings
2025-04-08 16:59:07 -04:00
Tamir Slobodskoy
d413e0c8ff Fix Copy Trip Modal 2025-04-08 05:27:56 +01:00
Tamir Slobodskoy
b356658635 Fix Dashboard following DB Update 1.9.7 2025-04-08 05:02:46 +01:00
Johnny
d92f0fc49b Merge pull request #1206 from itflow-org/develop
Develop to Master for 25.03.4 Release
2025-04-07 13:31:20 -04:00
johnnyq
f206a28cf7 Update Changelog and App version to 25.03.4 2025-04-07 13:07:03 -04:00
johnnyq
70cb0ac635 Add the ability to remove additional assets from the ticket details screen 2025-04-07 12:58:55 -04:00
johnnyq
a0ece18876 Allow to remove additional assets in a ticket 2025-04-07 11:59:56 -04:00
wrongecho
4a22b03952 Global search - assets
When global search returns an asset, include a hyperlink to the asset details as part of the asset name
2025-04-04 15:12:32 +01:00
wrongecho
5ebf797c90 rm asset_mac - no longer in assets table 2025-04-04 15:08:04 +01:00
wrongecho
a20759f1f2 rm asset_mac - no longer in assets table 2025-04-04 15:07:47 +01:00
wrongecho
c273cab36e Portal - View all ticket bugfix
View all tickets should display the ticket_number rather than the database ID
2025-04-04 14:50:36 +01:00
johnnyq
8306a04eda Add Purchase Reference to Copy Asset 2025-04-03 15:07:56 -04:00
johnnyq
f078203136 Fix Database Export, was not properly exporting utf8, html data and such. Also disable foreign key contraint check in the export then renable it in the end. This fixes the issue with importing the database into phpmyadmin or using the mysql command 2025-04-03 15:01:47 -04:00
johnnyq
15e89c3c4e Fix Bulk Assign ticket to only show ITflow users and not client users 2025-04-01 17:23:44 -04:00
Johnny
595c4f1440 Merge pull request #1205 from itflow-org/develop
Develop to Master for 25.03.3 release
2025-04-01 11:45:41 -04:00
johnnyq
91a523dc23 Update Changelog 2025-04-01 11:40:24 -04:00
johnnyq
8567c97c09 Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-04-01 11:33:16 -04:00
johnnyq
3621e99c61 Update Changelog and app version 2025-04-01 11:33:04 -04:00
Johnny
d99b9cbe68 Merge pull request #1204 from itflow-org/fix-assign2
Ticket assign
2025-04-01 10:56:56 -04:00
Johnny
e319768fd3 Merge pull request #1203 from itflow-org/fix-bulk-assign
Tickets - Fix bulk assign
2025-04-01 10:56:27 -04:00
Johnny
c30ffcf096 Merge pull request #1202 from itflow-org/user-activity
User activity
2025-04-01 10:55:17 -04:00
wrongecho
7286248fef Ticket assign
Remove the role check altogether, its the old way of doing the roles anyway
2025-04-01 09:12:24 +01:00
wrongecho
dc49f80cc3 Tickets - Fix bulk assign
Fix bulk assigning tickets to agents
2025-04-01 09:03:33 +01:00
wrongecho
1ae2da8054 User activity
Hide the See More button if the user can't actually access the logs due to not being an admin
2025-04-01 08:46:22 +01:00
johnnyq
090f4cb560 Fix adding location phone extension when addign a client 2025-03-31 19:33:07 -04:00
johnnyq
0914716b8e Allow user to redact client replied tickets 2025-03-31 18:42:56 -04:00
johnnyq
ab463c1773 Tidy Phone Country code add + placeholder 2025-03-31 17:30:33 -04:00
johnnyq
36af4d11fc Few more phone fixes 2025-03-31 16:52:47 -04:00
johnnyq
14d8dc6fa6 Fix php errors thrown when formatPhone is blank 2025-03-31 16:35:36 -04:00
johnnyq
2032b48ad3 DB Update Set Country codes to default to NULL and not 1 Nullify all current country codes 2025-03-31 12:06:36 -04:00
Johnny
2af795f548 Merge pull request #1201 from itflow-org/fix-users
Fix users
2025-03-31 11:22:47 -04:00
Johnny
7b4edb2948 Merge pull request #1200 from itflow-org/recurring-invoices
Recurring invoices
2025-03-31 11:22:30 -04:00
wrongecho
17a906fd03 Users bugfixes
- Fix syntax error when adding user, thanks @fleetlognorge
- Fix old reference to scheduled_tickets
2025-03-31 08:35:42 +01:00
wrongecho
af46a1fd96 Fix syntax error when adding user, thanks @fleetlognorge 2025-03-31 08:32:14 +01:00
wrongecho
393c0b8c11 Recurring invoices
- Fix the delete link
- Cron should only flag recurring invoices that with a next-run in the past if the recurring invoice is active
2025-03-31 08:28:22 +01:00
johnnyq
e92f2f714d Fix Ticket Assign to 2025-03-30 20:48:12 -04:00
johnnyq
42606067c0 If no country code is entered display the number only no spaces hyphens or perenthesis 2025-03-30 12:22:43 -04:00
johnnyq
98bb65509d Fix setting country code in company details 2025-03-30 11:45:27 -04:00
johnnyq
a2599e5d43 Fix network location edit 2025-03-30 02:14:06 -04:00
Johnny
0390b1bc2a Merge pull request #1198 from itflow-org/develop
Develop to Master
2025-03-29 18:23:37 -04:00
johnnyq
531f3ec741 Update app version and changelog 2025-03-29 18:18:52 -04:00
johnnyq
127afdca0d DB.sql revert 2 2025-03-29 18:16:25 -04:00
johnnyq
c4df5bf988 DB.sql revert 2025-03-29 18:12:32 -04:00
Johnny
30234e044d Merge pull request #1197 from itflow-org/develop
Merge Develop into Master
2025-03-29 17:47:08 -04:00
johnnyq
1e98ee8916 Update app version and Changelog hotfix 2025-03-29 17:43:00 -04:00
johnnyq
d5665c2577 Update db.sql to match the mediumtext of the updates 2025-03-29 17:35:53 -04:00
johnnyq
762ec51a19 Fix issue with missing phone numbers 2025-03-29 16:41:40 -04:00
johnnyq
309ad724ec Fix client export to only show licnesed software by the selected client only 2025-03-29 16:22:48 -04:00
Johnny
34397fe468 Merge pull request #1196 from itflow-org/develop
Merge Develop into Master
2025-03-29 15:51:47 -04:00
johnnyq
2f82647f5e One more chnagelog update 2025-03-29 15:35:40 -04:00
johnnyq
7d7854424c Refined and updated changelog 2025-03-28 13:15:33 -04:00
johnnyq
eaeadbe933 Fix users list 2025-03-28 12:01:39 -04:00
johnnyq
cf3f0cee6c Revert Users listing 2025-03-28 11:48:23 -04:00
ssteeltm
a5f7b7fa9c fix: missing kanban ticket settings 2025-03-28 12:00:48 -03:00
johnnyq
9f7c289e94 Fix AI Promps 2025-03-27 22:25:01 -04:00
johnnyq
c2bba7a919 Allow to close a project with resolved tickets 2025-03-27 14:21:56 -04:00
johnnyq
4bb37a7198 Removed absent task_description var from projects 2025-03-27 13:41:15 -04:00
johnnyq
231694aabe Fix Invoice Vars in ticket, return empty string instead of null for getFieldByID() 2025-03-27 13:38:22 -04:00
johnnyq
2fb75e6d67 Uncommented out temp comment check cli runtime 2025-03-27 12:40:43 -04:00
Johnny
810af638a3 Merge pull request #1193 from itflow-org/cron-recurring-notify
Recurring items with next-run dates in the past
2025-03-27 12:39:27 -04:00
johnnyq
9223b8cfb1 Fixed some renamed vars 2025-03-27 12:29:55 -04:00
wrongecho
b7df21a663 Notify if a recurring ticket, invoice or expense has a next run date in the past - it needs to be manually adjusted for cron to pick it up again. Also, bugfix bulk recurring ticket delete. 2025-03-27 16:29:39 +00:00
johnnyq
7d47ed4dbd Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-03-27 12:01:24 -04:00
johnnyq
65eaf92862 Fixed a few debug errors where client was not checked to see if it was set in some of the create modals, replaced old url_query_strings_sb var to the correct new var url_query_strings_sort. 2025-03-27 12:01:10 -04:00
wrongecho
8a01bc0d7d Recurring ticket - remove rogue 's' from 'Contact' tab 2025-03-27 15:54:10 +00:00
Johnny
1a8a3781dc Merge pull request #1192 from itflow-org/certs-exp-colours
Certificates page and sidebar - colours/badges
2025-03-27 11:39:49 -04:00
wrongecho
eadfdc41c4 Tickets api - allow setting the billable status when creating a ticket 2025-03-27 14:45:44 +00:00
wrongecho
421abd4c5b Tickets api - bugfix 500 error 2025-03-27 14:34:36 +00:00
wrongecho
ae1a0dcc73 Certificates page and sidebar - Only show yellow on certificates 7 days (blanket, not just for LE) 2025-03-27 12:27:08 +00:00
johnnyq
63b8804e2d Migrated client pdf export to TCPDF from pdfMake 2025-03-26 21:13:00 -04:00
johnnyq
634afcc089 Added TCPDF for PDFs and allow document export to PDF 2025-03-26 19:35:27 -04:00
johnnyq
90f5c8ad57 Simplify getFallBack function to just fallback on - instead N/A 2025-03-26 18:39:45 -04:00
johnnyq
12fd45c144 Dont include Archived Assets, contacts or software is the software license export report 2025-03-26 18:28:33 -04:00
johnnyq
382258a27c Add User and Asset Assigned Licenses to Client PDF Export 2025-03-26 18:17:45 -04:00
johnnyq
b5fa8ab4de Added Search by client Abbreviation to client and global search 2025-03-26 17:56:40 -04:00
johnnyq
bbb0db2f4f Update Changelog 2025-03-26 17:53:33 -04:00
johnnyq
5b89e3dbee Add Phone Country code in even more places 2025-03-26 14:04:47 -04:00
johnnyq
07b29a7bdc Add Phone Country code in more places for proper phone number formatting 2025-03-26 13:36:56 -04:00
johnnyq
3286343026 Update DB to remove phone_mask 2025-03-26 11:14:05 -04:00
johnnyq
6a26b611fa Remove Phone Masking option in favor of Country Codes 2025-03-26 11:10:51 -04:00
johnnyq
218fd2dcdc Update formatPhoneNumber php function to include other country formatting, updated phone inputs to incoude country code 2025-03-25 18:45:24 -04:00
johnnyq
4c85db5e49 Remove legacy redact function in favor of tinymce integration redact 2025-03-24 13:22:41 -04:00
johnnyq
85ae42190a Feature: Added User Signature preferences, currently appends signature to ticket replies / comments 2025-03-24 12:49:47 -04:00
johnnyq
df8a755462 Wrap a wait before the DOM is loaded before loading anything calling anything in app.js 2025-03-23 18:08:14 -04:00
johnnyq
53713a0318 Add back batch payment when in client view for invoices 2025-03-22 21:01:55 -04:00
johnnyq
61aa477cbf Fix Tags 2025-03-22 20:49:37 -04:00
johnnyq
c2adb92d28 Rework tag filter a bit to use array_map instead of looping through the get vars, update string wording to tag_filter and only show tags in the tag filter that are relatd to an entity and also include tags in the get var fixes 2025-03-22 18:32:56 -04:00
johnnyq
19b2b08eac Update locations filter to still include the a location that is not assigned to an entity if present in the url this fixes the issue where for example in client contact you select a location to filter only 1 contact is shown you goto edit the contacts location then submit it pushes you back with no results and all locations is present but in the uri the old location is still present 2025-03-22 15:49:35 -04:00
johnnyq
504346256f Only show locations if an entity references the locations. Previously, all locations were listed in the location filter, even if no entites were assigned to them. 2025-03-22 15:16:53 -04:00
johnnyq
34e92d2223 Update Tags filter to only show tags available 2025-03-22 14:55:13 -04:00
johnnyq
573953704c Limit Client Selection to clients that have an emtity in client filters 2025-03-22 14:11:27 -04:00
johnnyq
0b9f10985d Add Client Select Filters the remaining entities also when creating an entity auto select the client based off the the client selected in the client dropdown filter 2025-03-22 13:50:03 -04:00
johnnyq
8e3dd42a32 Allow start interface to be named 0 2025-03-21 21:54:55 -04:00
johnnyq
0647933df7 Added JS Library to handle Country based Phone formatting inputs intl-tel-input 2025-03-21 12:59:56 -04:00
johnnyq
93f4da3962 Added Phone Country Code fields defaulting to +1 for US will add logic in code later for phone number formatting 2025-03-21 12:48:00 -04:00
johnnyq
f72351ea88 UI tidy 2025-03-21 11:58:16 -04:00
johnnyq
d3c4c8c846 Comment Query 2025-03-20 18:18:33 -04:00
johnnyq
cf047024a1 Add Projects to client side nav and seperated the logic between client and global view of projects 2025-03-20 18:17:26 -04:00
johnnyq
ad3ed68932 Add the ability to Create a ticket inside a project then auto assign it to the project 2025-03-20 17:05:47 -04:00
Johnny
62b8ee9d30 Merge pull request #1190 from itflow-org/cron-certificate-notifs
Cron certificate notifs
2025-03-20 13:51:35 -04:00
johnnyq
eedd92c894 Fix creating a ticket and selecting a template it would use template name instead of the subject for the ticket 2025-03-20 13:47:11 -04:00
johnnyq
622d5e5a44 Delete unused add asset ajax modal 2025-03-20 13:00:51 -04:00
johnnyq
475d653979 You can now upload and create documents, credentials in contact and asset details sections 2025-03-20 12:58:00 -04:00
johnnyq
19a6f8f422 Use nearest text area instead of a static ID for AI rewording, started adding entity creations in contact details and auto selecting the contact when in contact details page 2025-03-20 11:39:50 -04:00
wrongecho
e69d69760d Cron - Only notify on certificates expiring in 45 days if they are valid for longer than 90 (i.e. not LE) 2025-03-20 13:53:53 +00:00
johnnyq
06de349fac Expanded the Redact tool into ticket details area, generalized it to allow redaction in other areas as well 2025-03-19 15:35:02 -04:00
johnnyq
c3ec83f640 Updated changelog also added redact to open tickets 2025-03-19 13:20:55 -04:00
wrongecho
37c20e4e0d Hyperlink the report_time_by_tech report. Need to add a monthly version. 2025-03-19 14:07:07 +00:00
wrongecho
400ba5bb20 Started changelog 2025-03-19 14:02:30 +00:00
wrongecho
a1ea5214a9 Sonarcloud fixes 2025-03-19 13:54:15 +00:00
wrongecho
aae633c4ac Merge pull request #1189 from itflow-org/ticket-redaction
Add ticket redaction feature
2025-03-19 13:53:15 +00:00
johnnyq
ec8d7a36a8 Only store optimized WebP images, so only 1 image is stored and used for thumnails and viewing, removed fields has_preview and has_thumbnail as these are no longer needed, fixed issue when optimizing portrait images the bottom half would get cropped out 2025-03-18 16:48:05 -04:00
wrongecho
21dc26b06f Merge branch 'develop' into ticket-redaction 2025-03-18 09:42:29 +00:00
wrongecho
6a8d2cf1d4 Add ticket redaction feature 2025-03-18 09:40:39 +00:00
johnnyq
b803ba4c55 Use MD5 hashing instead of SHA256 on file uploads which is way faster and still provides a unique file reference 2025-03-17 15:10:39 -04:00
johnnyq
4378fc2719 Removed redundant hash field from files table as the reference already stores this value 2025-03-17 14:59:37 -04:00
johnnyq
244e1290b4 Convert service_domains to use InnoDB instead of MyISAM 2025-03-15 18:35:21 -04:00
johnnyq
5a64bd3a32 Ensure all Tables and fields use CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci 2025-03-15 18:28:48 -04:00
johnnyq
cc0b2126ba Removed most Associated deletions when deleting a client as most of this is performed through SQL now using cascade deleting 2025-03-14 19:45:59 -04:00
johnnyq
97f92e508e Remove Associated Deletions as these are handled by the database cascade deletions 2025-03-14 18:37:56 -04:00
johnnyq
09fbe4e4ad Update more multi to multi link tables to use cascading delete and foreign key relation 2025-03-14 18:18:44 -04:00
johnnyq
508af6a80f Fix some Database update logic 2025-03-14 17:15:10 -04:00
johnnyq
073f816dbd Do not allow cascade deletion for rack devices as this table is optional to reference an asset and will cause issues when adding a devoce without a selected asset 2025-03-14 15:33:00 -04:00
johnnyq
bf327afd19 Bump DataTables from 2.2.1 to 2.2.2 2025-03-14 13:35:48 -04:00
johnnyq
8fb8ce319e Added copy to clipboard for contact and asset ajax modal credentials fixed issue with clipboard because jquery ui was declared last mved it up 2025-03-14 13:28:00 -04:00
johnnyq
eabfef22be Turned caching back on for Ajax Modals Function Fix some PHP Error, update credential vars in assets and contacts 2025-03-14 12:31:18 -04:00
johnnyq
06c31e0808 Update Asset reference SQL Tables to use Foreign keys and cascading delete, and remove orphaned data from the foreign tables to prevent integrity errors during update 2025-03-13 21:35:39 -04:00
johnnyq
509fb5cfed Bump TinyMCE from 7.6.1 to 7.7.1 2025-03-13 19:41:21 -04:00
johnnyq
f1aa66119a Update pointers to the includes folder 2025-03-13 18:12:18 -04:00
johnnyq
7150b1545a Moved files check_login.php, get_settings.php, settings_localization_array.php, inc_set_timezone.php into the includes folder, we also moved /client/check_login.php into client/includes/ 2025-03-13 17:55:31 -04:00
johnnyq
59bbbe4a8d Removed Patch panel tables as they share similarities with assets and assets interfaces, rename events to calendar events and event attendees to calendar even attendees 2025-03-13 16:34:38 -04:00
johnnyq
f64641cfdd Fix regression OTP in guest view item 2025-03-12 23:03:28 -04:00
johnnyq
f1783a6110 update credential model 2025-03-12 22:35:13 -04:00
johnnyq
c8c1155c9c Update the API for the new cred var names 2025-03-12 22:33:06 -04:00
johnnyq
338a08da6c Fix credential vars in Services post 2025-03-12 22:10:48 -04:00
johnnyq
15aed891f4 Fix credential vars in Services 2025-03-12 22:04:55 -04:00
johnnyq
c1c54780cb Update client export pdf for new table field names 2025-03-12 21:39:47 -04:00
johnnyq
e93704bbdb Completely renamed everything login to credential including tables added cascading deletion to the multi to multi tables 2025-03-12 21:28:50 -04:00
johnnyq
c0db914213 Added Recurring Ticket Reference to Tickets 2025-03-12 13:56:36 -04:00
johnnyq
b78e31e518 Fix Recurring Income by Client Report with the updated recurring invoice vars 2025-03-12 11:36:51 -04:00
johnnyq
2533f0ced1 Fix Create Auto Payment after renaming recurring to recurring invoices 2025-03-11 22:54:44 -04:00
johnnyq
c7f4e48a27 A Few more places to update recurring invoice vars 2025-03-11 22:38:13 -04:00
johnnyq
87c1a95b06 Few more places for recurring invoice vars 2025-03-11 22:26:52 -04:00
johnnyq
4efb39358a Missed recurring_invoice details and fixes up a few other places for recurring invoice vars 2025-03-11 22:24:19 -04:00
johnnyq
619b93a545 Renamed Recurring to recurring_invoices updated a large portion of code, and updated many other fields to reflect recurring_invoice and not just recurring 2025-03-11 22:08:37 -04:00
johnnyq
a0598997d7 Update Recurring Tickets in a few more places 2025-03-11 19:55:08 -04:00
johnnyq
d0b8095bba Feature: Added additional assets to Recurring Tickets as well 2025-03-11 19:36:39 -04:00
johnnyq
daab1bca3d Rename the remain items from Scheduled Tickets to Recurring Tickets 2025-03-11 18:32:24 -04:00
johnnyq
a0a2fddd90 Feature: Additonal Assets can now be assigned to a single Ticket 2025-03-11 17:41:40 -04:00
johnnyq
f61c30bd5a Started work on additional assets per ticket, added table ticket_assets, Fixed Legacy Check User Role Functions 2025-03-11 15:10:23 -04:00
johnnyq
4921d1eb19 More Work on Client Users section, added User Icon Indicator in contact if a user account exists 2025-03-11 13:59:01 -04:00
johnnyq
28c8b1a6da Fix missing attachments on ticket replies via the ticket email parser 2025-03-10 19:17:40 -04:00
johnnyq
3f0a6df717 Organize color theme settings into similar color rows 2025-03-10 18:46:08 -04:00
johnnyq
07c8398e0d Update user_roles naming in setup and setup_cli 2025-03-10 18:06:47 -04:00
johnnyq
82c7a64a25 Added Bulk Delete Asset Functionality and also deleted more asset reference tables as we are not using cascade delete yet 2025-03-10 17:35:16 -04:00
johnnyq
164a6a5604 Started Standard user view and client user view in users 2025-03-10 16:51:10 -04:00
johnnyq
9b6ea851e7 Removed the prepended user_ from the fields in the user_roles table, moved user_role_id from user_settings directly to users table, rename table user_permissions to user_client_permissions, removed unused Sessions vars in login. This upedate will require to update using update_cli.php --db_update 2025-03-10 15:57:16 -04:00
johnnyq
3804e18e53 When cron or manually generating invoice from a Recurring Invoice insert referencing recurring Invoice ID into the invoice 2025-03-10 12:34:31 -04:00
johnnyq
244a47efad Added Recurring Invoice Reference ID to Invoices and Product ID reference to Invoice Items 2025-03-10 12:26:14 -04:00
Johnny
89e59b2448 Merge pull request #1184 from itflow-org/tck-time-by-tech
Add work/time by technician report
2025-03-09 12:31:34 -04:00
Johnny
bf9c2f6de7 Merge pull request #1182 from itflow-org/tck-fr-at
Add database field for ticket_first_response_at.
2025-03-09 12:31:07 -04:00
Johnny
ff80a3db3f Merge pull request #1186 from itflow-org/develop
v25.02.4 - Stable Minor Release
2025-03-08 18:11:38 -05:00
johnnyq
c7d00d7b0d Fixed Changelog 2025-03-08 17:53:20 -05:00
johnnyq
1c6e74b08e Update Changelog put back the missing parts for 25.02.3 2025-03-08 17:40:36 -05:00
johnnyq
f8d054f8aa Bump minor version and update the Changelog 2025-03-08 17:25:10 -05:00
wrongecho
e5dc50ec35 Add time by technician report 2025-03-07 22:57:18 +00:00
johnnyq
e0dfaf2d22 Fixed a few var errors in ajax contact details 2025-03-07 16:58:52 -05:00
johnnyq
757a62c35b Fix Ticket Count under contact listing 2025-03-07 16:44:38 -05:00
johnnyq
52a62fc23c Fix Client URL in recurring Invoices 2025-03-07 14:47:47 -05:00
wrongecho
44b70d7161 Add database field for ticket_first_response_at. This can be used as part of metric reporting and also as part of SLAs in the future 2025-03-07 13:28:35 +00:00
johnnyq
ad9e4b4fb4 Added new php function to retrieve and escape a single record from a specified table using an id getFieldById(table, id, field_to_retrieve, escape_method) escape method defaults to SQL but html and json and int can be specified 2025-03-04 13:45:21 -05:00
johnnyq
4fdd5ae769 Fix Bug adding software license if no vendor is selected 2025-03-04 00:13:21 -05:00
Johnny
9f2b9e3b3e Merge pull request #1181 from itflow-org/develop
v25.02.3 - Stable Minor Release
2025-03-03 15:57:26 -05:00
johnnyq
2c074e9dc4 Spelling 2025-03-03 15:55:01 -05:00
johnnyq
0fad31d683 Update changelog new minor release 2025-03-03 15:53:58 -05:00
johnnyq
b154930a4c Fix Notifications 2025-03-03 15:36:32 -05:00
Johnny
359b04e7d1 Merge pull request #1180 from itflow-org/develop
v25.02.2 Maint / Small Feature Release
2025-03-03 15:22:57 -05:00
johnnyq
cc00e3bf75 Add Periods to the changelog 2025-03-03 15:19:18 -05:00
johnnyq
0454685039 Update Changelog 2025-03-03 15:09:40 -05:00
johnnyq
b5eb325c5e Fix Dismissed Notification Search Filter 2025-03-03 15:00:33 -05:00
johnnyq
ed6276a3e4 Add Active Inactive filter to recurring invoices 2025-03-03 14:56:04 -05:00
johnnyq
5da1310e34 Combine Notifications dismissed and notifications into 1 and add link to Notifications Ajax modal 2025-03-03 14:36:38 -05:00
wrongecho
a69b09c9e6 Bugfix: When exporting to CSV, the first asset isn't shown 2025-03-03 09:42:45 +00:00
wrongecho
8da3bb15e9 Add physical location field to asset csv import/export 2025-03-03 09:29:28 +00:00
wrongecho
8488445bf4 Start March changelog 2025-03-03 09:06:07 +00:00
wrongecho
546d21adac Fix client notes on edit modal 2025-03-03 09:03:49 +00:00
johnnyq
580f50b187 Added Link button to WYSIWYG Document Creation and editing 2025-03-03 00:22:51 -05:00
johnnyq
4744276f2a Don't count Non-Billable Invoices in overdue count 2025-03-03 00:07:22 -05:00
johnnyq
6106b8aebb Fix broken client link for the report clients with a balance 2025-03-02 21:03:02 -05:00
Johnny
dd2b203321 Merge pull request #1178 from itflow-org/43-ssl-history
Add SSL certificate history tracking
2025-03-02 11:22:34 -05:00
Marcus Hill
7994c9c7a8 Add SSL certificate history tracking 2025-03-02 10:15:26 +00:00
Marcus Hill
ae59aa3326 Add SSL certificate history tracking 2025-03-02 10:12:47 +00:00
Marcus Hill
0ab9a1c97d Temp fix warnings on num_domains expiring / num_domains_expired vars not defined yet 2025-03-02 09:50:50 +00:00
Marcus Hill
2908568e2a Fix certificates not showing notes 2025-03-02 09:40:21 +00:00
Marcus Hill
2b673a1b6c Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-03-02 09:26:28 +00:00
Marcus Hill
bece8abfe2 Prune db updates older than a year 2025-03-02 09:26:16 +00:00
johnnyq
ac2b355399 updated Changelog and bumped app version to 25.02.2 2025-03-01 21:21:03 -05:00
1280 changed files with 142801 additions and 17915 deletions

View File

@@ -2,6 +2,231 @@
This file documents all notable changes made to ITFlow.
## [25.06]
### Breaking CHANGES
- Old Document Verions will be deleted due to the major backend rewrite how document versions work.
### Added / Changed
- Improved function for retrieving remote IP address for logging purposes.
- Ticket categories are now sorted alphabetically.
- Visiting a deleted invoice or recurring invoice now redirects to the listing page; delete option added to invoice details page.
- Added "Mark as Sent" and "Make Payment" actions directly on the invoice listing page.
- Introduced Ticket Category UI for recurring tickets.
- In Project Details, bulk actions and sorting are now available for tickets.
- Updated ticket details UI to use full card stacks with edit icons for stackable items (e.g., asset, watchers, contact).
- Added a new setting to toggle AutoStart Timer in ticket details (disabled by default).
- Applied gray accent theme in the client section to visually distinguish from the global view.
- Introduced Ticket Due Date functionality (currently supports add/edit only; more updates coming next release).
- Added settings option to display Company Tax ID on invoices.
- Client overview now displays badge counts for all entities.
- Overhauled UI for Invoice, Quote, and Recurring Invoice details; switched PDF generation to TCPDF PHP from PDFMake JS.
- Document versioning has been moved to a separate backend table to resolve permanent link issues -- SEE Breaking CHANGES.
- Migrated Document Templates, Vendor Templates, and Software/License Templates to dedicated tables.
- Added functionality to mark all tasks in a ticket as complete or incomplete.
- Asset CSV import now supports a purchase date field.
- Recurring Payments have been restructured to auto-charge on the invoice due date instead of at generation time.
- Added "Base Template" label for vendor templates when available.
- Backup and restore processes now use a temporary directory; files are cleaned up automatically if operations fail.
- Added confirmation prompt when accepting or declining a quote.
- Other minor code UI/UX cleanups and refactoring throughout the app.
### Fixed
- Resolved issue with enabling MFA.
- Fixed UI regression where ticket listing columns would misalign.
- Non-billable invoices are no longer included in calculations.
- Addressed multiple minor reported security vulnerabilities.
- Tickets with open tasks are no longer resolved in bulk; a warning is shown along with a count of affected tickets.
## [25.05.1]
### Added / Changed
- Added Domain Expiring Card to Client Portal Dashboard for Primary and Technical Users.
- Added Balance and Monthly Recurring Amount to Client Portal Dahboard for Primary and Technical Users.
- Added Archive Searching to network and certificates also added unarchive capabilities to them as well.
### Fixed
- Add Payment not showing in Invoice.
- Updated Client Overview Entities to not show archived client's Entities even though the entity may not be archived.
## [25.05]
### Added / Changed
- Expanded file upload allow-list to include .bat and .stk file types.
- Added full backup/restore functionality. Backup downloads a zip that includes the SQL dump and uploads folder, setup now has option to restore from zip backup.
- Migrated Asset and Contact Links to modals to resolve variable overlap issue.
- Added Pagination to Notification Modal.
- Removed 500 Records Per Page option.
- Removed unused old DB checks in the top nav.
- Clients can now use the portal to setup Stripe automatic payments themselves for recurring invoices
- Automatic payments are now disabled for all recurring invoices if the saved payment method is removed
- Added Card Details and Payment added to Client Stripe.
- UI / UX updates to guest pay Make use of cards.
- Don't show Checkbox columns when ticket is closed, compact ticket list now matches round pills for status and priority.
- Ticket UI/UX update allow the ticket toolbar to be a little more mobile-friendly
- UI / UX Updates to Expenses - Combine Category and Description into 1 column.
- Country information is now displayed in Invoices, Quotes, Recurring Invoices, Clients, Locations, and the client top header.
- Added country-based search filters in Locations and Clients sections.
- Changed the settings name from Integrations to Identity Providers to make room for future iDPs (e.g. Google).
- Bump FullCalendar from 6.1.15 to 6.1.17.
- Bump DataTables from 2.2.2 to 2.3.1.
- Bump TCPDF from 6.8.2 to 6.9.4.
- Bump tinyMCE from 7.7.1 to 7.9.0.
- Bump phpMailer from 6.9.2 to 6.10.0.
- Bump stripe-php from 16.4.0 to 17.2.1.
### Fixed
- "None" option for SMTP encryption now functions correctly.
- Debug table row counts now reflect actual counts instead of relying on SHOW TABLE STATUS.
- Archived Categories now display properly.
- Stripe saved payment methods are now limited to credit/debit cards only.
## [25.03.6]
### Fixed
- Set default to date to 2035-12-31 as 9999-12-31 and 2999-12-31 broke certain browsers.
- Update Client PDF Export, add header added company logo.
- Present Larger clearer Warning about updates on update page.
- Allow to search by project reference.
## [25.03.5]
### Fixed
- Fixed the user listing issue when copying a trip.
- Corrected the display of recurring invoice amounts on the dashboard.
- Fixed the linking of entities with assets and contacts.
- Resolved the issue with displaying the correct mobile country code in the contact listing.
- Set the default date to `9999-12-31` to ensure future items (like invoices) are displayed by default.
- Fixed the display issue where file folders were not showing properly during document creation.
- Migrated from Dragula to SortableJS for a more modern, mobile-friendly solution.
- Added Handlebars icons for drag-and-drop items.
- Changed behavior to open Contact and Asset Details pages directly instead of using a modal.
## [25.03.4]
### Fixed
- Ability to remove additional assets from the ticket details screen.
- Fix the ability to remove assets from edit ticket not working when only 1 asset exists.
- Fix Database Backup corruption.
- Client Portal - show ticket number instead of ticket id in ticket listing.
- Add Purchase Reference to copy asset.
- Add Link to asset details from the global search.
- Fix Bulk assign ticket only showing contacts instead of ITFlow users.
## [25.03.3]
### Fixed
- Fix adding ITFlow user.
- Do not alert on inactive recurring invoices.
- Fix ticket user assignment including bulk assignment.
- Fix adding a location phone extension.
- Do not default to +1 Country code, instead default to null.
- Do not format numbers unless a country code is entered.
- Fix editing network location.
- Fix ticket redaction on client replies.
- Remove more from user activity as it requires admin privledges.
- Fix MFA Enforcement page.
## [25.03.2]
### Fixed
- Revert DB.sql change
## [25.03.1]
### Fixed
- Phone number missing in various sections.
- Match Database.
- Client Export Only display licenses users and assets from the selected client only.
## [25.03]
### Fixed
- Resolved missing attachments in ticket replies processed via the email parser.
- Fixed issue where the top half of portrait image uploads appeared cut off at the bottom.
- Ensured all tables and fields use `CHARACTER SET utf8mb4` and `COLLATE utf8mb4_general_ci` for updates and new installations.
- Converted `service_domains` table to use InnoDB instead of MyISAM.
- Fixed the initials function to properly handle UTF-8 characters, preventing contact-related issues.
- Interfaces can now start with `0`.
- Adjusted AI prompt handling to focus solely on content, avoiding unnecessary additions.
### Added / Changed
- Introduced bulk delete functionality for assets.
- Added the ability to redact ticket replies after a ticket is closed.
- Added support for redacting specific text while a ticket is open.
- Switched file upload hashing from SHA256 to MD5 to significantly improve performance.
- Enabled assigning multiple assets to a single ticket.
- Updated all many-to-many tables to support cascading deletes using foreign key associations, improving efficiency, performance, and data integrity.
- Enabled caching for AJAX modals to reduce repeated reloads and enhance browser performance.
- Upgraded DataTables from 2.2.1 to 2.2.2.
- Upgraded TinyMCE from 7.6.1 to 7.7.1, providing a significant performance boost.
- Added “Copy Credentials to Clipboard” button in AJAX asset and contact views.
- Renamed and reorganized several tables.
- Improved theme color organization by grouping primary colors and their related shades.
- Displayed a user icon next to contacts who have user accounts.
- New image uploads are now converted to optimized `.webp` format by default; original files are no longer saved. Existing images remain unchanged.
- Added international phone number support throughout the system.
- Introduced user signatures in preferences, which are now appended to all ticket replies.
- Optimized search filters to only display defined tags.
- Added “Projects” to the client-side navigation.
- Enabled “Create New Ticket” from within project details.
- Reintroduced batch payment functionality in client invoices.
- Included client abbreviations in both client and global search options.
- Added assigned software license details (User/Asset) to the client PDF export.
- Replaced client-side `pdfMake` with the PHP-based `TCPDF` library for generating client export runbooks.
- Introduced the ability to download documents as PDFs.
- Added a “Reference” field to tickets and invoices generated from recurring templates (not yet in active use).
### Breaking Changes
> **Important:** To update to this version, you **must** run the following commands from the command line from the scripts directory:
>
> ```bash
> php update_cli.php
> php update_cli.php --db_update
> ```
>
> Repeat `--db_update` until no further updates are found.
>
> **Back up your system before upgrading.**
> This version includes numerous backend changes critical for future development.
## [25.02.4]
### Fixed
- Resolved issue preventing the addition or editing of licenses when no vendor was selected.
- Fixed several undeclared variables in AJAX contact details.
- Corrected the contact ticket count display.
- Addressed an issue where clicking "More Details" in AJAX contact/asset details failed to include the `client_id` in the URL.
- Fixed an issue with recurring invoices in the client URL: clicking "Inactive" or "Active" would unexpectedly navigate away from the client section.
- Added new php function getFieldById() to return a record using just an id and sanitized as well.
## [25.02.3]
### Fixed
- Fixed notifications being reversed as dismissed notifications.
## [25.02.2]
### Fixed
- Corrected some edit modals not showing notes correctly.
- Bugfix: When exporting to CSV, the first asset wasn't being shown.
- Fix broken create / edit credentials.
- Fixed missing Notificatons link.
- Fixed a few dead links.
- Fixed Overdue count also counting Non-Billable Invoices.
- Fix Edit Client Notes.
### Added / Changed
- Implemented SSL certificate history tracking.
- Added Inactive / Active Filter to Recurring Invoices.
- Merged Dismissed notifications and notification in one.
- Added Link Button to addd / edit Document WYSIWYG.
- Added Physical location to the asset export / import.
## [25.02.1]
### Fixed
- Resolved broken links in the client overview, project and client listings, and rack details.
@@ -24,33 +249,33 @@ This file documents all notable changes made to ITFlow.
- Added a Vendor Quick Details Modal.
- Enabled vendor linking and added a License Purchase Reference in the Software Licenses section.
- Added download original, optimized and thumbnail option for images.
- Added Paid status to the top corner of Invoice PDFs
- Added Paid status to the top corner of Invoice PDFs.
## [25.02]
### Fixed
- Migrated several reports to the new permissions/roles system
- Resolved issue with empty task box showing for closed/resolved tickets
- Corrected ticket priority sorting
- Cloned asset interfaces when transferring assets between clients
- Migrated several reports to the new permissions/roles system.
- Resolved issue with empty task box showing for closed/resolved tickets.
- Corrected ticket priority sorting.
- Cloned asset interfaces when transferring assets between clients.
### Added / Changed
- Restored max number of records per page option back to 500 since we dont have repeating modals.
- Bulk Categorize Tickets feature
- Renamed "Interface port" to "Interface Description." "Interface Name" should now refer to port name and/or number
- Changed "Transfer Asset to Client" from a single action to a bulk action
- Updated Filter Footer UI to show "Showing x to x of x records" instead of just the total records
- Bulk Categorize Tickets feature.
- Renamed "Interface port" to "Interface Description." "Interface Name" should now refer to port name and/or number.
- Changed "Transfer Asset to Client" from a single action to a bulk action.
- Updated Filter Footer UI to show "Showing x to x of x records" instead of just the total records.
- Added Client Overview section to view client assets, contacts, licenses, credentials, etc.
- Introduced Quick Peek for asset details, contact information, and document viewing throughout the ITFlow App, all made possible by AJAX
- Enabled Simple Drag-and-Drop Ordering for Invoices, Recurring Invoices, Quotes, Ticket Tasks, and Ticket Template Tasks
- Added new Ticket View options: Kanban and Simple View
- Migrated all repeating modals to the new AJAX modal function for faster loading times and quicker development
- Allowed clients to upload PDF documents to accepted quotes
- Client Portal now shows ticket category
- Custom links can now be added to the Client Portal navbar
- Introduced Quick Peek for asset details, contact information, and document viewing throughout the ITFlow App, all made possible by AJAX.
- Enabled Simple Drag-and-Drop Ordering for Invoices, Recurring Invoices, Quotes, Ticket Tasks, and Ticket Template Tasks.
- Added new Ticket View options: Kanban and Simple View.
- Migrated all repeating modals to the new AJAX modal function for faster loading times and quicker development.
- Allowed clients to upload PDF documents to accepted quotes.
- Client Portal now shows ticket category.
- Custom links can now be added to the Client Portal navbar.
- Lots of little tweaks to UI, performance, bugs, etc.
### Breaking Changes
- Cron scripts have officially been moved to the /scripts folder and are no longer in the root directory; they must be updated to function properly
- Cron scripts have officially been moved to the /scripts folder and are no longer in the root directory; they must be updated to function properly.
## [25.01.3]
### Fixed

View File

@@ -93,6 +93,7 @@ If you want to improve ITFlow, feel free to fork the repo and create a pull requ
Were incredibly grateful to the organizations and individuals who support the project - a big thank you to:
- CompuMatter
- F1 for HELP
- JetBrains (PhpStorm)
## License
ITFlow is distributed "as is" under the GPL License, WITHOUT WARRANTY OF ANY KIND. See [`LICENSE`](https://github.com/itflow-org/itflow/blob/master/LICENSE) for details.

View File

@@ -12,10 +12,8 @@
We operate a rolling release model. Any bug fixes will be released into latest version of ITFlow, so you must stay up-to-date.
| Version | Supported |
| ------- | ------------------ |
| Beta | :x: |
| 24.12 | :white_check_mark: |
| 25.1 | :white_check_mark: (When released) |
|---------| ------------------ |
| 25.05 | :white_check_mark: |
## Reporting a Vulnerability via GitHub Security Advisories

View File

@@ -9,9 +9,6 @@ require_once "includes/inc_all.php";
// Perms
enforceUserPermission('module_financial');
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM accounts

View File

@@ -6,10 +6,6 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM api_keys

View File

@@ -26,9 +26,6 @@ if (isset($_GET['category']) & !empty($_GET['catergory'])) {
$category_filter = '';
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM app_logs
@@ -48,14 +45,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<h3 class="card-title"><i class="fas fa-fw fa-history mr-2"></i>App Logs</h3>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<form autocomplete="off">
<div class="row">
<div class="col-sm-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search app logs">
<div class="input-group-append">
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
<div class="form-group">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search app logs">
<div class="input-group-append">
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</div>

View File

@@ -46,9 +46,6 @@ if (isset($_GET['action']) & !empty($_GET['action'])) {
$action_filter = '';
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM logs
@@ -75,7 +72,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<form class="mb-4" autocomplete="off">
<div class="row">
<div class="col-sm-4">
<div class="input-group">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search audit logs">
<div class="input-group-append">
<button class="btn btn-secondary" type="button" data-toggle="collapse" data-target="#advancedFilter"><i class="fas fa-filter"></i></button>
@@ -85,7 +82,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
<div class="col-sm-2">
<div class="form-group">
<div class="input-group mb-3 mb-md-0">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="">- All Clients -</option>
@@ -105,7 +102,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
<div class="col-sm-2">
<div class="form-group">
<div class="input-group mb-3 mb-md-0">
<select class="form-control select2" name="user" onchange="this.form.submit()">
<option value="">- All Users -</option>
@@ -125,7 +122,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
<div class="col-sm-2">
<div class="form-group">
<div class="input-group mb-3 mb-md-0">
<select class="form-control select2" name="type" onchange="this.form.submit()">
<option value="">- All Types -</option>
@@ -144,7 +141,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
<div class="col-sm-2">
<div class="form-group">
<div class="input-group mb-3 mb-md-0">
<select class="form-control select2" name="action" onchange="this.form.submit()">
<option value="">- All Actions -</option>
@@ -198,7 +195,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<hr>
<div class="table-responsive-sm">
<table class="table table-sm table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_created_at&order=<?php echo $disp; ?>">

View File

@@ -8,7 +8,7 @@ require_once "includes/inc_all_admin.php";
</div>
<div class="card-body" style="text-align: center;">
<div class="alert alert-secondary">If you are unable to back up the entire VM, you'll need to back up the files & database individually. There is no built-in restore. See the <a href="https://docs.itflow.org/backups" target="_blank">docs here</a>.</div>
<a class="btn btn-primary btn-lg p-3" href="post.php?download_database&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download database</a>
<a class="btn btn-primary btn-lg p-3" href="post.php?download_backup&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-4x fa-download"></i><br><br>Download Backup</a>
</div>
</div>
@@ -20,12 +20,12 @@ require_once "includes/inc_all_admin.php";
<div class="card-body">
<form action="post.php" method="POST">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="row d-flex justify-content-center">
<div class="input-group col-4">
<div class="input-group-prepend">
<input type="password" class="form-control" placeholder="Enter your account password" name="password" autocomplete="new-password" required>
<div class="d-flex justify-content-center">
<div class="input-group col-sm-4">
<input type="password" class="form-control" placeholder="Enter your account password" name="password" autocomplete="new-password" required>
<div class="input-group-append">
<button class="btn btn-primary" type="submit" name="backup_master_key"><i class="fas fa-key"></i></button>
</div>
<button class="btn btn-primary" type="submit" name="backup_master_key"><i class="fas fa-fw fa-key mr-2"></i>Get Master Key</button>
</div>
</div>
</form>

View File

@@ -13,10 +13,6 @@ if (isset($_GET['category'])) {
$category = "Expense";
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM categories
@@ -27,10 +23,6 @@ $sql = mysqli_query(
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if (isset($_GET['archived'])) {
$category = "Archived";
}
?>
<div class="card card-dark">
@@ -98,7 +90,7 @@ if (isset($_GET['archived'])) {
} else {
echo 'btn-default';
} ?>">Ticket</a>
<a href="?archived=1"
<a href="?<?php echo $url_query_strings_sort ?>&archived=1"
class="btn <?php if (isset($_GET['archived'])) {
echo 'btn-primary';
} else {
@@ -150,7 +142,7 @@ if (isset($_GET['archived'])) {
</button>
<div class="dropdown-menu">
<?php
if ($category == "Archived") {
if ($archived) {
?>
<a class="dropdown-item text-success confirm-link"
href="post.php?unarchive_category=<?php echo $category_id; ?>">

View File

@@ -6,10 +6,6 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM custom_links

View File

@@ -296,7 +296,13 @@ if ($tablesResult) {
while ($table = $tablesResult->fetch_assoc()) {
$tableName = $table['Name'];
$tableRows = $table['Rows'];
// Accurate row count
$countResult = $mysqli->query("SELECT COUNT(*) AS cnt FROM `$tableName`");
$countRow = $countResult->fetch_assoc();
$tableRows = $countRow['cnt'];
$countResult->free();
$dataLength = $table['Data_length'];
$indexLength = $table['Index_length'];
$tableSize = ($dataLength + $indexLength) / (1024 * 1024); // Size in MB
@@ -336,11 +342,6 @@ if ($tablesResult) {
'name' => 'Total database size (MB)',
'value' => round($totalSize, 2) . ' MB',
];
} else {
$databaseStats[] = [
'name' => 'Database connection error',
'value' => $mysqli->error,
];
}
// Section: Database Structure Comparison
@@ -518,24 +519,26 @@ $mysqli->close();
</ul>
<hr>
<table class="table table-bordered mb-3">
<tr>
<th>ITFlow release version</th>
<th><?php echo APP_VERSION; ?></th>
</tr>
<tr>
<td>Current DB Version</td>
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
</tr>
<tr>
<td>Current Code Commit</td>
<td><?php echo $commitHash; ?></td>
</tr>
<tr>
<td>Current Branch</td>
<td><?php echo $gitBranch; ?></td>
</tr>
</table>
<div class="table-responsive">
<table class="table table-bordered mb-3">
<tr>
<th>ITFlow release version</th>
<th><?php echo APP_VERSION; ?></th>
</tr>
<tr>
<td>Current DB Version</td>
<td><?php echo CURRENT_DATABASE_VERSION; ?></td>
</tr>
<tr>
<td>Current Code Commit</td>
<td><?php echo $commitHash; ?></td>
</tr>
<tr>
<td>Current Branch</td>
<td><?php echo $gitBranch; ?></td>
</tr>
</table>
</div>
<!-- System Information Table -->
<h3>System Information</h3>
@@ -552,200 +555,209 @@ $mysqli->close();
<!-- PHP Extensions and Configuration Table -->
<h3 class="mt-3">PHP Extensions and Configuration</h3>
<table class="table table-sm table-bordered">
<!-- PHP Extensions Section -->
<thead>
<tr class="table-secondary">
<th colspan="3">PHP Extensions</th>
</tr>
</thead>
<tbody>
<?php foreach ($phpExtensions as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<!-- PHP Extensions Section -->
<thead>
<tr class="table-secondary">
<th colspan="3">PHP Extensions</th>
</tr>
<?php endforeach; ?>
</tbody>
<!-- PHP Configuration Section -->
<thead>
<tr class="table-secondary">
<th colspan="3">PHP Configuration</th>
</tr>
</thead>
<tbody>
<?php foreach ($phpConfig as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</thead>
<tbody>
<?php foreach ($phpExtensions as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<!-- PHP Configuration Section -->
<thead>
<tr class="table-secondary">
<th colspan="3">PHP Configuration</th>
</tr>
<?php endforeach; ?>
</tbody>
<thead>
<tr class="table-secondary">
<th colspan="3">Shell Commands</th>
</tr>
</thead>
<tbody>
<?php foreach ($shellCommands as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</thead>
<tbody>
<?php foreach ($phpConfig as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<thead>
<tr class="table-secondary">
<th colspan="3">Shell Commands</th>
</tr>
<?php endforeach; ?>
</tbody>
<thead>
<tr class="table-secondary">
<th colspan="3">SSL Checks</th>
</tr>
</thead>
<tbody>
<?php foreach ($sslChecks as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</thead>
<tbody>
<?php foreach ($shellCommands as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<thead>
<tr class="table-secondary">
<th colspan="3">SSL Checks</th>
</tr>
<?php endforeach; ?>
</tbody>
<thead>
<tr class="table-secondary">
<th colspan="3">Domain Checks</th>
</tr>
</thead>
<tbody>
<?php foreach ($domainChecks as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</thead>
<tbody>
<?php foreach ($sslChecks as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<thead>
<tr class="table-secondary">
<th colspan="3">Domain Checks</th>
</tr>
<?php endforeach; ?>
</tbody>
</thead>
<tbody>
<?php foreach ($domainChecks as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
<!-- File Permissions Table -->
<thead>
<tr class="table-secondary">
<th colspan="3">File Permissions</th>
</tr>
</thead>
<tbody>
<?php foreach ($filePermissions as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
<!-- File Permissions Table -->
<thead>
<tr class="table-secondary">
<th colspan="3">File Permissions</th>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</thead>
<tbody>
<?php foreach ($filePermissions as $check): ?>
<tr>
<td><?= htmlspecialchars($check['name']); ?></td>
<td class="text-center">
<?php if ($check['passed']): ?>
<i class="fas fa-check" style="color:green"></i>
<?php else: ?>
<i class="fas fa-times" style="color:red"></i>
<?php endif; ?>
</td>
<td><?= htmlspecialchars($check['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<!-- Database Structure Comparison Table -->
<h3 class="mt-3">Database Structure Comparison</h3>
<table class="table table-sm table-bordered">
<tbody>
<?php if (!empty($dbComparison)): ?>
<?php foreach ($dbComparison as $issue): ?>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<tbody>
<?php if (!empty($dbComparison)): ?>
<?php foreach ($dbComparison as $issue): ?>
<tr>
<td><?= htmlspecialchars($issue['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td><?= htmlspecialchars($issue['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></td>
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
</tr>
<?php endforeach; ?>
<?php else: ?>
<tr>
<td colspan="3">No discrepancies found between the database and db.sql file.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
<?php endif; ?>
</tbody>
</table>
</div>
<!-- Uploads Directory Stats Table -->
<h3 class="mt-3">Uploads Directory Stats</h3>
<table class="table table-sm table-bordered">
<tbody>
<?php foreach ($uploadsStats as $stat): ?>
<tr>
<td><?= htmlspecialchars($stat['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<tbody>
<?php foreach ($uploadsStats as $stat): ?>
<tr>
<td><?= htmlspecialchars($stat['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<!-- Database Stats Table -->
<h3 class="mt-3">Database Stats</h3>
<table class="table table-sm table-bordered">
<tbody>
<?php foreach ($databaseStats as $stat): ?>
<tr>
<td><?= htmlspecialchars($stat['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<tbody>
<?php foreach ($databaseStats as $stat): ?>
<tr>
<td><?= htmlspecialchars($stat['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($stat['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<!-- Table Stats Table -->
<h3 class="mt-3">Table Stats</h3>
<table class="table table-sm table-bordered">
<thead>
<tr>
<th>Table Name</th>
<th>Fields / Rows</th>
<th>Size (MB)</th>
</tr>
</thead>
<tbody>
<?php foreach ($tableDetails as $table): ?>
<div class="table-responsive">
<table class="table table-sm table-bordered">
<thead>
<tr>
<td><?= htmlspecialchars($table['name']); ?></td>
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
<th>Table Name</th>
<th>Fields / Rows</th>
<th>Size (MB)</th>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</thead>
<tbody>
<?php foreach ($tableDetails as $table): ?>
<tr>
<td><?= htmlspecialchars($table['name']); ?></td>
<td><?= htmlspecialchars("Fields: {$table['fields']}, Rows: {$table['rows']}"); ?></td>
<td><?= htmlspecialchars($table['size'] . ' MB'); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>

View File

@@ -1,27 +1,16 @@
<?php
// Default Column Sort by Filter
$sort = "document_name";
$sort = "document_template_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
// Search query SQL snippet
if (!empty($q)) {
$query_snippet = "AND (MATCH(document_content_raw) AGAINST ('$q') OR document_name LIKE '%$q%')";
} else {
$query_snippet = ""; // empty
}
// Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM documents
LEFT JOIN users ON document_created_by = user_id
WHERE document_template = 1
$query_snippet
"SELECT SQL_CALC_FOUND_ROWS * FROM document_templates
LEFT JOIN users ON document_template_created_by = user_id
WHERE user_name LIKE '%$q%' OR document_template_name LIKE '%$q%'
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
@@ -55,18 +44,18 @@
<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=document_name&order=<?php echo $disp; ?>">
Template Name <?php if ($sort == 'document_name') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=document_template_name&order=<?php echo $disp; ?>">
Template Name <?php if ($sort == 'document_template_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=document_created_at&order=<?php echo $disp; ?>">
Created <?php if ($sort == 'document_created_at') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=document_template_created_at&order=<?php echo $disp; ?>">
Created <?php if ($sort == 'document_template_created_at') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=document_updated_at&order=<?php echo $disp; ?>">
Updated <?php if ($sort == 'document_updated_at') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=document_template_updated_at&order=<?php echo $disp; ?>">
Updated <?php if ($sort == 'document_template_updated_at') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">
@@ -78,27 +67,26 @@
<?php
while ($row = mysqli_fetch_array($sql)) {
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
$document_description = nullable_htmlentities($row['document_description']);
$document_content = nullable_htmlentities($row['document_content']);
$document_created_by_name = nullable_htmlentities($row['user_name']);
$document_created_at = nullable_htmlentities($row['document_created_at']);
$document_updated_at = nullable_htmlentities($row['document_updated_at']);
$document_folder_id = intval($row['document_folder_id']);
$document_template_id = intval($row['document_template_id']);
$document_template_name = nullable_htmlentities($row['document_template_name']);
$document_template_description = nullable_htmlentities($row['document_template_description']);
$document_template_content = nullable_htmlentities($row['document_template_content']);
$document_template_created_by_name = nullable_htmlentities($row['user_name']);
$document_template_created_at = nullable_htmlentities($row['document_template_created_at']);
$document_template_updated_at = nullable_htmlentities($row['document_template_updated_at']);
?>
<tr>
<td>
<a class="text-bold" href="admin_document_template_details.php?document_id=<?php echo $document_id; ?>"><i class="fas fa-fw fa-file-alt text-dark"></i> <?php echo $document_name; ?></a>
<div class="mt-1 text-secondary"><?php echo $document_description; ?></div>
<a class="text-bold" href="admin_document_template_details.php?document_template_id=<?php echo $document_template_id; ?>"><i class="fas fa-fw fa-file-alt text-dark"></i> <?php echo $document_template_name; ?></a>
<div class="mt-1 text-secondary"><?php echo $document_template_description; ?></div>
</td>
<td>
<?php echo $document_created_at; ?>
<div class="text-secondary"><?php echo $document_created_by_name; ?></div>
<?php echo $document_template_created_at; ?>
<div class="text-secondary"><?php echo $document_template_created_by_name; ?></div>
</td>
<td><?php echo $document_updated_at; ?></td>
<td><?php echo $document_template_updated_at; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -109,12 +97,12 @@
data-toggle="ajax-modal"
data-modal-size="xl"
data-ajax-url="ajax/ajax_document_template_edit.php"
data-ajax-id="<?php echo $document_id; ?>"
data-ajax-id="<?php echo $document_template_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_document=<?php echo $document_id; ?>">
<a class="dropdown-item text-danger text-bold" href="post.php?delete_document_template=<?php echo $document_template_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>

View File

@@ -11,19 +11,19 @@ $purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting
$purifier_config->set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]);
$purifier = new HTMLPurifier($purifier_config);
if (isset($_GET['document_id'])) {
$document_id = intval($_GET['document_id']);
if (isset($_GET['document_template_id'])) {
$document_template_id = intval($_GET['document_template_id']);
}
$sql_document = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_template = 1 AND document_id = $document_id");
$sql_document = mysqli_query($mysqli, "SELECT * FROM document_templates WHERE document_template_id = $document_template_id");
$row = mysqli_fetch_array($sql_document);
$document_name = nullable_htmlentities($row['document_name']);
$document_description = nullable_htmlentities($row['document_description']);
$document_content = $purifier->purify($row['document_content']);
$document_created_at = nullable_htmlentities($row['document_created_at']);
$document_updated_at = nullable_htmlentities($row['document_updated_at']);
$document_template_name = nullable_htmlentities($row['document_template_name']);
$document_template_description = nullable_htmlentities($row['document_template_description']);
$document_template_content = $purifier->purify($row['document_template_content']);
$document_template_created_at = nullable_htmlentities($row['document_template_created_at']);
$document_template_updated_at = nullable_htmlentities($row['document_template_updated_at']);
?>
@@ -37,27 +37,27 @@ $document_updated_at = nullable_htmlentities($row['document_updated_at']);
<li class="breadcrumb-item">
<a href="admin_document_template.php">Document Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-file mr-2"></i><?php echo $document_name; ?></li>
<li class="breadcrumb-item active"><i class="fas fa-file mr-2"></i><?php echo $document_template_name; ?></li>
</ol>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file mr-2"></i><?php echo $document_name; ?></h3>
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file mr-2"></i><?php echo $document_template_name; ?></h3>
<div class="card-tools">
<button type="button" class="btn btn-primary"
data-toggle="ajax-modal"
data-modal-size="xl"
data-ajax-url="ajax/ajax_document_template_edit.php"
data-ajax-id="<?php echo $document_id; ?>"
data-ajax-id="<?php echo $document_template_id; ?>"
>
<i class="fas fa-edit mr-2"></i>Edit
</button>
</div>
</div>
<div class="card-body prettyContent">
<?php echo $document_content; ?>
<?php echo $document_template_content; ?>
</div>
</div>

View File

@@ -4,13 +4,29 @@ require_once "includes/inc_all_admin.php";
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-plug mr-2"></i>Integration Settings</h3>
<h3 class="card-title"><i class="fas fa-fw fa-fingerprint mr-2"></i>Identity Providers</h3>
</div>
<div class="card-body">
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<h4>Client Portal SSO via Microsoft Entra</h4>
<div class="form-group">
<label>Identity Provider <small class='text-secondary'>(Currently only works with Microsft Entra)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-fingerprint"></i></span>
</div>
<select class="form-control select2" readonly>
<option <?php if (empty($config_azure_client_id)) { echo "selected"; } ?>>Disabled</option>
<option <?php if ($config_azure_client_id) { echo "selected"; } ?>>Microsoft Entra</option>
<option>Google (WIP)</option>
<option>Custom SSO (WIP)</option>
</select>
</div>
</div>
<div class="form-group">
<label>MS Entra OAuth App (Client) ID</label>
<div class="input-group">
@@ -33,11 +49,10 @@ require_once "includes/inc_all_admin.php";
<hr>
<button type="submit" name="edit_integrations_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="submit" name="edit_identity_provider" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php require_once "includes/footer.php";

View File

@@ -6,9 +6,6 @@ $order = "DESC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM email_queue

View File

@@ -6,10 +6,6 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM project_templates

View File

@@ -1,20 +1,16 @@
<?php
// Default Column Sortby Filter
$sort = "user_role_is_admin";
$sort = "role_is_admin";
$order = "DESC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM user_roles
WHERE (user_roles.user_role_name LIKE '%$q%' OR user_roles.user_role_description LIKE '%$q%')
AND user_roles.user_role_archived_at IS NULL
WHERE (role_name LIKE '%$q%' OR role_description LIKE '%$q%')
AND role_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
@@ -50,17 +46,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?> text-nowrap">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_role_name&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'user_role_name') { echo $order_icon; } ?>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_name&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'role_name') { echo $order_icon; } ?>
</a>
</th>
<th>Members</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_role_is_admin&order=<?php echo $disp; ?>">
Admin <?php if ($sort == 'user_role_is_admin') { echo $order_icon; } ?>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_is_admin&order=<?php echo $disp; ?>">
Admin <?php if ($sort == 'role_is_admin') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
@@ -70,17 +66,17 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
while ($row = mysqli_fetch_array($sql)) {
$role_id = intval($row['user_role_id']);
$role_name = nullable_htmlentities($row['user_role_name']);
$role_description = nullable_htmlentities($row['user_role_description']);
$role_admin = intval($row['user_role_is_admin']);
$role_archived_at = nullable_htmlentities($row['user_role_archived_at']);
$role_id = intval($row['role_id']);
$role_name = nullable_htmlentities($row['role_name']);
$role_description = nullable_htmlentities($row['role_description']);
$role_admin = intval($row['role_is_admin']);
$role_archived_at = nullable_htmlentities($row['role_archived_at']);
// Count number of users that have each role
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(users.user_id) FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(user_id) FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
$role_user_count = mysqli_fetch_row($sql_role_user_count)[0];
$sql_users = mysqli_query($mysqli, "SELECT * FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_users = mysqli_query($mysqli, "SELECT * FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
// Initialize an empty array to hold user names
$user_names = [];
@@ -90,7 +86,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
// Convert the array of user names to a comma-separated string
$user_names_string = implode(",", $user_names) ;
$user_names_string = implode(",", $user_names);
if (empty($user_names_string)) {
$user_names_string = "-";

View File

@@ -12,12 +12,14 @@ $company_address = nullable_htmlentities($row['company_address']);
$company_city = nullable_htmlentities($row['company_city']);
$company_state = nullable_htmlentities($row['company_state']);
$company_zip = nullable_htmlentities($row['company_zip']);
$company_phone = formatPhoneNumber($row['company_phone']);
$company_phone_country_code = formatPhoneNumber($row['company_phone_country_code']);
$company_phone = nullable_htmlentities(formatPhoneNumber($row['company_phone'], $company_phone_country_code));
$company_email = nullable_htmlentities($row['company_email']);
$company_website = nullable_htmlentities($row['company_website']);
$company_logo = nullable_htmlentities($row['company_logo']);
$company_locale = nullable_htmlentities($row['company_locale']);
$company_currency = nullable_htmlentities($row['company_currency']);
$company_tax_id = nullable_htmlentities($row['company_tax_id']);
$company_initials = nullable_htmlentities(initials($company_name));
@@ -110,13 +112,18 @@ $company_initials = nullable_htmlentities(initials($company_name));
</div>
</div>
<div class="form-group">
<label>Phone</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
<label>Phone</label>
<div class="form-row">
<div class="col-md-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo $company_phone_country_code; ?>" placeholder="+" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $company_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" value="<?php echo $company_phone; ?>">
</div>
</div>
@@ -140,6 +147,16 @@ $company_initials = nullable_htmlentities(initials($company_name));
</div>
</div>
<div class="form-group">
<label>Tax ID</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-balance-scale"></i></span>
</div>
<input type="text" class="form-control" name="tax_id" value="<?php echo $company_tax_id; ?>" placeholder="Tax ID" maxlength="200">
</div>
</div>
<hr>
<button type="submit" name="edit_company" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
@@ -152,4 +169,3 @@ $company_initials = nullable_htmlentities(initials($company_name));
<?php
require_once "includes/footer.php";

View File

@@ -13,9 +13,6 @@ if (isset($_GET['table'])) {
$table = "client_assets";
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM custom_fields

View File

@@ -218,28 +218,6 @@ require_once "includes/inc_all_admin.php";
</div>
</div>
<div class="form-group">
<label>Phone Mask</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-phone"></i></span>
</div>
<select class="form-control select2" name="phone_mask">
<?php
$sql = mysqli_query($mysqli, "SELECT config_phone_mask FROM settings WHERE company_id = 1");
while ($row = mysqli_fetch_array($sql)) {
$phone_mask = intval($row['config_phone_mask']);
} ?>
<option <?php if ($phone_mask == 1) { echo "selected"; }?> value=1>
US Format - e.g. (412) 888-9999
</option>
<option <?php if ($phone_mask == 0) { echo "selected"; }?> value=0>
Non-US Format - e.g. 4128889999
</option>
</select>
</div>
</div>
<hr>
<button type="submit" name="edit_default_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>

View File

@@ -37,12 +37,21 @@ require_once "includes/inc_all_admin.php";
<textarea class="form-control" rows="4" name="config_invoice_footer"><?php echo nullable_htmlentities($config_invoice_footer); ?></textarea>
</div>
<h5>Show Tax ID On Invoices</h5>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_invoice_show_tax_id" <?php if ($config_invoice_show_tax_id == 1) { echo "checked"; } ?> value="1" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Show Tax ID</label>
</div>
</div>
<h5>Invoice Late Fees</h5>
<div class="form-group">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_invoice_late_fee_enable" <?php if ($config_invoice_late_fee_enable == 1) { echo "checked"; } ?> value="1" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Enable Late Fee</label>
<input type="checkbox" class="custom-control-input" name="config_invoice_late_fee_enable" <?php if ($config_invoice_late_fee_enable == 1) { echo "checked"; } ?> value="1" id="customSwitch2">
<label class="custom-control-label" for="customSwitch2">Enable Late Fee</label>
</div>
</div>
@@ -77,7 +86,7 @@ require_once "includes/inc_all_admin.php";
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-barcode"></i></span>
</div>
<input type="text" class="form-control" name="config_recurring_prefix" placeholder="Recurring Prefix" value="<?php echo nullable_htmlentities($config_recurring_prefix); ?>" required>
<input type="text" class="form-control" name="config_recurring_invoice_prefix" placeholder="Recurring Invoice Prefix" value="<?php echo nullable_htmlentities($config_recurring_invoice_prefix); ?>" required>
</div>
</div>
@@ -87,7 +96,7 @@ require_once "includes/inc_all_admin.php";
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-barcode"></i></span>
</div>
<input type="number" min="0" class="form-control" name="config_recurring_next_number" placeholder="Next Recurring Number" value="<?php echo intval($config_recurring_next_number); ?>" required>
<input type="number" min="0" class="form-control" name="config_recurring_invoice_next_number" placeholder="Next Recurring Invoice Number" value="<?php echo intval($config_recurring_invoice_next_number); ?>" required>
</div>
</div>

View File

@@ -319,7 +319,7 @@ require_once "includes/inc_all_admin.php";
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="input-group-append">
<button type="submit" name="test_email_imap" class="btn btn-success"><i class="fas fa-fw fa-inbox mr-2"></i>Test</button>
<button type="submit" name="test_email_imap" class="btn btn-success" disabled><i class="fas fa-fw fa-inbox mr-2"></i>Test (WIP)</button>
</div>
</form>
</div>

View File

@@ -18,158 +18,159 @@ require_once "includes/inc_all_admin.php";
<label class="custom-control-label" for="enableCronSwitch">Enable Cron (recommended) <small>(several cron scripts must also be added to cron with correct schedules, <a href="https://docs.itflow.org/cron">docs</a>)</small></label>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th>Notification</th>
<th>App Notify</th>
<th>Tech Email Notify</th>
<th>Client Email Notify</th>
<th>Create Ticket</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan=5>Expirations</th>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_enable_alert_domain_expire" id="customCheck1" <?php if ($config_enable_alert_domain_expire == 1) { echo "checked"; } ?> value="1">
<label class="custom-control-label" for="customCheck1"></label>
</div>
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th colspan=5>Billing</th>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Reminders</div>
<small class="text-muted">
(This will automatically dispatch a reminder email for the invoice to the primary contact's email every 30 days following the invoice's due date.)
</small>
</th>
<td>
<table class="table table-bordered">
<thead class="thead-dark">
<tr>
<th>Notification</th>
<th>App Notify</th>
<th>Tech Email Notify</th>
<th>Client Email Notify</th>
<th>Create Ticket</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan=5>Expirations</th>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-globe mr-2"></i>Domain Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when a domain is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_enable_alert_domain_expire" id="customCheck1" <?php if ($config_enable_alert_domain_expire == 1) { echo "checked"; } ?> value="1">
<label class="custom-control-label" for="customCheck1"></label>
</div>
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-lock mr-2"></i>Certificate Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when a certificate is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-desktop mr-2"></i>Asset Warranty Expiration Notice</div>
<small class="text-muted">
(This setting triggers a notification when an asset is approaching its expiration date, specifically at 1, 7 and 45 days prior to expiry.)
</small>
</th>
<td>
</td>
<td></td>
<td></td>
<td></td>
</tr>
<tr>
<th colspan=5>Billing</th>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Reminders</div>
<small class="text-muted">
(This will automatically dispatch a reminder email for the invoice to the primary contact's email every 30 days following the invoice's due date.)
</small>
</th>
<td>
</td>
<td></td>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_send_invoice_reminders" <?php if ($config_send_invoice_reminders == 1) { echo "checked"; } ?> value="1" id="sendInvoiceRemindersSwitch">
<label class="custom-control-label" for="sendInvoiceRemindersSwitch"></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-redo-alt mr-2"></i>Send Recurring Invoice</div>
<small class="text-muted">
(This will notify all primary and billing contacts of a client that a new invoice was generated from recurring invoices)
</small>
</th>
<td>
</td>
<td></td>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_send_invoice_reminders" <?php if ($config_send_invoice_reminders == 1) { echo "checked"; } ?> value="1" id="sendInvoiceRemindersSwitch">
<label class="custom-control-label" for="sendInvoiceRemindersSwitch"></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-redo-alt mr-2"></i>Send Recurring Invoice</div>
<small class="text-muted">
(This will notify all primary and billing contacts of a client that a new invoice was generated from recurring invoices)
</small>
</th>
<td>
</td>
<td></td>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_recurring_auto_send_invoice" <?php if ($config_recurring_auto_send_invoice == 1) { echo "checked"; } ?> value="1" id="sendRecurringSwitch">
<label class="custom-control-label" for="sendRecurringSwitch"></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th colspan=5>Operational</th>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-bell mr-2"></i>Send clients general notification emails</div>
<small class="text-secondary">(Should clients receive automatic emails when tickets are raised/closed?)</small>
</th>
<td></td>
<td></td>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_ticket_client_general_notifications" <?php if($config_ticket_client_general_notifications == 1){ echo "checked"; } ?> value="1" id="ticketNotificationSwitch">
<label class="custom-control-label" for="ticketNotificationSwitch"></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-link mr-2"></i>Shared Item View</div>
<small class="text-secondary">(Notify when Shared items are viewed)</small>
</th>
<td></td>
<td></td>
<td>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-clock mr-2"></i>Cron Execution</div>
<small class="text-secondary">(Notify when the nightly cron job ran)</small>
</th>
<td></td>
<td></td>
<td>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-download mr-2"></i>ITFlow Updates</div>
<small class="text-secondary">(Notify when ITFlow has an update)</small>
</th>
<td></td>
<td></td>
<td>
</td>
<td></td>
</tr>
</tbody>
</table>
</td>
<td></td>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_recurring_auto_send_invoice" <?php if ($config_recurring_auto_send_invoice == 1) { echo "checked"; } ?> value="1" id="sendRecurringSwitch">
<label class="custom-control-label" for="sendRecurringSwitch"></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th colspan=5>Operational</th>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-bell mr-2"></i>Send clients general notification emails</div>
<small class="text-secondary">(Should clients receive automatic emails when tickets are raised/closed?)</small>
</th>
<td></td>
<td></td>
<td>
<div class="custom-control custom-checkbox text-center">
<input type="checkbox" class="custom-control-input" name="config_ticket_client_general_notifications" <?php if($config_ticket_client_general_notifications == 1){ echo "checked"; } ?> value="1" id="ticketNotificationSwitch">
<label class="custom-control-label" for="ticketNotificationSwitch"></label>
</div>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-link mr-2"></i>Shared Item View</div>
<small class="text-secondary">(Notify when Shared items are viewed)</small>
</th>
<td></td>
<td></td>
<td>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-clock mr-2"></i>Cron Execution</div>
<small class="text-secondary">(Notify when the nightly cron job ran)</small>
</th>
<td></td>
<td></td>
<td>
</td>
<td></td>
</tr>
<tr>
<th>
<div><i class="fas fa-fw fa-download mr-2"></i>ITFlow Updates</div>
<small class="text-secondary">(Notify when ITFlow has an update)</small>
</th>
<td></td>
<td></td>
<td>
</td>
<td></td>
</tr>
</tbody>
</table>
</div>
<hr>

View File

@@ -76,7 +76,7 @@ require_once "includes/inc_all_admin.php";
<option value="">- Do not expense Stripe fees -</option>
<?php
$sql_select = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND vendor_template = 0 AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
$sql_select = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_select)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);

View File

@@ -11,56 +11,63 @@ $stripe_clients_sql = mysqli_query($mysqli, "SELECT * FROM client_stripe LEFT JO
</div>
<div class="card-body">
<table class="table border border-dark">
<thead class="thead-dark">
<tr>
<th>Client</th>
<th>Stripe Customer ID</th>
<th>Stripe Payment ID</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($stripe_clients_sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$stripe_id = nullable_htmlentities($row['stripe_id']);
$stripe_pm = nullable_htmlentities($row['stripe_pm']);
?>
<div class="table-responsive">
<table class="table border border-dark">
<thead class="thead-dark text-nowrap">
<tr>
<td><?php echo "$client_name ($client_id)" ?></td>
<td><?php echo $stripe_id; ?></td>
<td><?php echo $stripe_pm ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<?php if (!empty($stripe_pm)) { ?>
<a class="dropdown-item text-danger confirm-link" href="post.php?stripe_remove_pm&client_id=<?php echo $client_id ?>&pm=<?php echo $stripe_pm ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-credit-card mr-2"></i>Delete payment method
</a>
<?php } else { ?>
<a data-toggle="tooltip" data-placement="left" title="May result in duplicate customer records in Stripe" class="dropdown-item text-danger confirm-link" href="post.php?stripe_reset_customer&client_id=<?php echo $client_id ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Reset Stripe
</a>
<?php } ?>
</div>
</div>
</td>
<th>Client</th>
<th>Stripe Customer ID</th>
<th>Stripe Payment ID</th>
<th>Payment Details</th>
<th>Created</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php } ?>
<?php
while ($row = mysqli_fetch_array($stripe_clients_sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$stripe_id = nullable_htmlentities($row['stripe_id']);
$stripe_pm = nullable_htmlentities($row['stripe_pm']);
$stripe_pm_details = nullable_htmlentities($row['stripe_pm_details']);
$stripe_pm_created_at = nullable_htmlentities($row['stripe_pm_created_at']);
</tbody>
</table>
?>
<tr>
<td><?php echo "$client_name ($client_id)"; ?></td>
<td><?php echo $stripe_id; ?></td>
<td><?php echo $stripe_pm; ?></td>
<td><?php echo $stripe_pm_details; ?></td>
<td><?php echo $stripe_pm_created_at; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<?php if (!empty($stripe_pm)) { ?>
<a class="dropdown-item text-danger confirm-link" href="post.php?stripe_remove_pm&client_id=<?php echo $client_id ?>&pm=<?php echo $stripe_pm ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-credit-card mr-2"></i>Delete payment method
</a>
<?php } else { ?>
<a data-toggle="tooltip" data-placement="left" title="May result in duplicate customer records in Stripe" class="dropdown-item text-danger confirm-link" href="post.php?stripe_reset_customer&client_id=<?php echo $client_id ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Reset Stripe
</a>
<?php } ?>
</div>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>

View File

@@ -19,7 +19,7 @@ require_once "includes/inc_all_admin.php";
?>
<div class="col-3 text-center mb-3">
<div class="col-4 text-center mb-3">
<div class="form-group">
<div class="custom-control custom-radio">
<input class="custom-control-input" type="radio" onchange="this.form.submit()" id="customRadio<?php echo $theme_color; ?>" name="edit_theme_settings" value="<?php echo $theme_color; ?>" <?php if ($config_theme == $theme_color) { echo "checked"; } ?>>

View File

@@ -53,6 +53,13 @@ require_once "includes/inc_all_admin.php";
</div>
<?php } ?>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_timer_autostart" <?php if ($config_ticket_timer_autostart == 1) { echo "checked"; } ?> value="1" id="ticketTimerSwitch">
<label class="custom-control-label" for="ticketTimerSwitch">Autostart Ticket Timer <small class="text-secondary">(This option will control if the timer starts automatically or manually)</small></label>
</div>
</div>
<div class="form-group">
<label>Number of hours to auto close resolved tickets</label>
<div class="input-group">
@@ -73,6 +80,31 @@ require_once "includes/inc_all_admin.php";
</div>
</div>
<div class="form-group">
<label>Tickets Default View</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
<select class="form-control" name="config_ticket_default_view">
<option value=0 <?php if ($config_ticket_default_view == 0) { echo "selected"; } ?>>List</option>
<option value=1 <?php if ($config_ticket_default_view == 1) { echo "selected"; } ?>>Compact</option>
<option value=2 <?php if ($config_ticket_default_view == 2) { echo "selected"; } ?>>Kanban</option>
</select>
</div>
</div>
<div class="form-group">
<label>Kanban Settings</label>
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_ordering" <?php if ($config_ticket_ordering == 1) { echo "checked"; } ?> value="1" id="ticketOrderingSwitch">
<label class="custom-control-label" for="ticketOrderingSwitch">Allow ticket ordering within its column<small class="text-secondary">(uncheked will result in ordering it by priority and id)</small></label>
</div>
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_moving_columns" <?php if ($config_ticket_moving_columns == 1) { echo "checked"; } ?> value="1" id="ticketMovingColumnsSwitch">
<label class="custom-control-label" for="ticketMovingColumnsSwitch">Allow moving columns</label>
</div>
</div>
<hr>
<button type="submit" name="edit_ticket_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>

View File

@@ -1,20 +1,15 @@
<?php
// Default Column Sortby Filter
$sort = "software_name";
$sort = "software_template_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM software
WHERE software_template = 1
AND (software_name LIKE '%$q%' OR software_type LIKE '%$q%')
"SELECT SQL_CALC_FOUND_ROWS * FROM software_templates
WHERE software_template_name LIKE '%$q%' OR software_template_type LIKE '%$q%'
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
@@ -53,18 +48,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<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=software_name&order=<?php echo $disp; ?>">
Template <?php if ($sort == 'software_name') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=software_template_name&order=<?php echo $disp; ?>">
Template <?php if ($sort == 'software_template_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=software_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'software_type') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=software_template_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'software_template_type') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=software_license_type&order=<?php echo $disp; ?>">
License Type <?php if ($sort == 'software_license_type') { echo $order_icon; } ?>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=software_template_license_type&order=<?php echo $disp; ?>">
License Type <?php if ($sort == 'software_template_license_type') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
@@ -74,41 +69,41 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
while($row = mysqli_fetch_array($sql)){
$software_id = intval($row['software_id']);
$software_name = nullable_htmlentities($row['software_name']);
$software_version = nullable_htmlentities($row['software_version']);
$software_description = nullable_htmlentities($row['software_description']);
$software_type = nullable_htmlentities($row['software_type']);
$software_license_type = nullable_htmlentities($row['software_license_type']);
$software_notes = nullable_htmlentities($row['software_notes']);
$software_template_id = intval($row['software_template_id']);
$software_template_name = nullable_htmlentities($row['software_template_name']);
$software_template_version = nullable_htmlentities($row['software_template_version']);
$software_template_description = nullable_htmlentities($row['software_template_description']);
$software_template_type = nullable_htmlentities($row['software_template_type']);
$software_template_license_type = nullable_htmlentities($row['software_template_license_type']);
$software_template_notes = nullable_htmlentities($row['software_template_notes']);
?>
<tr>
<td>
<a class="text-dark" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_software_template_edit.php" data-ajax-id="<?php echo $software_id; ?>">
<a class="text-dark" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_software_template_edit.php" data-ajax-id="<?php echo $software_template_id; ?>">
<div class="media">
<i class="fa fa-fw fa-2x fa-cube mr-3"></i>
<div class="media-body">
<div><?php echo "$software_name <span>$software_version</span>"; ?></div>
<div><small class="text-secondary"><?php echo $software_description; ?></small></div>
<div><?php echo "$software_template_name <span>$software_template_version</span>"; ?></div>
<div><small class="text-secondary"><?php echo $software_template_description; ?></small></div>
</div>
</div>
</a>
</td>
<td><?php echo $software_type; ?></td>
<td><?php echo $software_license_type; ?></td>
<td><?php echo $software_template_type; ?></td>
<td><?php echo $software_template_license_type; ?></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" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_software_template_edit.php" data-ajax-id="<?php echo $software_id; ?>">
<a class="dropdown-item" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_software_template_edit.php" data-ajax-id="<?php echo $software_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_software=<?php echo $software_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_software_template=<?php echo $software_template_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>

View File

@@ -6,10 +6,6 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM tags

View File

@@ -6,10 +6,6 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT * FROM taxes

View File

@@ -1,15 +1,11 @@
<?php
// Default Column Sortby Filter
$sort = "ticket_status_name";
$sort = "ticket_status_order";
$order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM ticket_statuses
@@ -79,7 +75,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if ($ticket_status_active) {
$ticket_status_display = "<div class='text-success text-bold'>Active</div>";
} else {
$ticket_status_display = "<div class='text-secondary'>Disabled</div>";
$ticket_status_display = "<div class='text-secondary'>Inactive</div>";
}
?>
@@ -97,7 +93,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<span class='badge badge-pill text-light p-2' style="background-color: <?php echo $ticket_status_color; ?>"><?php echo $ticket_status_name; ?></span>
<td><?php echo $ticket_status_display; ?></td>
<td>
<?php if ( $ticket_status_id > 5 ) { ?>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
@@ -106,13 +101,14 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<a class="dropdown-item" href="#" data-toggle="ajax-modal" data-ajax-url="ajax/ajax_custom_ticket_status_edit.php" data-ajax-id="<?php echo $ticket_status_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_status=<?php echo $ticket_status_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php if (!$ticket_status_active) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_status=<?php echo $ticket_status_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token']; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
</div>
</div>
<?php } ?>
</td>
</tr>

View File

@@ -6,10 +6,6 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM ticket_templates

View File

@@ -20,7 +20,7 @@ $sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates WH
$row = mysqli_fetch_array($sql_ticket_templates);
$ticket_template_name = nullable_htmlentities($row['ticket_template_name']);
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
//$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
$ticket_template_details = $purifier->purify($row['ticket_template_details']);
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
@@ -30,156 +30,135 @@ $ticket_template_updated_at = nullable_htmlentities($row['ticket_template_update
$sql_task_templates = mysqli_query($mysqli, "SELECT * FROM task_templates WHERE task_template_ticket_template_id = $ticket_template_id ORDER BY task_template_order ASC, task_template_id ASC");
?>
<link rel="stylesheet" href="plugins/dragula/dragula.min.css">
<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="clients.php">Home</a>
</li>
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_ticket_template.php">Ticket Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
</ol>
<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="clients.php">Home</a>
</li>
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_ticket_template.php">Ticket Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
</ol>
<div class="row">
<div class="col-8">
<div class="row">
<div class="col-9">
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title mt-2">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body">
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
</div>
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title mt-2">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body">
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
<div><small class="text-secondary"><?php //echo $ticket_template_description; ?></small></div>
</div>
</h3>
<div class="card-tools">
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#editTicketTemplateModal">
<i class="fas fa-edit"></i>
</button>
</div>
</div>
<h5><?php echo $ticket_template_subject; ?></h5>
<div class="card-body prettyContent">
<?php echo $ticket_template_details; ?>
</h3>
<div class="card-tools">
<button type="button" class="btn btn-default btn-sm" data-toggle="modal" data-target="#editTicketTemplateModal">
<i class="fas fa-edit"></i>
</button>
</div>
</div>
</div>
<div class="col-4">
<div class="card card-dark">
<div class="card-header">
<h5 class="card-title"><i class="fa fa-fw fa-tasks mr-2"></i>Tasks</h5>
</div>
<div class="card-body">
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tasks"></i></span>
</div>
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required>
<div class="input-group-append">
<button type="submit" name="add_ticket_template_task" class="btn btn-primary"><i class="fas fa-fw fa-check"></i></button>
</div>
</div>
</div>
</form>
<table class="table table-striped table-sm">
<?php
while($row = mysqli_fetch_array($sql_task_templates)){
$task_id = intval($row['task_template_id']);
$task_name = nullable_htmlentities($row['task_template_name']);
$task_completion_estimate = intval($row['task_template_completion_estimate']);
$task_description = nullable_htmlentities($row['task_template_description']);
?>
<tr data-task-id="<?php echo $task_id; ?>">
<td><i class="far fa-fw fa-square text-secondary"></i></td>
<td>
<a href="#" class="grab-cursor">
<span class="text-secondary"><?php echo $task_completion_estimate; ?>m</span>
<span class="text-dark"> - <?php echo $task_name; ?></span>
</a>
</td>
<td class="text-right">
<div class="float-right">
<div class="dropdown dropleft text-center">
<button class="btn btn-link text-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle = "ajax-modal"
data-ajax-url = "ajax/ajax_ticket_template_task_edit.php"
data-ajax-id = "<?php echo $task_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_task_template=<?php echo $task_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash-alt mr-2"></i>Delete
</a>
</div>
</div>
</div>
</td>
</tr>
<?php
}
?>
</table>
</div>
<h5><?php echo $ticket_template_subject; ?></h5>
<div class="card-body prettyContent">
<?php echo $ticket_template_details; ?>
</div>
</div>
</div>
<script src="js/pretty_content.js"></script>
<script src="plugins/dragula/dragula.min.js"></script>
<script>
$(document).ready(function() {
var container = $('.table tbody')[0];
<div class="col-3">
dragula([container])
.on('drop', function (el, target, source, sibling) {
// Handle the drop event to update the order in the database
var rows = $(container).children();
var positions = rows.map(function(index, row) {
return {
id: $(row).data('taskId'),
order: index
};
}).get();
// Send the new order to the server
$.ajax({
url: 'ajax.php',
method: 'POST',
data: {
update_task_templates_order: true, // Adjust the parameter name if needed
ticket_template_id: <?php echo $ticket_template_id; ?>,
positions: positions
},
success: function(data) {
// Handle success
},
error: function(error) {
console.error('Error updating order:', error);
<div class="card card-dark">
<div class="card-header">
<h5 class="card-title"><i class="fa fa-fw fa-tasks mr-2"></i>Tasks</h5>
</div>
<div class="card-body">
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<div class="form-group">
<div class="input-group input-group-sm">
<input type="text" class="form-control" name="task_name" placeholder="Create a task" required maxlength="200">
<div class="input-group-append">
<button type="submit" name="add_ticket_template_task" class="btn btn-primary"><i class="fas fa-fw fa-check"></i></button>
</div>
</div>
</div>
</form>
<table class="table table-sm" id="tasks">
<?php
while($row = mysqli_fetch_array($sql_task_templates)){
$task_id = intval($row['task_template_id']);
$task_name = nullable_htmlentities($row['task_template_name']);
$task_completion_estimate = intval($row['task_template_completion_estimate']);
//$task_description = nullable_htmlentities($row['task_template_description']);
?>
<tr data-task-id="<?php echo $task_id; ?>">
<td>
<a href="#" class="drag-handle"><i class="fas fa-bars text-muted mr-2"></i></a>
<span class="text-dark"><?php echo $task_name; ?></span>
</td>
<td class="text-right">
<div class="float-right">
<div class="dropdown dropleft text-center">
<button class="btn btn-light text-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle = "ajax-modal"
data-ajax-url = "ajax/ajax_ticket_template_task_edit.php"
data-ajax-id = "<?php echo $task_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_task_template=<?php echo $task_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-trash-alt mr-2"></i>Delete
</a>
</div>
</div>
</div>
</td>
</tr>
<?php
}
});
});
});
</script>
?>
</table>
</div>
</div>
</div>
</div>
<script src="js/pretty_content.js"></script>
<script src="plugins/SortableJS/Sortable.min.js"></script>
<script>
new Sortable(document.querySelector('table#tasks tbody'), {
handle: '.drag-handle',
animation: 150,
onEnd: function (evt) {
const rows = document.querySelectorAll('table#tasks tbody tr');
const positions = Array.from(rows).map((row, index) => ({
id: row.dataset.taskId,
order: index
}));
$.post('ajax.php', {
update_task_templates_order: true,
ticket_template_id: <?php echo $ticket_template_id; ?>,
positions: positions
});
}
});
</script>
<?php

View File

@@ -32,8 +32,11 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
<?php } ?>
<?php if (LATEST_DATABASE_VERSION > CURRENT_DATABASE_VERSION) { ?>
<div class="alert alert-warning">
<strong>Ensure you have a current <a href="https://docs.itflow.org/backups">app & database backup</a> before updating!</strong>
<div class="alert alert-danger">
<h1 class="font-weight-bold text-center">⚠️ DANGER ⚠️</h1>
<h2 class="font-weight-bold text-center">Do NOT run updates without first taking a backup</h2>
<p>VM Snapshots are highly recommended over other methods - see the <a href="https://docs.itflow.org/backups" class="alert-link" target="_blank">docs</a>. Review the <a href="https://github.com/itflow-org/itflow/blob/master/CHANGELOG.md" class="alert-link" target="_blank">changelog</a> for breaking changes that may require manual remediation.</p>
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
</div>
<br>
<a class="btn btn-dark btn-lg my-4" href="post.php?update_db"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update Database</h5></a>
@@ -46,9 +49,17 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
<?php } else {
if (!empty($git_log)) { ?>
<div class="alert alert-danger">
<h1 class="font-weight-bold text-center">⚠️ DANGER ⚠️</h1>
<h2 class="font-weight-bold text-center">Do NOT run updates without first taking a backup</h2>
<p>VM Snapshots are highly recommended over other methods - see the <a href="https://docs.itflow.org/backups" class="alert-link" target="_blank">docs</a>. Review the <a href="https://github.com/itflow-org/itflow/blob/master/CHANGELOG.md" class="alert-link" target="_blank">changelog</a> for breaking changes that may require manual remediation.</p>
<p class="text-center font-weight-bold">Ignore this warning at your own risk.</p>
</div>
<a class="btn btn-primary btn-lg my-4" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
<a class="btn btn-danger btn-lg" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?no"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>TEST</h5></a>
<a class="btn btn-primary btn-lg my-4 confirm-link" href="post.php?update"><i class="fas fa-fw fa-4x fa-download mb-1"></i><h5>Update App</h5></a>
<a class="btn btn-danger btn-lg confirm-link" href="post.php?update&force_update=1"><i class="fas fa-fw fa-4x fa-hammer mb-1"></i><h5>FORCE Update App</h5></a>
<?php } else { ?>
<p><strong>Application Release Version:<br><strong class="text-dark"><?php echo APP_VERSION; ?></strong></p>
@@ -56,6 +67,17 @@ $git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format
<p class="text-secondary">Code Commit:<br><strong class="text-dark"><?php echo $current_version; ?></strong></p>
<p class="text-muted">You are up to date!<br>Everything is going to be alright</p>
<i class="far fa-3x text-dark fa-smile-wink"></i><br>
<?php if (rand(1,10) == 1) { ?>
<br>
<div class="alert alert-info alert-dismissible fade show" role="alert">
You're up to date, but when was the last time you checked your ITFlow backup works?
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<?php } ?>
<?php }
}

View File

@@ -6,16 +6,13 @@ $order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM users, user_settings, user_roles
WHERE users.user_id = user_settings.user_id
AND user_settings.user_role = user_roles.user_role_id
AND (user_name LIKE '%$q%' OR user_email LIKE '%$q%')
"SELECT SQL_CALC_FOUND_ROWS * FROM users
LEFT JOIN user_roles ON user_role_id = role_id
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
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
@@ -36,6 +33,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<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>-->
<?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>
<?php } ?>
@@ -55,9 +53,6 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-md-8">
<div class="float-right">
<button type="button" class="btn btn-default" data-toggle="modal" data-target="#exportUserModal"><i class="fa fa-fw fa-download mr-2"></i>Export</button>
</div>
</div>
</div>
</form>
@@ -77,8 +72,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_role&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'user_role') { echo $order_icon; } ?>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=role_name&order=<?php echo $disp; ?>">
Role <?php if ($sort == 'role_name') { echo $order_icon; } ?>
</a>
</th>
<th>
@@ -116,8 +111,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$mfa_status_display = "<i class='fas fa-fw fa-lock text-success'></i>";
}
$user_config_force_mfa = intval($row['user_config_force_mfa']);
$user_role = $row['user_role'];
$user_role_display = nullable_htmlentities($row['user_role_name']);
$user_role = intval($row['user_role_id']);
$user_role_display = nullable_htmlentities($row['role_name']);
$user_initials = nullable_htmlentities(initials($user_name));
$sql_last_login = mysqli_query(
@@ -139,7 +134,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
}
// Get User Client Access Permissions
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_permissions WHERE user_id = $user_id");
$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']);

View File

@@ -1,20 +1,15 @@
<?php
// Default Column Sortby Filter
$sort = "vendor_name";
$sort = "vendor_template_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM vendors
WHERE vendor_template = 1
AND (vendor_name LIKE '%$q%' OR vendor_description LIKE '%$q%' OR vendor_account_number LIKE '%$q%' OR vendor_website LIKE '%$q%' OR vendor_contact_name LIKE '%$q%' OR vendor_email LIKE '%$q%' OR vendor_phone LIKE '%$phone_query%') ORDER BY $sort $order LIMIT $record_from, $record_to"
"SELECT SQL_CALC_FOUND_ROWS * FROM vendor_templates
WHERE vendor_template_name LIKE '%$q%' OR vendor_template_description LIKE '%$q%' OR vendor_template_account_number LIKE '%$q%' OR vendor_template_website LIKE '%$q%' OR vendor_template_contact_name LIKE '%$q%' OR vendor_template_email LIKE '%$q%' OR vendor_template_phone LIKE '%$phone_query%' ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
@@ -53,13 +48,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<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_name&order=<?php echo $disp; ?>">
Vendor <?php if ($sort == 'vendor_name') { echo $order_icon; } ?>
<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_description&order=<?php echo $disp; ?>">
Description <?php if ($sort == 'vendor_description') { echo $order_icon; } ?>
<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>
@@ -70,30 +65,29 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
while ($row = mysqli_fetch_array($sql)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_description = nullable_htmlentities($row['vendor_description']);
if (empty($vendor_description)) {
$vendor_description_display = "-";
$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_description_display = $vendor_description;
$vendor_template_description_display = $vendor_template_description;
}
$vendor_account_number = nullable_htmlentities($row['vendor_account_number']);
$vendor_contact_name = nullable_htmlentities($row['vendor_contact_name']);
if (empty($vendor_contact_name)) {
$vendor_contact_name_display = "-";
$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_contact_name_display = $vendor_contact_name;
$vendor_template_contact_name_display = $vendor_template_contact_name;
}
$vendor_phone = formatPhoneNumber($row['vendor_phone']);
$vendor_extension = nullable_htmlentities($row['vendor_extension']);
$vendor_email = nullable_htmlentities($row['vendor_email']);
$vendor_website = nullable_htmlentities($row['vendor_website']);
$vendor_hours = nullable_htmlentities($row['vendor_hours']);
$vendor_sla = nullable_htmlentities($row['vendor_sla']);
$vendor_code = nullable_htmlentities($row['vendor_code']);
$vendor_notes = nullable_htmlentities($row['vendor_notes']);
$vendor_template = intval($row['vendor_template']);
$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>
@@ -101,38 +95,38 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_vendor_template_edit.php"
data-ajax-id="<?php echo $vendor_id; ?>"
data-ajax-id="<?php echo $vendor_template_id; ?>"
>
<i class="fa fa-fw fa-building text-secondary mr-2"></i><?php echo $vendor_name; ?>
<i class="fa fa-fw fa-building text-secondary mr-2"></i><?php echo $vendor_template_name; ?>
</a>
<?php
if (!empty($vendor_account_number)) {
if (!empty($vendor_template_account_number)) {
?>
<br>
<small class="text-secondary"><?php echo $vendor_account_number; ?></small>
<small class="text-secondary"><?php echo $vendor_template_account_number; ?></small>
<?php
}
?>
</th>
<td><?php echo $vendor_description_display; ?></td>
<td><?php echo $vendor_template_description_display; ?></td>
<td>
<?php
if (!empty($vendor_contact_name)) {
if (!empty($vendor_template_contact_name)) {
?>
<i class="fa fa-fw fa-user text-secondary mr-2 mb-2"></i><?php echo $vendor_contact_name_display; ?>
<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_contact_name_display;
echo $vendor_template_contact_name_display;
}
if (!empty($vendor_phone)) { ?>
<i class="fa fa-fw fa-phone text-secondary mr-2 mb-2"></i><?php echo $vendor_phone; ?>
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_email)) { ?>
<i class="fa fa-fw fa-envelope text-secondary mr-2 mb-2"></i><?php echo $vendor_email; ?>
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 } ?>
@@ -146,13 +140,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_vendor_template_edit.php"
data-ajax-id="<?php echo $vendor_id; ?>"
data-ajax-id="<?php echo $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_id; ?>">
<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 } ?>

View File

@@ -8,7 +8,7 @@
require_once "config.php";
require_once "functions.php";
require_once "check_login.php";
require_once "includes/check_login.php";
require_once "plugins/totp/totp.php";
/*
@@ -165,7 +165,7 @@ if (isset($_GET['ticket_query_views'])) {
}
/*
* Generates public/guest links for sharing logins/docs
* Generates public/guest links for sharing credentials/docs
*/
if (isset($_GET['share_generate_link'])) {
enforceUserPermission('module_support', 2);
@@ -207,23 +207,23 @@ if (isset($_GET['share_generate_link'])) {
$item_name = sanitizeInput($row['file_name']);
}
if ($item_type == "Login") {
$login = mysqli_query($mysqli, "SELECT login_name, login_username, login_password FROM logins WHERE login_id = $item_id AND login_client_id = $client_id LIMIT 1");
$row = mysqli_fetch_array($login);
if ($item_type == "Credential") {
$credential = mysqli_query($mysqli, "SELECT credential_name, credential_username, credential_password FROM credentials WHERE credential_id = $item_id AND credential_client_id = $client_id LIMIT 1");
$row = mysqli_fetch_array($credential);
$item_name = sanitizeInput($row['login_name']);
$item_name = sanitizeInput($row['credential_name']);
// Decrypt & re-encrypt username/password for sharing
$login_encryption_key = randomString();
$credential_encryption_key = randomString();
$login_username_cleartext = decryptLoginEntry($row['login_username']);
$credential_username_cleartext = decryptCredentialEntry($row['credential_username']);
$iv = randomString();
$username_ciphertext = openssl_encrypt($login_username_cleartext, 'aes-128-cbc', $login_encryption_key, 0, $iv);
$username_ciphertext = openssl_encrypt($credential_username_cleartext, 'aes-128-cbc', $credential_encryption_key, 0, $iv);
$item_encrypted_username = $iv . $username_ciphertext;
$login_password_cleartext = decryptLoginEntry($row['login_password']);
$credential_password_cleartext = decryptCredentialEntry($row['credential_password']);
$iv = randomString();
$password_ciphertext = openssl_encrypt($login_password_cleartext, 'aes-128-cbc', $login_encryption_key, 0, $iv);
$password_ciphertext = openssl_encrypt($credential_password_cleartext, 'aes-128-cbc', $credential_encryption_key, 0, $iv);
$item_encrypted_credential = $iv . $password_ciphertext;
}
@@ -232,8 +232,8 @@ if (isset($_GET['share_generate_link'])) {
$share_id = $mysqli->insert_id;
// Return URL
if ($item_type == "Login") {
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key&ek=$login_encryption_key";
if ($item_type == "Credential") {
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key&ek=$credential_encryption_key";
}
else {
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key";
@@ -242,7 +242,7 @@ if (isset($_GET['share_generate_link'])) {
$sql = mysqli_query($mysqli,"SELECT * FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// Sanitize Config vars from get_settings.php
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
@@ -294,6 +294,7 @@ if (isset($_GET['get_active_clients'])) {
$mysqli,
"SELECT client_id, client_name FROM clients
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_accessed_at DESC"
);
@@ -315,7 +316,9 @@ if (isset($_GET['get_client_contacts'])) {
$contact_sql = mysqli_query(
$mysqli,
"SELECT contact_id, contact_name, contact_primary, contact_important, contact_technical FROM contacts
LEFT JOIN clients on contact_client_id = client_id
WHERE contacts.contact_archived_at IS NULL AND contact_client_id = $client_id
$access_permission_query
ORDER BY contact_primary DESC, contact_technical DESC, contact_important DESC, contact_name"
);
@@ -333,24 +336,24 @@ if (isset($_GET['get_client_contacts'])) {
if (isset($_GET['get_totp_token_via_id'])) {
enforceUserPermission('module_credential');
$login_id = intval($_GET['login_id']);
$credential_id = intval($_GET['credential_id']);
$sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT login_name, login_otp_secret, login_client_id FROM logins WHERE login_id = $login_id"));
$name = sanitizeInput($sql['login_name']);
$totp_secret = $sql['login_otp_secret'];
$client_id = intval($sql['login_client_id']);
$sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT credential_name, credential_otp_secret, credential_client_id FROM credentials WHERE credential_id = $credential_id"));
$name = sanitizeInput($sql['credential_name']);
$totp_secret = $sql['credential_otp_secret'];
$client_id = intval($sql['credential_client_id']);
$otp = TokenAuth6238::getTokenCode(strtoupper($totp_secret));
echo json_encode($otp);
// Logging
// Only log the TOTP view if the user hasn't already viewed this specific login entry recently, this prevents logs filling if a user hovers across an entry a few times
$check_recent_totp_view_logged_sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS recent_totp_view FROM logs WHERE log_type = 'Login' AND log_action = 'View TOTP' AND log_user_id = $session_user_id AND log_entity_id = $login_id AND log_client_id = $client_id AND log_created_at > (NOW() - INTERVAL 5 MINUTE)"));
$check_recent_totp_view_logged_sql = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT COUNT(log_id) AS recent_totp_view FROM logs WHERE log_type = 'Credential' AND log_action = 'View TOTP' AND log_user_id = $session_user_id AND log_entity_id = $credential_id AND log_client_id = $client_id AND log_created_at > (NOW() - INTERVAL 5 MINUTE)"));
$recent_totp_view_logged_count = intval($check_recent_totp_view_logged_sql['recent_totp_view']);
if ($recent_totp_view_logged_count == 0) {
// Logging
logAction("Credential", "View TOTP", "$session_name viewed credential TOTP code for $name", $client_id, $login_id);
logAction("Credential", "View TOTP", "$session_name viewed credential TOTP code for $name", $client_id, $credential_id);
}
}
@@ -444,10 +447,10 @@ if (isset($_POST['update_kanban_ticket'])) {
$config_base_url = sanitizeInput($config_base_url);
// Get Company Info
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone FROM companies WHERE company_id = 1");
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone, company_phone_country_code FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = sanitizeInput($row['company_name']);
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone']));
$company_phone = sanitizeInput(formatPhoneNumber($row['company_phone'], $row['company_phone_country_code']));
// EMAIL
$subject = "Ticket resolved - [$ticket_prefix$ticket_number] - $ticket_subject | (pending closure)";
@@ -586,17 +589,16 @@ if (isset($_POST['update_recurring_invoice_items_order'])) {
enforceUserPermission('module_sales', 2);
$positions = $_POST['positions'];
$recurring_id = intval($_POST['recurring_id']);
$recurring_invoice_id = intval($_POST['recurring_invoice_id']);
foreach ($positions as $position) {
$id = intval($position['id']);
$order = intval($position['order']);
mysqli_query($mysqli, "UPDATE invoice_items SET item_order = $order WHERE item_recurring_id = $recurring_id AND item_id = $id");
mysqli_query($mysqli, "UPDATE invoice_items SET item_order = $order WHERE item_recurring_invoice_id = $recurring_invoice_id AND item_id = $id");
}
// return a response
echo json_encode(['status' => 'success']);
exit;
}

View File

@@ -341,7 +341,7 @@ ob_start();
<option value="">- Select Vendor -</option>
<?php
$sql_vendors = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id AND vendor_template = 0 ORDER BY vendor_name ASC");
$sql_vendors = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_archived_at IS NULL AND vendor_client_id = $client_id ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);
@@ -364,6 +364,16 @@ ob_start();
</div>
<?php if ($asset_type !== 'Virtual Machine') { ?>
<div class="form-group">
<label>Purchase Reference</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
</div>
<input type="text" class="form-control" name="purchase_reference" placeholder="eg. Invoice, PO Number" >
</div>
</div>
<div class="form-group">
<label>Purchase Date</label>
<div class="input-group">

View File

@@ -24,8 +24,8 @@ $asset_make = nullable_htmlentities($row['asset_make']);
$asset_model = nullable_htmlentities($row['asset_model']);
$asset_serial = nullable_htmlentities($row['asset_serial']);
$asset_os = nullable_htmlentities($row['asset_os']);
$asset_uri = nullable_htmlentities($row['asset_uri']);
$asset_uri_2 = nullable_htmlentities($row['asset_uri_2']);
$asset_uri = sanitize_url($row['asset_uri']);
$asset_uri_2 = sanitize_url($row['asset_uri_2']);
$asset_status = nullable_htmlentities($row['asset_status']);
$asset_purchase_reference = nullable_htmlentities($row['asset_purchase_reference']);
$asset_purchase_date = nullable_htmlentities($row['asset_purchase_date']);
@@ -50,6 +50,7 @@ $device_icon = getAssetIcon($asset_type);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_phone = nullable_htmlentities($row['contact_phone']);
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = nullable_htmlentities($row['contact_mobile']);
$contact_archived_at = nullable_htmlentities($row['contact_archived_at']);
if ($contact_archived_at) {
@@ -111,46 +112,53 @@ $interface_count = mysqli_num_rows($sql_related_interfaces);
// Related Credentials Query
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS login_id,
logins.login_name,
logins.login_description,
logins.login_uri,
logins.login_username,
logins.login_password,
logins.login_otp_secret,
logins.login_note,
logins.login_important,
logins.login_contact_id,
logins.login_asset_id
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_asset_id = $asset_id
AND login_archived_at IS NULL
GROUP BY logins.login_id
ORDER BY login_name DESC
credentials.credential_id AS credential_id,
credentials.credential_name,
credentials.credential_description,
credentials.credential_uri,
credentials.credential_username,
credentials.credential_password,
credentials.credential_otp_secret,
credentials.credential_note,
credentials.credential_important,
credentials.credential_contact_id,
credentials.credential_asset_id
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
WHERE credential_asset_id = $asset_id
AND credential_archived_at IS NULL
GROUP BY credentials.credential_id
ORDER BY credential_name DESC
");
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Tickets Query
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
LEFT JOIN users on ticket_assigned_to = user_id
$sql_related_tickets = mysqli_query($mysqli, "
SELECT tickets.*, users.*, ticket_statuses.*
FROM tickets
LEFT JOIN users ON ticket_assigned_to = user_id
LEFT JOIN ticket_statuses ON ticket_status_id = ticket_status
WHERE ticket_asset_id = $asset_id
ORDER BY ticket_number DESC"
);
LEFT JOIN ticket_assets ON tickets.ticket_id = ticket_assets.ticket_id
WHERE ticket_asset_id = $asset_id OR ticket_assets.asset_id = $asset_id
GROUP BY tickets.ticket_id
ORDER BY ticket_number DESC
");
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_asset_id = $asset_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
GROUP BY recurring_tickets.recurring_ticket_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
// Related Documents
$sql_related_documents = mysqli_query($mysqli, "SELECT * FROM asset_documents
LEFT JOIN documents ON asset_documents.document_id = documents.document_id
LEFT JOIN users ON user_id = document_created_by
WHERE asset_documents.asset_id = $asset_id
AND document_archived_at IS NULL
ORDER BY document_name DESC"
@@ -254,25 +262,25 @@ ob_start();
</div>
<div class="card-body">
<?php if ($asset_type) { ?>
<div><i class="fa fa-fw fa-tag text-secondary mr-3"></i><?php echo $asset_type; ?></div>
<div><i class="fa fa-fw fa-tag text-secondary mr-2"></i><?php echo $asset_type; ?></div>
<?php }
if ($asset_make) { ?>
<div class="mt-2"><i class="fa fa-fw fa-circle text-secondary mr-3"></i><?php echo "$asset_make $asset_model"; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-circle text-secondary mr-2"></i><?php echo "$asset_make $asset_model"; ?></div>
<?php }
if ($asset_os) { ?>
<div class="mt-2"><i class="fab fa-fw fa-windows text-secondary mr-3"></i><?php echo "$asset_os"; ?></div>
<div class="mt-2"><i class="fab fa-fw fa-windows text-secondary mr-2"></i><?php echo "$asset_os"; ?></div>
<?php }
if ($asset_serial) { ?>
<div class="mt-2"><i class="fa fa-fw fa-barcode text-secondary mr-3"></i><?php echo $asset_serial; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-barcode text-secondary mr-2"></i><?php echo $asset_serial; ?></div>
<?php }
if ($asset_purchase_date) { ?>
<div class="mt-2"><i class="fa fa-fw fa-shopping-cart text-secondary mr-3"></i><?php echo date('Y-m-d', strtotime($asset_purchase_date)); ?></div>
<div class="mt-2"><i class="fa fa-fw fa-shopping-cart text-secondary mr-2"></i><?php echo date('Y-m-d', strtotime($asset_purchase_date)); ?></div>
<?php }
if ($asset_install_date) { ?>
<div class="mt-2"><i class="fa fa-fw fa-calendar-check text-secondary mr-3"></i><?php echo date('Y-m-d', strtotime($asset_install_date)); ?></div>
<div class="mt-2"><i class="fa fa-fw fa-calendar-check text-secondary mr-2"></i><?php echo date('Y-m-d', strtotime($asset_install_date)); ?></div>
<?php }
if ($asset_warranty_expire) { ?>
<div class="mt-2"><i class="fa fa-fw fa-exclamation-triangle text-secondary mr-3"></i><?php echo date('Y-m-d', strtotime($asset_warranty_expire)); ?></div>
<div class="mt-2"><i class="fa fa-fw fa-exclamation-triangle text-secondary mr-2"></i><?php echo date('Y-m-d', strtotime($asset_warranty_expire)); ?></div>
<?php } ?>
</div>
</div>
@@ -283,19 +291,19 @@ ob_start();
</div>
<div class="card-body">
<?php if ($asset_ip) { ?>
<div><i class="fa fa-fw fa-globe text-secondary mr-3"></i><?php echo $asset_ip; ?></div>
<div><i class="fa fa-fw fa-globe text-secondary mr-2"></i><?php echo $asset_ip; ?></div>
<?php } ?>
<?php if ($asset_nat_ip) { ?>
<div class="mt-2"><i class="fa fa-fw fa-random text-secondary mr-3"></i><?php echo $asset_nat_ip; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-random text-secondary mr-2"></i><?php echo $asset_nat_ip; ?></div>
<?php }
if ($asset_mac) { ?>
<div class="mt-2"><i class="fa fa-fw fa-ethernet text-secondary mr-3"></i><?php echo $asset_mac; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-ethernet text-secondary mr-2"></i><?php echo $asset_mac; ?></div>
<?php }
if ($asset_uri) { ?>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-3"></i><a href="<?php echo $asset_uri; ?>" target="_blank">Link</a></div>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-2"></i><a href="<?php echo $asset_uri; ?>" target="_blank" title="<?php echo $asset_uri; ?>"><?php echo truncate($asset_uri, 20); ?></a></div>
<?php }
if ($asset_uri_2) { ?>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-3"></i><a href="<?php echo $asset_uri_2; ?>" target="_blank">Link 2</a></div>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-2"></i><a href="<?php echo $asset_uri_2; ?>" target="_blank" title="<?php echo $asset_uri_2; ?>"><?php echo truncate($asset_uri_2, 20); ?></a></div>
<?php } ?>
</div>
</div>
@@ -307,19 +315,19 @@ ob_start();
</div>
<div class="card-body">
<?php if ($location_name) { ?>
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-3"></i><?php echo $location_name_display; ?></div>
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-2"></i><?php echo $location_name_display; ?></div>
<?php }
if ($contact_name) { ?>
<div class="mt-2"><i class="fa fa-fw fa-user text-secondary mr-3"></i><?php echo $contact_name_display; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-user text-secondary mr-2"></i><?php echo $contact_name_display; ?></div>
<?php }
if ($contact_email) { ?>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-3"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<?php }
if ($contact_phone) { ?>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-3"></i><?php echo formatPhoneNumber($contact_phone); echo " $contact_extension"; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-2"></i><?php echo formatPhoneNumber($contact_phone); echo " $contact_extension"; ?></div>
<?php }
if ($contact_mobile) { ?>
<div class="mt-2"><i class="fa fa-fw fa-mobile-alt text-secondary mr-3"></i><?php echo formatPhoneNumber($contact_mobile); ?></div>
<div class="mt-2"><i class="fa fa-fw fa-mobile-alt text-secondary mr-2"></i><?php echo formatPhoneNumber($contact_mobile); ?></div>
<?php } ?>
</div>
@@ -446,68 +454,69 @@ ob_start();
<?php
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri";
$credential_uri_display = "$credential_uri";
}
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username";
$credential_username_display = "$credential_username <button type='button' class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
<td>
<i class="fa fa-fw fa-key text-secondary"></i>
<?php echo $login_name; ?>
<?php echo $credential_name; ?>
</td>
<td><?php echo $login_username_display; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button type='button' class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $credential_password; ?>'><i class='far fa-copy text-secondary'></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
</tr>
<?php
@@ -520,7 +529,7 @@ ob_start();
</table>
</div>
</div>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the credentials ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php } ?>
@@ -547,12 +556,13 @@ ob_start();
$ticket_number = intval($row['ticket_number']);
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
$ticket_status_id = intval($row['ticket_status_id']);
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
$ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
if (empty($ticket_updated_at)) {
if ($ticket_status == "Closed") {
if ($ticket_status_name == "Closed") {
$ticket_updated_at_display = "<p>Never</p>";
} else {
$ticket_updated_at_display = "<p class='text-danger'>Never</p>";
@@ -573,7 +583,7 @@ ob_start();
}
$ticket_assigned_to = intval($row['ticket_assigned_to']);
if (empty($ticket_assigned_to)) {
if ($ticket_status == 5) {
if ($ticket_status_id == 5) {
$ticket_assigned_to_display = "<p>Not Assigned</p>";
} else {
$ticket_assigned_to_display = "<p class='text-danger'>Not Assigned</p>";
@@ -628,18 +638,18 @@ ob_start();
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
<td class="text-bold"><?php echo $scheduled_ticket_subject ?></td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td class="text-bold"><?php echo $recurring_ticket_subject ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
</tr>
<?php } ?>
@@ -679,11 +689,6 @@ ob_start();
$seat_count = 0;
// Get Login
$login_id = intval($row['login_id']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
// Asset Licenses
$asset_licenses_sql = mysqli_query($mysqli, "SELECT asset_id FROM software_assets WHERE software_id = $software_id");
$asset_licenses_array = array();
@@ -848,7 +853,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<a href="asset_details.php?<?php echo $client_url; ?>asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
<a href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>" class="btn btn-primary text-bold"><span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span></a>
<a href="#" class="btn btn-secondary"
data-toggle="ajax-modal" data-ajax-url="ajax/ajax_asset_edit.php" data-ajax-id="<?php echo $asset_id; ?>">
<span class="text-white"><i class="fas fa-edit mr-2"></i>Edit</span>

View File

@@ -0,0 +1,69 @@
<?php
require_once '../includes/ajax_header.php';
$asset_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets
WHERE asset_id = $asset_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$asset_name = nullable_htmlentities($row['asset_name']);
$client_id = intval($row['asset_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<select class="form-control select2" name="credential_id">
<option value="">- Select a Credential -</option>
<?php
$sql_credentials_select = mysqli_query($mysqli, "
SELECT credentials.credential_id, credentials.credential_name
FROM credentials
LEFT JOIN assets ON credentials.credential_asset_id = assets.asset_id
AND credentials.credential_asset_id = $asset_id
WHERE credentials.credential_client_id = $client_id
AND credentials.credential_asset_id = 0
AND credentials.credential_archived_at IS NULL
ORDER BY credentials.credential_name ASC
");
while ($row = mysqli_fetch_array($sql_credentials_select)) {
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
?>
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_asset_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -0,0 +1,70 @@
<?php
require_once '../includes/ajax_header.php';
$asset_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets
WHERE asset_id = $asset_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$asset_name = nullable_htmlentities($row['asset_name']);
$client_id = intval($row['asset_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
</div>
<select class="form-control select2" name="document_id">
<option value="">- Select a Document -</option>
<?php
$sql_documents_select = mysqli_query($mysqli, "
SELECT documents.document_id, documents.document_name
FROM documents
LEFT JOIN asset_documents
ON documents.document_id = asset_documents.document_id
AND asset_documents.asset_id = $asset_id
WHERE documents.document_client_id = $client_id
AND documents.document_archived_at IS NULL
AND asset_documents.asset_id IS NULL
ORDER BY documents.document_name ASC
");
while ($row = mysqli_fetch_array($sql_documents_select)) {
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
?>
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_asset_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -0,0 +1,73 @@
<?php
require_once '../includes/ajax_header.php';
$asset_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets
WHERE asset_id = $asset_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$asset_name = nullable_htmlentities($row['asset_name']);
$client_id = intval($row['asset_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
</div>
<select class="form-control select2" name="file_id">
<option value="">- Select a File -</option>
<?php
$sql_files_select = mysqli_query($mysqli, "
SELECT files.file_id, files.file_name, folders.folder_name
FROM files
LEFT JOIN asset_files
ON files.file_id = asset_files.file_id
AND asset_files.asset_id = $asset_id
LEFT JOIN folders
ON folders.folder_id = files.file_folder_id
WHERE files.file_client_id = $client_id
AND asset_files.asset_id IS NULL
ORDER BY folders.folder_name ASC, files.file_name ASC
");
while ($row = mysqli_fetch_array($sql_files_select)) {
$file_id = intval($row['file_id']);
$file_name = nullable_htmlentities($row['file_name']);
$folder_name = nullable_htmlentities($row['folder_name']);
?>
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_asset_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -0,0 +1,68 @@
<?php
require_once '../includes/ajax_header.php';
$asset_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets
WHERE asset_id = $asset_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$asset_name = nullable_htmlentities($row['asset_name']);
$client_id = intval($row['asset_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
</div>
<select class="form-control select2" name="service_id">
<option value="">- Select a Service -</option>
<?php
$sql_services_select = mysqli_query($mysqli, "
SELECT services.service_id, services.service_name
FROM services
LEFT JOIN service_assets
ON services.service_id = service_assets.service_id
AND service_assets.asset_id = $asset_id
WHERE services.service_client_id = $client_id
AND service_assets.asset_id IS NULL
ORDER BY services.service_name ASC
");
while ($row = mysqli_fetch_array($sql_services_select)) {
$service_id = intval($row['service_id']);
$service_name = nullable_htmlentities($row['service_name']);
?>
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_service_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -0,0 +1,73 @@
<?php
require_once '../includes/ajax_header.php';
$asset_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets
WHERE asset_id = $asset_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$asset_name = nullable_htmlentities($row['asset_name']);
$client_id = intval($row['asset_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $asset_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="asset_id" value="<?php echo $asset_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
</div>
<select class="form-control select2" name="software_id">
<option value="">- Select a Device Software License -</option>
<?php
$sql_software_select = mysqli_query($mysqli, "
SELECT software.software_id, software.software_name
FROM software
LEFT JOIN software_assets
ON software.software_id = software_assets.software_id
AND software_assets.asset_id = $asset_id
WHERE software.software_client_id = $client_id
AND software.software_archived_at IS NULL
AND software.software_license_type = 'Device'
AND software_assets.asset_id IS NULL
ORDER BY software.software_name ASC
");
while ($row = mysqli_fetch_array($sql_software_select)) {
$software_id = intval($row['software_id']);
$software_name = nullable_htmlentities($row['software_name']);
?>
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_software_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -4,7 +4,7 @@ require_once '../includes/ajax_header.php';
$event_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id WHERE event_id = $event_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id WHERE event_id = $event_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$event_title = nullable_htmlentities($row['event_title']);

View File

@@ -13,10 +13,13 @@ $certificate_domain = nullable_htmlentities($row['certificate_domain']);
$certificate_domain_id = intval($row['certificate_domain_id']);
$certificate_issued_by = nullable_htmlentities($row['certificate_issued_by']);
$certificate_public_key = nullable_htmlentities($row['certificate_public_key']);
$certificate_notes = nullable_htmlentities($row['certificate_notes']);
$certificate_expire = nullable_htmlentities($row['certificate_expire']);
$certificate_created_at = nullable_htmlentities($row['certificate_created_at']);
$client_id = intval($row['certificate_client_id']);
$history_sql = mysqli_query($mysqli, "SELECT * FROM certificate_history WHERE certificate_history_certificate_id = $certificate_id");
// Generate the HTML form content using output buffering.
ob_start();
?>
@@ -42,6 +45,9 @@ ob_start();
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pillsEditNotes<?php echo $certificate_id; ?>">Notes</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pillsEditHistory<?php echo $certificate_id; ?>">History</a>
</li>
</ul>
<hr>
@@ -141,11 +147,40 @@ ob_start();
</div>
<div class="tab-pane fade" id="pillsEditNotes<?php echo $certificate_id; ?>">
<div class="form-group">
<textarea class="form-control" name="notes" rows="12" placeholder="Enter some notes"><?php echo $certificate_notes; ?></textarea>
</div>
</div>
<div class="tab-pane fade" id="pillsEditHistory<?php echo $certificate_id; ?>">
<div class="table-responsive">
<table class='table table-sm table-striped border table-hover'>
<thead class='thead-dark'>
<tr>
<th>Date</th>
<th>Field</th>
<th>Before</th>
<th>After</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($history_sql)) {
$certificate_modified_at = nullable_htmlentities($row['certificate_history_modified_at']);
$certificate_field = nullable_htmlentities($row['certificate_history_column']);
$certificate_before_value = nullable_htmlentities($row['certificate_history_old_value']);
$certificate_after_value = nullable_htmlentities($row['certificate_history_new_value']);
?>
<tr>
<td><?php echo $certificate_modified_at; ?></td>
<td><?php echo $certificate_field; ?></td>
<td><?php echo $certificate_before_value; ?></td>
<td><?php echo $certificate_after_value; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>

View File

@@ -251,9 +251,7 @@ ob_start();
<div class="tab-pane fade" id="pills-client-notes<?php echo $client_id; ?>">
<div class="form-group">
<textarea class="form-control" rows="10" placeholder="Enter some notes"
name="notes"><?php echo $client_notes; ?>
</textarea>
<textarea class="form-control" rows="10" placeholder="Enter some notes" name="notes"><?php echo $client_notes; ?></textarea>
</div>
</div>

View File

@@ -9,7 +9,7 @@ $sql = mysqli_query($mysqli, "SELECT * FROM contacts
LEFT JOIN locations ON location_id = contact_location_id
LEFT JOIN users ON user_id = contact_user_id
WHERE contact_id = $contact_id
$client_query
LIMIT 1
");
$row = mysqli_fetch_array($sql);
@@ -18,9 +18,11 @@ $client_name = nullable_htmlentities($row['client_name']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_department =nullable_htmlentities($row['contact_department']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
$contact_pin = nullable_htmlentities($row['contact_pin']);
@@ -51,21 +53,21 @@ $software_count = mysqli_num_rows($sql_linked_software);
$linked_software = array();
// Related Logins Query 1 to 1 relationship
$sql_related_logins = mysqli_query($mysqli, "
// Related Credentials Query 1 to 1 relationship
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS logins_login_id, -- Alias for logins.login_id
logins.*, -- All other columns from logins
login_tags.*, -- All columns from login_tags
credentials.credential_id AS credentials_credential_id, -- Alias for credentials.credential_id
credentials.*, -- All other columns from credentials
credential_tags.*, -- All columns from credential_tags
tags.* -- All columns from tags
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_contact_id = $contact_id
GROUP BY logins.login_id
ORDER BY login_name DESC
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_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
");
$credential_count = mysqli_num_rows($sql_related_logins);
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Tickets Query - 1 to 1 relationship
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
@@ -75,9 +77,9 @@ $sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_contact_id = $contact_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM recurring_tickets
WHERE recurring_ticket_contact_id = $contact_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
@@ -114,7 +116,7 @@ $sql_linked_services = mysqli_query($mysqli, "SELECT * FROM service_contacts, se
AND service_contacts.service_id = services.service_id
ORDER BY service_name ASC"
);
$service_count = mysqli_num_rows($sql_linked_services);
$services_count = mysqli_num_rows($sql_linked_services);
$linked_services = array();
@@ -123,7 +125,6 @@ $sql_linked_documents = mysqli_query($mysqli, "SELECT * FROM contact_documents,
LEFT JOIN users ON document_created_by = user_id
WHERE contact_documents.contact_id = $contact_id
AND contact_documents.document_id = documents.document_id
AND document_template = 0
AND document_archived_at IS NULL
ORDER BY document_name ASC"
);
@@ -189,11 +190,6 @@ ob_start();
<a class="nav-link" data-toggle="pill" href="#pills-contact-recurring-tickets<?php echo $contact_id; ?>"><i class="fas fa-fw fa-redo-alt fa-2x"></i><br>Rcr Tickets (<?php echo $recurring_ticket_count; ?>)</a>
</li>
<?php } ?>
<?php if ($services_count) { ?>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-services<?php echo $contact_id; ?>"><i class="fas fa-fw fa-stream fa-2x"></i><br>Services (<?php echo $services_count; ?>)</a>
</li>
<?php } ?>
<?php if ($document_count) { ?>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact-documents<?php echo $contact_id; ?>"><i class="fas fa-fw fa-file-alt fa-2x"></i><br>Documents (<?php echo $document_count; ?>)</a>
@@ -244,7 +240,7 @@ ob_start();
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-2"></i><?php echo $location_name; ?></div>
<?php }
if ($contact_email) { ?>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<?php }
if ($contact_phone) { ?>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-2"></i><a href="tel:<?php echo "$contact_phone"?>"><?php echo $contact_phone; ?></a></div>
@@ -404,7 +400,7 @@ ob_start();
<?php if ($credential_count) { ?>
<div class="tab-pane fade" id="pills-contact-credentials<?php echo $contact_id; ?>">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover table-sm">
<table class="table table-striped table-borderless table-hover table-sm dataTables" style="width:100%">
<thead>
<tr>
<th>Name</th>
@@ -418,68 +414,70 @@ ob_start();
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_related_logins)) {
$login_id = intval($row['logins_login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$credential_id = intval($row['credentials_credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri";
$credential_uri_display = "$credential_uri";
}
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username";
$credential_username_display = "$credential_username <button type='button' class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
<td><i class="fa fa-fw fa-key text-secondary mr-2"></i><?php echo $login_name; ?></td>
<td><?php echo $login_description; ?></td>
<td><?php echo $login_username_display; ?></td>
<td><i class="fa fa-fw fa-key text-secondary mr-2"></i><?php echo $credential_name; ?></td>
<td><?php echo $credential_description; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button>
<button type="button" class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $credential_password; ?>'><i class='far fa-copy text-secondary'></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
</tr>
<?php
@@ -492,7 +490,7 @@ ob_start();
</table>
</div>
</div>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the credential ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php } ?>
@@ -597,18 +595,18 @@ ob_start();
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
<td class="text-bold"><?php echo $scheduled_ticket_subject ?></td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td class="text-bold"><?php echo $recurring_ticket_subject ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
</tr>
<?php } ?>
@@ -846,7 +844,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<a href="contact_details.php?<?php echo $client_url; ?>contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
<a href="contact_details.php?client_id=<?php echo $client_id; ?>&contact_id=<?php echo $contact_id; ?>" class="btn btn-primary text-bold">
<span class="text-white"><i class="fas fa-info-circle mr-2"></i>More Details</span>
</a>
<a href="#" class="btn btn-secondary"

View File

@@ -16,8 +16,10 @@ $contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
$contact_department = nullable_htmlentities($row['contact_department']);
$contact_extension = nullable_htmlentities($row['contact_extension']);
$contact_phone = formatPhoneNumber($row['contact_phone']);
$contact_mobile = formatPhoneNumber($row['contact_mobile']);
$contact_phone_country_code = nullable_htmlentities($row['contact_phone_country_code']);
$contact_phone = nullable_htmlentities(formatPhoneNumber($row['contact_phone'], $contact_phone_country_code));
$contact_mobile_country_code = nullable_htmlentities($row['contact_mobile_country_code']);
$contact_mobile = nullable_htmlentities(formatPhoneNumber($row['contact_mobile'], $contact_mobile_country_code));
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_pin = nullable_htmlentities($row['contact_pin']);
$contact_photo = nullable_htmlentities($row['contact_photo']);
@@ -111,30 +113,38 @@ ob_start();
</div>
</div>
<label>Phone</label>
<label>Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-8">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $contact_phone; ?>">
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo "$contact_phone_country_code"; ?>" placeholder="+" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $contact_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-4">
<input type="text" class="form-control" name="extension" placeholder="Extension" maxlength="200" value="<?php echo $contact_extension; ?>">
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="extension" value="<?php echo $contact_extension; ?>" placeholder="ext." maxlength="200">
</div>
</div>
</div>
<div class="form-group">
<label>Mobile</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-mobile-alt"></i></span>
<label>Mobile</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-mobile-alt"></i></span>
</div>
<input type="tel" class="form-control col-2" name="mobile_country_code" value="<?php echo "$contact_mobile_country_code"; ?>" placeholder="+" maxlength="4">
<input type="tel" class="form-control" name="mobile" value="<?php echo $contact_mobile; ?>" placeholder="Phone Number">
</div>
</div>
<input type="text" class="form-control" name="mobile" placeholder="Mobile Phone Number" maxlength="200" value="<?php echo $contact_mobile; ?>">
</div>
</div>

View File

@@ -0,0 +1,67 @@
<?php
require_once '../includes/ajax_header.php';
$contact_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
WHERE contact_id = $contact_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$contact_name = nullable_htmlentities($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-desktop mr-2"></i>Link Asset to <strong><?php echo $contact_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
</div>
<select class="form-control select2" name="asset_id">
<option value="">- Select an Asset -</option>
<?php
$sql_assets_select = mysqli_query($mysqli, "
SELECT asset_id, asset_name
FROM assets
WHERE asset_client_id = $client_id
AND asset_contact_id = 0
AND asset_archived_at IS NULL
ORDER BY asset_name ASC
");
while ($row = mysqli_fetch_array($sql_assets_select)) {
$asset_id = intval($row['asset_id']);
$asset_name = nullable_htmlentities($row['asset_name']);
?>
<option value="<?php echo $asset_id ?>"><?php echo $asset_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_contact_to_asset" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -0,0 +1,67 @@
<?php
require_once '../includes/ajax_header.php';
$contact_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
WHERE contact_id = $contact_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$contact_name = nullable_htmlentities($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-key mr-2"></i>Link Credential to <strong><?php echo $contact_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<select class="form-control select2" name="credential_id">
<option value="">- Select a Credential -</option>
<?php
$sql_credentials_select = mysqli_query($mysqli, "
SELECT credential_id, credential_name
FROM credentials
WHERE credential_client_id = $client_id
AND credential_contact_id = 0
AND credential_archived_at IS NULL
ORDER BY credential_name ASC
");
while ($row = mysqli_fetch_array($sql_credentials_select)) {
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
?>
<option value="<?php echo $credential_id ?>"><?php echo $credential_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_contact_to_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -0,0 +1,70 @@
<?php
require_once '../includes/ajax_header.php';
$contact_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
WHERE contact_id = $contact_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$contact_name = nullable_htmlentities($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-folder mr-2"></i>Link Document to <strong><?php echo $contact_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-folder"></i></span>
</div>
<select class="form-control select2" name="document_id">
<option value="">- Select a Document -</option>
<?php
$sql_documents_select = mysqli_query($mysqli, "
SELECT documents.document_id, documents.document_name
FROM documents
LEFT JOIN contact_documents
ON documents.document_id = contact_documents.document_id
AND contact_documents.contact_id = $contact_id
WHERE documents.document_client_id = $client_id
AND documents.document_archived_at IS NULL
AND contact_documents.contact_id IS NULL
ORDER BY documents.document_name ASC
");
while ($row = mysqli_fetch_array($sql_documents_select)) {
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
?>
<option value="<?php echo $document_id ?>"><?php echo $document_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_contact_to_document" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -0,0 +1,72 @@
<?php
require_once '../includes/ajax_header.php';
$contact_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
WHERE contact_id = $contact_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$contact_name = nullable_htmlentities($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-paperclip mr-2"></i>Link File to <strong><?php echo $contact_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-paperclip"></i></span>
</div>
<select class="form-control select2" name="file_id">
<option value="">- Select a File -</option>
<?php
$sql_files_select = mysqli_query($mysqli, "
SELECT files.file_id, files.file_name, folders.folder_name
FROM files
LEFT JOIN contact_files
ON files.file_id = contact_files.file_id
AND contact_files.contact_id = $contact_id
LEFT JOIN folders
ON folders.folder_id = files.file_folder_id
WHERE files.file_client_id = $client_id
AND contact_files.contact_id IS NULL
ORDER BY folders.folder_name ASC, files.file_name ASC
");
while ($row = mysqli_fetch_array($sql_files_select)) {
$file_id = intval($row['file_id']);
$file_name = nullable_htmlentities($row['file_name']);
$folder_name = nullable_htmlentities($row['folder_name']);
?>
<option value="<?php echo $file_id ?>"><?php echo "$folder_name/$file_name"; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_contact_to_file" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -0,0 +1,68 @@
<?php
require_once '../includes/ajax_header.php';
$contact_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
WHERE contact_id = $contact_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$contact_name = nullable_htmlentities($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-stream mr-2"></i>Link Service to <strong><?php echo $contact_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-stream"></i></span>
</div>
<select class="form-control select2" name="service_id">
<option value="">- Select a Service -</option>
<?php
$sql_services_select = mysqli_query($mysqli, "
SELECT services.service_id, services.service_name
FROM services
LEFT JOIN service_contacts
ON services.service_id = service_contacts.service_id
AND service_contacts.contact_id = $contact_id
WHERE services.service_client_id = $client_id
AND service_contacts.contact_id IS NULL
ORDER BY services.service_name ASC
");
while ($row = mysqli_fetch_array($sql_services_select)) {
$service_id = intval($row['service_id']);
$service_name = nullable_htmlentities($row['service_name']);
?>
<option value="<?php echo $service_id ?>"><?php echo $service_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_service_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -0,0 +1,71 @@
<?php
require_once '../includes/ajax_header.php';
$contact_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
WHERE contact_id = $contact_id
LIMIT 1
");
$row = mysqli_fetch_array($sql);
$contact_name = nullable_htmlentities($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-cube mr-2"></i>License Software to <strong><?php echo $contact_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="contact_id" value="<?php echo $contact_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-cube"></i></span>
</div>
<select class="form-control select2" name="software_id">
<option value="">- Select a User Software License -</option>
<?php
$sql_software_select = mysqli_query($mysqli, "
SELECT software.software_id, software.software_name
FROM software
LEFT JOIN software_contacts
ON software.software_id = software_contacts.software_id
AND software_contacts.contact_id = $contact_id
WHERE software.software_client_id = $client_id
AND software.software_archived_at IS NULL
AND software.software_license_type = 'User'
AND software_contacts.contact_id IS NULL
ORDER BY software.software_name ASC
");
while ($row = mysqli_fetch_array($sql_software_select)) {
$software_id = intval($row['software_id']);
$software_name = nullable_htmlentities($row['software_name']);
?>
<option value="<?php echo $software_id ?>"><?php echo $software_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="link_software_to_contact" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Link</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -2,33 +2,34 @@
require_once '../includes/ajax_header.php';
$login_id = intval($_GET['id']);
$credential_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = $login_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = $credential_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['login_client_id']);
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_note = nullable_htmlentities($row['login_note']);
$login_created_at = nullable_htmlentities($row['login_created_at']);
$login_archived_at = nullable_htmlentities($row['login_archived_at']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$client_id = intval($row['credential_client_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_uri_link = sanitize_url($row['credential_uri']);
$credential_uri_2_link = sanitize_url($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_created_at = nullable_htmlentities($row['credential_created_at']);
$credential_archived_at = nullable_htmlentities($row['credential_archived_at']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT tag_id FROM login_tags WHERE login_id = $login_id");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_id_array[] = $login_tag_id;
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT tag_id FROM credential_tags WHERE credential_id = $credential_id");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$credential_tag_id = intval($row['tag_id']);
$credential_tag_id_array[] = $credential_tag_id;
}
// Generate the HTML form content using output buffering.
@@ -36,26 +37,26 @@ ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class='fas fa-fw fa-key mr-2'></i>Editing credential: <strong><?php echo $login_name; ?></strong></h5>
<h5 class="modal-title"><i class='fas fa-fw fa-key mr-2'></i>Editing credential: <strong><?php echo $credential_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="login_id" value="<?php echo $login_id; ?>">
<input type="hidden" name="credential_id" value="<?php echo $credential_id; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<div class="modal-body bg-white">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-login-details<?php echo $login_id; ?>">Details</a>
<a class="nav-link active" data-toggle="pill" href="#pills-credential-details<?php echo $credential_id; ?>">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-login-relation<?php echo $login_id; ?>">Relation</a>
<a class="nav-link" data-toggle="pill" href="#pills-credential-relation<?php echo $credential_id; ?>">Relation</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-login-notes<?php echo $login_id; ?>">Notes</a>
<a class="nav-link" data-toggle="pill" href="#pills-credential-notes<?php echo $credential_id; ?>">Notes</a>
</li>
</ul>
@@ -63,7 +64,7 @@ ob_start();
<div class="tab-content" <?php if (lookupUserPermission('module_credential') <= 1) { echo 'inert'; } ?>>
<div class="tab-pane fade show active" id="pills-login-details<?php echo $login_id; ?>">
<div class="tab-pane fade show active" id="pills-credential-details<?php echo $credential_id; ?>">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong> / <span class="text-secondary">Important?</span></label>
@@ -71,10 +72,10 @@ ob_start();
<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="name" placeholder="Name of Login" maxlength="200" value="<?php echo $login_name; ?>" required>
<input type="text" class="form-control" name="name" placeholder="Name of Credential" maxlength="200" value="<?php echo $credential_name; ?>" required>
<div class="input-group-append">
<div class="input-group-text">
<input type="checkbox" name="important" value="1" <?php if ($login_important == 1) { echo "checked"; } ?>>
<input type="checkbox" name="important" value="1" <?php if ($credential_important == 1) { echo "checked"; } ?>>
</div>
</div>
</div>
@@ -86,7 +87,7 @@ ob_start();
<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 $login_description; ?>">
<input type="text" class="form-control" name="description" placeholder="Description" value="<?php echo $credential_description; ?>">
</div>
</div>
@@ -96,7 +97,7 @@ ob_start();
<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="username" placeholder="Username or ID" maxlength="350" value="<?php echo $login_username; ?>">
<input type="text" class="form-control" name="username" placeholder="Username or ID" maxlength="350" value="<?php echo $credential_username; ?>">
</div>
</div>
@@ -106,12 +107,12 @@ 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="password" placeholder="Password or Key" maxlength="350" value="<?php echo $login_password; ?>" required autocomplete="new-password">
<input type="password" class="form-control" data-toggle="password" name="password" placeholder="Password or Key" maxlength="350" value="<?php echo $credential_password; ?>" required 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">
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $login_password; ?>"><i class="fa fa-fw fa-copy"></i></button>
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $credential_password; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
@@ -122,7 +123,7 @@ ob_start();
<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="otp_secret" maxlength="200" value="<?php echo $login_otp_secret; ?>" placeholder="Insert secret key">
<input type="password" class="form-control" data-toggle="password" name="otp_secret" maxlength="200" value="<?php echo $credential_otp_secret; ?>" placeholder="Insert secret key">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
@@ -135,13 +136,13 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-link"></i></span>
</div>
<input type="text" class="form-control" name="uri" placeholder="ex. http://192.168.1.1" maxlength="500" value="<?php echo $login_uri; ?>">
<input type="text" class="form-control" name="uri" placeholder="ex. http://192.168.1.1" maxlength="500" value="<?php echo $credential_uri; ?>">
<div class="input-group-append">
<a href="<?php echo $login_uri; ?>" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
<a href="<?php echo $credential_uri_link; ?>" target="_blank" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
</div>
<div class="input-group-append">
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $login_uri; ?>"><i class="fa fa-fw fa-copy"></i></button>
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $credential_uri; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
@@ -152,19 +153,19 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-link"></i></span>
</div>
<input type="text" class="form-control" name="uri_2" placeholder="ex. https://server.company.com:5001" maxlength="500" value="<?php echo $login_uri_2; ?>">
<input type="text" class="form-control" name="uri_2" placeholder="ex. https://server.company.com:5001" maxlength="500" value="<?php echo $credential_uri_2; ?>">
<div class="input-group-append">
<a href="<?php echo $login_uri_2; ?>" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
<a href="<?php echo $credential_uri_2_link; ?>" target="_blank" class="input-group-text"><i class="fa fa-fw fa-link"></i></a>
</div>
<div class="input-group-append">
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $login_uri_2; ?>"><i class="fa fa-fw fa-copy"></i></button>
<button class="input-group-text clipboardjs" type="button" data-clipboard-text="<?php echo $credential_uri_2; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-login-relation<?php echo $login_id; ?>">
<div class="tab-pane fade" id="pills-credential-relation<?php echo $credential_id; ?>">
<div class="form-group">
<label>Contact</label>
@@ -173,7 +174,7 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<select class="form-control select2" name="contact">
<option value="">- Contact -</option>
<option value="">- Select Contact -</option>
<?php
$sql_contacts = mysqli_query($mysqli, "SELECT contact_id, contact_name FROM contacts WHERE contact_client_id = $client_id ORDER BY contact_name ASC");
@@ -181,7 +182,7 @@ ob_start();
$contact_id_select = intval($row['contact_id']);
$contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option <?php if ($login_contact_id == $contact_id_select) { echo "selected"; } ?> value="<?php echo $contact_id_select; ?>"><?php echo $contact_name_select; ?></option>
<option <?php if ($credential_contact_id == $contact_id_select) { echo "selected"; } ?> value="<?php echo $contact_id_select; ?>"><?php echo $contact_name_select; ?></option>
<?php } ?>
</select>
</div>
@@ -194,7 +195,7 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<select class="form-control select2" name="asset">
<option value="0">- None -</option>
<option value="0">- Select Asset -</option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, location_name FROM assets LEFT JOIN locations on asset_location_id = location_id WHERE asset_client_id = $client_id AND asset_archived_at IS NULL ORDER BY asset_name ASC");
@@ -209,7 +210,7 @@ ob_start();
}
?>
<option <?php if ($login_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo $asset_select_display_string; ?></option>
<option <?php if ($credential_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo $asset_select_display_string; ?></option>
<?php } ?>
</select>
@@ -218,10 +219,10 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-login-notes<?php echo $login_id; ?>">
<div class="tab-pane fade" id="pills-credential-notes<?php echo $credential_id; ?>">
<div class="form-group">
<textarea class="form-control" rows="12" placeholder="Enter some notes" name="note"><?php echo $login_note; ?></textarea>
<textarea class="form-control" rows="12" placeholder="Enter some notes" name="note"><?php echo $credential_note; ?></textarea>
</div>
<div class="form-group">
@@ -238,7 +239,7 @@ ob_start();
$tag_id_select = intval($row['tag_id']);
$tag_name_select = nullable_htmlentities($row['tag_name']);
?>
<option value="<?php echo $tag_id_select; ?>" <?php if (in_array($tag_id_select, $login_tag_id_array)) { echo "selected"; } ?>><?php echo $tag_name_select; ?></option>
<option value="<?php echo $tag_id_select; ?>" <?php if (in_array($tag_id_select, $credential_tag_id_array)) { echo "selected"; } ?>><?php echo $tag_name_select; ?></option>
<?php } ?>
</select>
@@ -259,7 +260,7 @@ ob_start();
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_login" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="submit" name="edit_credential" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>

View File

@@ -2,26 +2,26 @@
require_once '../includes/ajax_header.php';
$login_id = intval($_GET['id']);
$credential_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = $login_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = $credential_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
$login_uri_2 = nullable_htmlentities($row['login_uri_2']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
$credential_uri_2 = nullable_htmlentities($row['credential_uri_2']);
$credential_username = nullable_htmlentities(decryptLoginEntry($row['credential_username']));
$credential_password = nullable_htmlentities(decryptLoginEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_created_at = nullable_htmlentities($row['login_created_at']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_created_at = nullable_htmlentities($row['credential_created_at']);
// Generate the HTML form content using output buffering.
ob_start();

View File

@@ -8,6 +8,7 @@ $sql = mysqli_query($mysqli, "SELECT * FROM ticket_statuses WHERE ticket_status_
$row = mysqli_fetch_array($sql);
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
$ticket_status_order = intval($row['ticket_status_order']);
$ticket_status_active = intval($row['ticket_status_active']);
// Generate the HTML form content using output buffering.
@@ -30,7 +31,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $ticket_status_name; ?>" required>
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $ticket_status_name; ?>" required <?php if ($ticket_status_id <= 5) { echo "readonly"; } ?>>
</div>
</div>
@@ -44,6 +45,16 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Order</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-sort-numeric-down"></i></span>
</div>
<input type="number" class="form-control" name="order" placeholder="Leave blank for no order" value="<?php echo $ticket_status_order; ?>">
</div>
</div>
<div class="form-group">
<label>Status <strong class="text-danger">*</strong></label>
<div class="input-group">
@@ -52,7 +63,7 @@ ob_start();
</div>
<select class="form-control select2" name="status" required>
<option <?php if ($ticket_status_active == 1) { echo "selected"; } ?> value="1">Active</option>
<option <?php if ($ticket_status_active == 0) { echo "selected"; } ?> value="0">Disabled</option>
<option <?php if ($ticket_status_active == 0) { echo "selected"; } ?> value="0" <?php if ($ticket_status_id <= 5) { echo "disabled"; } ?>>Inactive</option>
</select>
</div>
</div>

View File

@@ -10,12 +10,7 @@ $row = mysqli_fetch_array($sql);
$document_name = nullable_htmlentities($row['document_name']);
$document_description = nullable_htmlentities($row['document_description']);
$document_content = nullable_htmlentities($row['document_content']);
$document_created_by_id = intval($row['document_created_by']);
$document_created_at = nullable_htmlentities($row['document_created_at']);
$document_updated_at = nullable_htmlentities($row['document_updated_at']);
$document_archived_at = nullable_htmlentities($row['document_archived_at']);
$document_folder_id = intval($row['document_folder_id']);
$document_parent = intval($row['document_parent']);
$document_client_visible = intval($row['document_client_visible']);
$client_id = intval($row['document_client_id']);
@@ -30,10 +25,8 @@ ob_start();
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="document_id" value="<?php if($document_parent == 0){ echo $document_id; } else { echo $document_parent; } ?>">
<input type="hidden" name="document_parent" value="<?php echo $document_parent; ?>">
<input type="hidden" name="document_id" value="<?php echo $document_id; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<input type="hidden" name="created_by" value="<?php echo $document_created_by_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">

View File

@@ -2,38 +2,38 @@
require_once '../includes/ajax_header.php';
$document_id = intval($_GET['id']);
$document_template_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_id = $document_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM document_templates WHERE document_template_id = $document_template_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$document_name = nullable_htmlentities($row['document_name']);
$document_description = nullable_htmlentities($row['document_description']);
$document_content = nullable_htmlentities($row['document_content']);
$document_template_name = nullable_htmlentities($row['document_template_name']);
$document_template_description = nullable_htmlentities($row['document_template_description']);
$document_template_content = nullable_htmlentities($row['document_template_content']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-file-alt mr-2"></i>Editing template: <strong><?php echo $document_name; ?></strong></h5>
<h5 class="modal-title"><i class="fa fa-fw fa-file-alt mr-2"></i>Editing template: <strong><?php echo $document_template_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="document_id" value="<?php echo $document_id; ?>">
<input type="hidden" name="document_template_id" value="<?php echo $document_template_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $document_name; ?>" placeholder="Name" required>
<input type="text" class="form-control" name="name" maxlength="200" value="<?php echo $document_template_name; ?>" placeholder="Name" required>
</div>
<div class="form-group">
<textarea class="form-control tinymce" name="content"><?php echo $document_content; ?></textarea>
<textarea class="form-control tinymce" name="content"><?php echo $document_template_content; ?></textarea>
</div>
<div class="form-group">
<input type="text" class="form-control" name="description" value="<?php echo $document_description; ?>" placeholder="Short summary">
<input type="text" class="form-control" name="description" value="<?php echo $document_template_description; ?>" placeholder="Short summary">
</div>
</div>

View File

@@ -0,0 +1,39 @@
<?php
require_once '../includes/ajax_header.php';
// Initialize the HTML Purifier to prevent XSS
require_once "../plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
$purifier_config->set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]);
$purifier = new HTMLPurifier($purifier_config);
$document_version_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM document_versions WHERE document_version_id = $document_version_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$document_version_name = nullable_htmlentities($row['document_version_name']);
$document_version_content = $purifier->purify($row['document_version_content']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title text-white"><i class="fa fa-fw fa-file-alt mr-2"></i><?php echo $document_version_name; ?></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<div class="modal-body bg-white prettyContent">
<?php echo $document_version_content; ?>
</div>
<script src="../js/pretty_content.js"></script>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -33,5 +33,8 @@ ob_start();
<?php echo $document_content; ?>
</div>
<script src="../js/pretty_content.js"></script>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -105,7 +105,7 @@ ob_start();
<select class="form-control select2" name="vendor" required>
<?php
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND vendor_template = 0 ORDER BY vendor_name ASC");
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);

View File

@@ -119,7 +119,7 @@ ob_start();
<select class="form-control select2" name="vendor" required>
<?php
$sql_select = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND vendor_template = 0 AND (vendor_archived_at > '$expense_created_at' OR vendor_archived_at IS NULL) ORDER BY vendor_name ASC");
$sql_select = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND (vendor_archived_at > '$expense_created_at' OR vendor_archived_at IS NULL) ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_select)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);

182
ajax/ajax_invoice_pay.php Normal file
View File

@@ -0,0 +1,182 @@
<?php
require_once '../includes/ajax_header.php';
$invoice_id = intval($_GET['id']);
$sql = mysqli_query(
$mysqli,
"SELECT * FROM invoices
LEFT JOIN clients ON invoice_client_id = client_id
LEFT JOIN contacts ON client_id = contact_client_id AND contact_primary = 1
WHERE invoice_id = $invoice_id
LIMIT 1"
);
$row = mysqli_fetch_array($sql);
$invoice_id = intval($row['invoice_id']);
$invoice_prefix = nullable_htmlentities($row['invoice_prefix']);
$invoice_number = intval($row['invoice_number']);
$invoice_amount = floatval($row['invoice_amount']);
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
$client_currency_code = nullable_htmlentities($row['client_currency_code']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_email = nullable_htmlentities($row['contact_email']);
//Add up all the payments for the invoice and get the total amount paid to the invoice
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments WHERE payment_invoice_id = $invoice_id");
$row = mysqli_fetch_array($sql_amount_paid);
$amount_paid = floatval($row['amount_paid']);
$balance = $invoice_amount - $amount_paid;
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-credit-card mr-2"></i><?php echo "$invoice_prefix$invoice_number"; ?>: Make Payment</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="invoice_id" value="<?php echo $invoice_id; ?>">
<input type="hidden" name="balance" value="<?php echo $balance; ?>">
<input type="hidden" name="currency_code" value="<?php echo $client_currency_code; ?>">
<div class="modal-body bg-white">
<div class="form-row">
<div class="col-md">
<div class="form-group">
<label>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="date" max="2999-12-31" value="<?php echo date("Y-m-d"); ?>" required>
</div>
</div>
</div>
<div class="col-md">
<div class="form-group">
<label>Amount <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-dollar-sign"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="amount" value="<?php echo number_format($balance, 2, '.', ''); ?>" placeholder="0.00" required>
</div>
</div>
</div>
</div>
<div class="form-group">
<label>Account <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-piggy-bank"></i></span>
</div>
<select class="form-control select2" name="account" required>
<option value="">- Select an Account -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM accounts WHERE account_archived_at IS NULL ORDER BY account_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$account_id = intval($row['account_id']);
$account_name = nullable_htmlentities($row['account_name']);
$opening_balance = floatval($row['opening_balance']);
$sql_payments = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS total_payments FROM payments WHERE payment_account_id = $account_id");
$row = mysqli_fetch_array($sql_payments);
$total_payments = floatval($row['total_payments']);
$sql_revenues = mysqli_query($mysqli, "SELECT SUM(revenue_amount) AS total_revenues FROM revenues WHERE revenue_account_id = $account_id");
$row = mysqli_fetch_array($sql_revenues);
$total_revenues = floatval($row['total_revenues']);
$sql_expenses = mysqli_query($mysqli, "SELECT SUM(expense_amount) AS total_expenses FROM expenses WHERE expense_account_id = $account_id");
$row = mysqli_fetch_array($sql_expenses);
$total_expenses = floatval($row['total_expenses']);
$account_balance = $opening_balance + $total_payments + $total_revenues - $total_expenses;
?>
<option <?php if ($config_default_payment_account == $account_id) { echo "selected"; } ?>
value="<?php echo $account_id; ?>">
<?php echo $account_name; ?> [$<?php echo number_format($account_balance, 2); ?>]
</option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Payment Method <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-money-check-alt"></i></span>
</div>
<select class="form-control select2" name="payment_method" required>
<option value="">- Method of Payment -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Payment Method' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$category_name = nullable_htmlentities($row['category_name']);
?>
<option <?php if ($config_default_payment_method == $category_name) {
echo "selected";
} ?>><?php echo $category_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Reference</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-file-alt"></i></span>
</div>
<input type="text" class="form-control" name="reference" placeholder="Check #, Trans #, etc" maxlength="200">
</div>
</div>
<?php if (!empty($config_smtp_host) && !empty($contact_email)) { ?>
<div class="form-group">
<label>Email Receipt</label>
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="customControlAutosizing" name="email_receipt" value="1" checked>
<label class="custom-control-label" for="customControlAutosizing"><?php echo $contact_email; ?></label>
</div>
</div>
<?php } ?>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="add_payment" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Pay</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -14,8 +14,11 @@ $location_address = nullable_htmlentities($row['location_address']);
$location_city = nullable_htmlentities($row['location_city']);
$location_state = nullable_htmlentities($row['location_state']);
$location_zip = nullable_htmlentities($row['location_zip']);
$location_phone = formatPhoneNumber($row['location_phone']);
$location_fax = formatPhoneNumber($row['location_fax']);
$location_phone_country_code = nullable_htmlentities($row['location_phone_country_code']);
$location_phone = nullable_htmlentities(formatPhoneNumber($row['location_phone'], $location_phone_country_code));
$location_extension = formatPhoneNumber($row['location_extension']);
$location_fax_country_code = nullable_htmlentities($row['location_fax_country_code']);
$location_fax = nullable_htmlentities(formatPhoneNumber($row['location_fax'], $location_fax_country_code));
$location_hours = nullable_htmlentities($row['location_hours']);
$location_photo = nullable_htmlentities($row['location_photo']);
$location_notes = nullable_htmlentities($row['location_notes']);
@@ -198,23 +201,38 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Phone</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
<label>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" value="<?php echo $location_phone_country_code; ?>" placeholder="+" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $location_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="extension" value="<?php echo $location_extension; ?>" placeholder="ext." maxlength="200">
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $location_phone; ?>">
</div>
</div>
<div class="form-group">
<label>Fax</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-fax"></i></span>
<label>Fax</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-fax"></i></span>
</div>
<input type="tel" class="form-control col-2" name="fax_country_code" value="<?php echo $location_fax_country_code; ?>" placeholder="+" maxlength="4">
<input type="tel" class="form-control" name="fax" value="<?php echo $location_fax; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
<input type="text" class="form-control" name="fax" placeholder="Fax Number" maxlength="200" value="<?php echo $location_fax; ?>">
</div>
</div>

View File

@@ -90,7 +90,7 @@ ob_start();
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
?>
<option value="<?php echo $location_id; ?>" <?php if ($location_id = $network_location_id) { echo "selected"; } ?>>
<option value="<?php echo $location_id; ?>" <?php if ($location_id == $network_location_id) { echo "selected"; } ?>>
<?php echo $location_name; ?>
</option>
<?php

View File

@@ -25,54 +25,68 @@ ob_start();
<div class="modal-body bg-white">
<?php if ($num_notifications) { ?>
<table class="table table-sm table-hover table-borderless">
<?php while ($row = mysqli_fetch_array($sql)) {
$notification_id = intval($row["notification_id"]);
$notification_type = nullable_htmlentities($row["notification_type"]);
$notification_details = nullable_htmlentities($row["notification"]);
$notification_action = nullable_htmlentities(
$row["notification_action"]
);
$notification_timestamp_formated = date(
"M d g:ia",
strtotime($row["notification_timestamp"])
);
$notification_client_id = intval($row["notification_client_id"]);
if (empty($notification_action)) {
$notification_action = "#";
<?php while ($row = mysqli_fetch_array($sql)) {
$notification_id = intval($row["notification_id"]);
$notification_type = nullable_htmlentities($row["notification_type"]);
$notification_details = nullable_htmlentities($row["notification"]);
$notification_action = nullable_htmlentities(
$row["notification_action"]
);
$notification_timestamp_formated = date(
"M d g:ia",
strtotime($row["notification_timestamp"])
);
$notification_client_id = intval($row["notification_client_id"]);
if (empty($notification_action)) {
$notification_action = "#";
}
?>
<tr class="notification-item">
<th>
<a class="text-dark" href="<?php echo $notification_action; ?>">
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
<small class="text-muted float-right">
<?php echo $notification_timestamp_formated; ?>
</small>
<br>
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
</a>
</th>
</tr>
<?php
}
?>
<a class="text-dark dropdown-item px-1" href="<?php echo $notification_action; ?>">
<div>
<span class="text-bold">
<i class="fas fa-bullhorn mr-2"></i><?php echo $notification_type; ?>
</span>
<small class="text-muted float-right">
<?php echo $notification_timestamp_formated; ?>
</small>
</table>
<div class="text-center mt-2">
<button id="prev-btn" class="btn btn-sm btn-outline-secondary mr-2"><i class="fas fa-caret-left"></i></button>
<button id="next-btn" class="btn btn-sm btn-outline-secondary"><i class="fas fa-caret-right"></i></button>
</div>
<small class="text-secondary text-wrap"><?php echo $notification_details; ?></small>
</a>
<?php
}} else { ?>
<div class="text-center text-secondary py-5">
<?php } else { ?>
<div class="text-center text-secondary pt-3">
<i class='far fa-6x fa-bell-slash'></i>
<h3 class="mt-3">No Notifications</h3>
</div>
<?php } ?>
</div>
<div class="modal-footer bg-white justify-content-end">
<div class="modal-footer bg-white">
<?php if ($num_notifications) { ?>
<a href="post.php?dismiss_all_notifications&csrf_token=<?php echo $_SESSION[
"csrf_token"
]; ?>" class="btn btn-primary">
<span class="text-white text-bold"><i class="fas fa-check mr-2"></i>Dismiss all</span>
</a>
<a href="notifications.php" class="btn btn-secondary">
<span class="text-white">See all Notifications</span>
</a>
<?php } else { ?>
<a href="notifications_dismissed.php" class="btn btn-dark">
<a href="notifications.php?dismissed" class="btn btn-dark">
<span class="text-white text-bold">See Dismissed Notifications</span>
</a>
<?php } ?>
@@ -81,4 +95,41 @@ ob_start();
</button>
</div>
<script>
$(document).ready(function () {
var perPage = 8;
var $items = $(".notification-item");
var totalItems = $items.length;
var totalPages = Math.ceil(totalItems / perPage);
var currentPage = 0;
function showPage(page) {
$items.hide().slice(page * perPage, (page + 1) * perPage).show();
$("#prev-btn").prop("disabled", page === 0);
$("#next-btn").prop("disabled", page >= totalPages - 1);
$("#page-indicator").text(`Page ${page + 1} of ${totalPages} (${totalItems} total)`);
}
$("#prev-btn").on("click", function () {
if (currentPage > 0) {
currentPage--;
showPage(currentPage);
}
});
$("#next-btn").on("click", function () {
if (currentPage < totalPages - 1) {
currentPage++;
showPage(currentPage);
}
});
if (totalItems <= perPage) {
$("#prev-btn, #next-btn, #page-indicator").hide();
}
showPage(currentPage);
});
</script>
<?php require_once "../includes/ajax_footer.php";

View File

@@ -74,9 +74,8 @@ ob_start();
<?php
$sql_project_managers_select = mysqli_query(
$mysqli,
"SELECT users.user_id, user_name FROM users
LEFT JOIN user_settings on users.user_id = user_settings.user_id
WHERE user_role > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
"SELECT user_id, user_name FROM users
WHERE user_role_id > 1 AND user_status = 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
);
while ($row = mysqli_fetch_array($sql_project_managers_select)) {
$user_id_select = intval($row['user_id']);
@@ -86,6 +85,25 @@ ob_start();
</select>
</div>
</div>
<div class="form-group">
<label>Client</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-users"></i></span>
</div>
<select class="form-control select2" name="client_id">
<option value="0">- No Client -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$select_client_id = intval($row['client_id']);
$select_client_name = nullable_htmlentities($row['client_name']);
?>
<option value="<?php echo $select_client_id; ?>" <?php if ($client_id == $select_client_id) { echo "selected"; } ?>><?php echo $select_client_name; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_project" class="btn btn-primary text-bold">

View File

@@ -157,7 +157,7 @@ ob_start();
<select class="form-control select2" name="vendor" required>
<?php
$sql_select = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND vendor_template = 0 AND (vendor_archived_at > '$recurring_expense_created_at' OR vendor_archived_at IS NULL) ORDER BY vendor_name ASC");
$sql_select = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = 0 AND (vendor_archived_at > '$recurring_expense_created_at' OR vendor_archived_at IS NULL) ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_select)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);

View File

@@ -2,33 +2,33 @@
require_once '../includes/ajax_header.php';
$recurring_id = intval($_GET['id']);
$recurring_invoice_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM recurring WHERE recurring_id = $recurring_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_invoices WHERE recurring_invoice_id = $recurring_invoice_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$recurring_prefix = nullable_htmlentities($row['recurring_prefix']);
$recurring_number = intval($row['recurring_number']);
$recurring_scope = nullable_htmlentities($row['recurring_scope']);
$recurring_frequency = nullable_htmlentities($row['recurring_frequency']);
$recurring_status = nullable_htmlentities($row['recurring_status']);
$recurring_created_at = date('Y-m-d', strtotime($row['recurring_created_at']));
$recurring_next_date = nullable_htmlentities($row['recurring_next_date']);
$recurring_discount = floatval($row['recurring_discount_amount']);
$category_id = intval($row['recurring_category_id']);
$recurring_invoice_prefix = nullable_htmlentities($row['recurring_invoice_prefix']);
$recurring_invoice_number = intval($row['recurring_invoice_number']);
$recurring_invoice_scope = nullable_htmlentities($row['recurring_invoice_scope']);
$recurring_invoice_frequency = nullable_htmlentities($row['recurring_invoice_frequency']);
$recurring_invoice_status = nullable_htmlentities($row['recurring_invoice_status']);
$recurring_invoice_created_at = date('Y-m-d', strtotime($row['recurring_invoice_created_at']));
$recurring_invoice_next_date = nullable_htmlentities($row['recurring_invoice_next_date']);
$recurring_invoice_discount = floatval($row['recurring_invoice_discount_amount']);
$category_id = intval($row['recurring_invoice_category_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-redo-alt mr-2"></i>Editing Recur Invoice: <strong><?php echo "$recurring_prefix$recurring_number"; ?></strong></h5>
<h5 class="modal-title"><i class="fas fa-fw fa-redo-alt mr-2"></i>Editing Recur Invoice: <strong><?php echo "$recurring_invoice_prefix$recurring_invoice_number"; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="recurring_id" value="<?php echo $recurring_id; ?>">
<input type="hidden" name="recurring_invoice_id" value="<?php echo $recurring_invoice_id; ?>">
<div class="modal-body bg-white">
@@ -38,7 +38,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-comment"></i></span>
</div>
<input type="text" class="form-control" name="scope" placeholder="Quick description" maxlength="255" value="<?php echo $recurring_scope; ?>">
<input type="text" class="form-control" name="scope" placeholder="Quick description" maxlength="255" value="<?php echo $recurring_invoice_scope; ?>">
</div>
</div>
@@ -50,8 +50,8 @@ ob_start();
</div>
<select class="form-control select2" name="frequency" required>
<option value="">- Frequency -</option>
<option <?php if ($recurring_frequency == 'month') { echo "selected"; } ?> value="month">Monthly</option>
<option <?php if ($recurring_frequency == 'year') { echo "selected"; } ?> value="year">Yearly</option>
<option <?php if ($recurring_invoice_frequency == 'month') { echo "selected"; } ?> value="month">Monthly</option>
<option <?php if ($recurring_invoice_frequency == 'year') { echo "selected"; } ?> value="year">Yearly</option>
</select>
</div>
</div>
@@ -62,7 +62,7 @@ ob_start();
<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="next_date" max="2999-12-31" value="<?php echo $recurring_next_date; ?>" required>
<input type="date" class="form-control" name="next_date" max="2999-12-31" value="<?php echo $recurring_invoice_next_date; ?>" required>
</div>
</div>
@@ -76,7 +76,7 @@ ob_start();
<option value="">- Category -</option>
<?php
$sql_income_category = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' AND (category_archived_at > '$recurring_created_at' OR category_archived_at IS NULL) ORDER BY category_name ASC");
$sql_income_category = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Income' AND (category_archived_at > '$recurring_invoice_created_at' OR category_archived_at IS NULL) ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_income_category)) {
$category_id_select = intval($row['category_id']);
$category_name_select = nullable_htmlentities($row['category_name']);
@@ -104,7 +104,7 @@ ob_start();
<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' inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name='recurring_discount' placeholder='0.00' value="<?php echo number_format($recurring_discount, 2, '.', ''); ?>">
<input type='text' class='form-control' inputmode="numeric" pattern="-?[0-9]*\.?[0-9]{0,2}" name='recurring_invoice_discount' placeholder='0.00' value="<?php echo number_format($recurring_invoice_discount, 2, '.', ''); ?>">
</div>
</div>
@@ -115,10 +115,10 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
</div>
<select class="form-control select2" name="status" required>
<option <?php if ($recurring_status == 1) {
<option <?php if ($recurring_invoice_status == 1) {
echo "selected";
} ?> value="1">Active</option>
<option <?php if ($recurring_status == 0) {
<option <?php if ($recurring_invoice_status == 0) {
echo "selected";
} ?> value="0">InActive</option>
</select>
@@ -127,7 +127,7 @@ ob_start();
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_recurring" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
<button type="submit" name="edit_recurring_invoice" 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>

View File

@@ -2,56 +2,65 @@
require_once '../includes/ajax_header.php';
$scheduled_ticket_id = intval($_GET['id']);
$recurring_ticket_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets WHERE scheduled_ticket_id = $scheduled_ticket_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM recurring_tickets WHERE recurring_ticket_id = $recurring_ticket_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$client_id = intval($row['scheduled_ticket_client_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_details = nullable_htmlentities($row['scheduled_ticket_details']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$scheduled_ticket_assigned_to = intval($row['scheduled_ticket_assigned_to']);
$scheduled_ticket_contact_id = intval($row['scheduled_ticket_contact_id']);
$scheduled_ticket_asset_id = intval($row['scheduled_ticket_asset_id']);
$scheduled_ticket_billable = intval($row['scheduled_ticket_billable']);
$client_id = intval($row['recurring_ticket_client_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_details = nullable_htmlentities($row['recurring_ticket_details']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
$recurring_ticket_assigned_to = intval($row['recurring_ticket_assigned_to']);
$recurring_ticket_contact_id = intval($row['recurring_ticket_contact_id']);
$recurring_ticket_asset_id = intval($row['recurring_ticket_asset_id']);
$recurring_ticket_category = intval($row['recurring_ticket_category']);
$recurring_ticket_billable = intval($row['recurring_ticket_billable']);
// Additional Assets Selected
$additional_assets_array = array();
$sql_additional_assets = mysqli_query($mysqli, "SELECT asset_id FROM recurring_ticket_assets WHERE recurring_ticket_id = $recurring_ticket_id");
while ($row = mysqli_fetch_array($sql_additional_assets)) {
$additional_asset_id = intval($row['asset_id']);
$additional_assets_array[] = $additional_asset_id;
}
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fas fa-fw fa-calendar-check mr-2"></i>Editing Recurring Ticket: <strong><?php echo $scheduled_ticket_subject; ?></strong></h5>
<h5 class="modal-title"><i class="fas fa-fw fa-calendar-check mr-2"></i>Editing Recurring Ticket: <strong><?php echo $recurring_ticket_subject; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="scheduled_ticket_id" value="<?php echo $scheduled_ticket_id; ?>">
<input type="hidden" name="recurring_ticket_id" value="<?php echo $recurring_ticket_id; ?>">
<input type="hidden" name="client" value="<?php echo $client_id; ?>">
<div class="modal-body bg-white">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-edit-details<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-life-ring mr-2"></i>Details</a>
<a class="nav-link active" data-toggle="pill" href="#pills-edit-details<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-life-ring mr-2"></i>Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-edit-contacts<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-users mr-2"></i>Contacts</a>
<a class="nav-link" data-toggle="pill" href="#pills-edit-contacts<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-users mr-2"></i>Contact</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-edit-schedule<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-building mr-2"></i>Schedule</a>
<a class="nav-link" data-toggle="pill" href="#pills-edit-schedule<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-building mr-2"></i>Schedule</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-edit-assets<?php echo $scheduled_ticket_id; ?>"><i class="fa fa-fw fa-desktop mr-2"></i>Assets</a>
<a class="nav-link" data-toggle="pill" href="#pills-edit-assets<?php echo $recurring_ticket_id; ?>"><i class="fa fa-fw fa-desktop mr-2"></i>Assets</a>
</li>
</ul>
<div class="tab-content" <?php if (lookupUserPermission('module_support') <= 1) { echo 'inert'; } ?>>
<div class="tab-pane fade show active" id="pills-edit-details<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade show active" id="pills-edit-details<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Subject <strong class="text-danger">*</strong></label>
@@ -59,25 +68,61 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500" value="<?php echo $scheduled_ticket_subject; ?>" required >
<input type="text" class="form-control" name="subject" placeholder="Subject" maxlength="500" value="<?php echo $recurring_ticket_subject; ?>" required >
</div>
</div>
<div class="form-group">
<textarea class="form-control tinymce" name="details"><?php echo $scheduled_ticket_details; ?></textarea>
<textarea class="form-control tinymce" name="details"><?php echo $recurring_ticket_details; ?></textarea>
</div>
<div class="form-group">
<label>Priority <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-thermometer-half"></i></span>
<div class="row">
<div class="col">
<div class="form-group">
<label>Priority <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-thermometer-half"></i></span>
</div>
<select class="form-control select2" name="priority" required>
<option <?php if ($recurring_ticket_priority == "Low") { echo "selected"; } ?> >Low</option>
<option <?php if ($recurring_ticket_priority == "Medium") { echo "selected"; } ?> >Medium</option>
<option <?php if ($recurring_ticket_priority == "High") { echo "selected"; } ?> >High</option>
</select>
</div>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Category</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-layer-group"></i></span>
</div>
<select class="form-control select2" name="category">
<option value="0">- Uncategorized -</option>
<?php
$sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_categories)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
?>
<option <?php if ($recurring_ticket_category == $category_id) {echo "selected";} ?> value="<?php echo $category_id; ?>"><?php echo $category_name; ?></option>
<?php } ?>
</select>
<div class="input-group-append">
<button class="btn btn-secondary" type="button"
data-toggle="ajax-modal"
data-modal-size="sm"
data-ajax-url="ajax/ajax_category_add.php?category=Ticket">
<i class="fas fa-fw fa-plus"></i>
</button>
</div>
</div>
</div>
<select class="form-control select2" name="priority" required>
<option <?php if ($scheduled_ticket_priority == "Low") { echo "selected"; } ?> >Low</option>
<option <?php if ($scheduled_ticket_priority == "Medium") { echo "selected"; } ?> >Medium</option>
<option <?php if ($scheduled_ticket_priority == "High") { echo "selected"; } ?> >High</option>
</select>
</div>
</div>
@@ -100,7 +145,7 @@ ob_start();
$user_name_select = nullable_htmlentities($row['user_name']);
?>
<option value="<?php echo $user_id_select; ?>" <?php if ($scheduled_ticket_assigned_to == $user_id_select) { echo "selected"; } ?>><?php echo $user_name_select; ?></option>
<option value="<?php echo $user_id_select; ?>" <?php if ($recurring_ticket_assigned_to == $user_id_select) { echo "selected"; } ?>><?php echo $user_name_select; ?></option>
<?php } ?>
</select>
</div>
@@ -109,7 +154,7 @@ ob_start();
<div class="form-group <?php if (!$config_module_enable_accounting) { echo 'd-none'; } ?>">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" id="editTicketBillable" name="billable"
<?php if ($scheduled_ticket_billable == 1) { echo "checked"; } ?> value="1"
<?php if ($recurring_ticket_billable == 1) { echo "checked"; } ?> value="1"
>
<label class="custom-control-label" for="editTicketBillable">Mark Billable</label>
</div>
@@ -117,7 +162,7 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-edit-contacts<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade" id="pills-edit-contacts<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Contact</label>
@@ -152,7 +197,7 @@ ob_start();
}
?>
<option value="<?php echo $contact_id_select; ?>" <?php if ($contact_id_select == $scheduled_ticket_contact_id) { echo "selected"; } ?>><?php echo "$contact_name_select$contact_title_display_select$contact_primary_display_select$contact_technical_display_select"; ?></option>
<option value="<?php echo $contact_id_select; ?>" <?php if ($contact_id_select == $recurring_ticket_contact_id) { echo "selected"; } ?>><?php echo "$contact_name_select$contact_title_display_select$contact_primary_display_select$contact_technical_display_select"; ?></option>
<?php } ?>
</select>
</div>
@@ -160,7 +205,7 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-edit-schedule<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade" id="pills-edit-schedule<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Frequency <strong class="text-danger">*</strong></label>
@@ -169,11 +214,11 @@ ob_start();
<span class="input-group-text"><i class="fa fa-fw fa-recycle"></i></span>
</div>
<select class="form-control select2" name="frequency">
<option <?php if ($scheduled_ticket_frequency == "Weekly") { echo "selected"; } ?>>Weekly</option>
<option <?php if ($scheduled_ticket_frequency == "Monthly") { echo "selected"; } ?>>Monthly</option>
<option <?php if ($scheduled_ticket_frequency == "Quarterly") { echo "selected"; } ?>>Quarterly</option>
<option <?php if ($scheduled_ticket_frequency == "Biannually") { echo "selected"; } ?>>Biannually</option>
<option <?php if ($scheduled_ticket_frequency == "Annually") { echo "selected"; } ?>>Annually</option>
<option <?php if ($recurring_ticket_frequency == "Weekly") { echo "selected"; } ?>>Weekly</option>
<option <?php if ($recurring_ticket_frequency == "Monthly") { echo "selected"; } ?>>Monthly</option>
<option <?php if ($recurring_ticket_frequency == "Quarterly") { echo "selected"; } ?>>Quarterly</option>
<option <?php if ($recurring_ticket_frequency == "Biannually") { echo "selected"; } ?>>Biannually</option>
<option <?php if ($recurring_ticket_frequency == "Annually") { echo "selected"; } ?>>Annually</option>
</select>
</div>
</div>
@@ -184,13 +229,13 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar-day"></i></span>
</div>
<input class="form-control" type="date" name="next_date" max="2999-12-31" value="<?php echo $scheduled_ticket_next_run; ?>">
<input class="form-control" type="date" name="next_date" max="2999-12-31" value="<?php echo $recurring_ticket_next_run; ?>">
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-edit-assets<?php echo $scheduled_ticket_id; ?>">
<div class="tab-pane fade" id="pills-edit-assets<?php echo $recurring_ticket_id; ?>">
<div class="form-group">
<label>Asset</label>
@@ -208,7 +253,7 @@ ob_start();
$asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option <?php if ($scheduled_ticket_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<option <?php if ($recurring_ticket_asset_id == $asset_id_select) { echo "selected"; } ?> value="<?php echo $asset_id_select; ?>"><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<?php
}
@@ -217,6 +262,31 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Additional Assets</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
</div>
<select class="form-control select2" name="additional_assets[]" data-tags="true" data-placeholder="- Select Additional Assets -" multiple>
<option value=""></option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, contact_name FROM assets LEFT JOIN contacts ON contact_id = asset_contact_id WHERE asset_client_id = $client_id AND asset_id != $recurring_ticket_asset_id AND asset_archived_at IS NULL ORDER BY asset_name ASC");
while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id_select = intval($row['asset_id']);
$asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option value="<?php echo $asset_id_select; ?>"
<?php if (in_array($asset_id_select, $additional_assets_array)) { echo "selected"; } ?>
><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
</div>

View File

@@ -4,18 +4,18 @@ require_once '../includes/ajax_header.php';
$role_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE user_role_id = $role_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE role_id = $role_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$role_name = nullable_htmlentities($row['user_role_name']);
$role_description = nullable_htmlentities($row['user_role_description']);
$role_admin = intval($row['user_role_is_admin']);
$role_name = nullable_htmlentities($row['role_name']);
$role_description = nullable_htmlentities($row['role_description']);
$role_admin = intval($row['role_is_admin']);
// Count number of users that have each role
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(users.user_id) FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_role_user_count = mysqli_query($mysqli, "SELECT COUNT(user_id) FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
$role_user_count = mysqli_fetch_row($sql_role_user_count)[0];
$sql_users = mysqli_query($mysqli, "SELECT * FROM users LEFT JOIN user_settings on users.user_id = user_settings.user_id WHERE user_role = $role_id AND user_archived_at IS NULL");
$sql_users = mysqli_query($mysqli, "SELECT * FROM users WHERE user_role_id = $role_id AND user_archived_at IS NULL");
// Initialize an empty array to hold user names
$user_names = [];

View File

@@ -5,7 +5,6 @@ require_once '../includes/ajax_header.php';
$service_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM services WHERE service_id = $service_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$service_name = nullable_htmlentities($row['service_name']);
$service_description = nullable_htmlentities($row['service_description']);
@@ -17,6 +16,7 @@ $service_created_at = nullable_htmlentities($row['service_created_at']);
$service_updated_at = nullable_htmlentities($row['service_updated_at']);
$service_review_due = nullable_htmlentities($row['service_review_due']);
$client_id = intval($row['service_client_id']);
// Service Importance
if ($service_importance == "High") {
$service_importance_display = "<span class='p-2 badge badge-danger'>$service_importance</span>";
@@ -28,23 +28,23 @@ if ($service_importance == "High") {
$service_importance_display = "-";
}
// Associated Assets (and their logins/networks/locations)
// Associated Assets (and their credentials/networks/locations)
$sql_assets = mysqli_query(
$mysqli,
"SELECT * FROM service_assets
LEFT JOIN assets ON service_assets.asset_id = assets.asset_id
LEFT JOIN asset_interfaces ON interface_asset_id = assets.asset_id AND interface_primary = 1
LEFT JOIN logins ON service_assets.asset_id = logins.login_asset_id
LEFT JOIN credentials ON service_assets.asset_id = credentials.credential_asset_id
LEFT JOIN networks ON interface_network_id = networks.network_id
LEFT JOIN locations ON assets.asset_location_id = locations.location_id
WHERE service_id = $service_id"
);
// Associated logins
$sql_logins = mysqli_query(
// Associated credentials
$sql_credentials = mysqli_query(
$mysqli,
"SELECT * FROM service_logins
LEFT JOIN logins ON service_logins.login_id = logins.login_id
"SELECT * FROM service_credentials
LEFT JOIN credentials ON service_credentials.credential_id = credentials.credential_id
WHERE service_id = $service_id"
);
@@ -55,6 +55,7 @@ $sql_domains = mysqli_query(
LEFT JOIN domains ON service_domains.domain_id = domains.domain_id
WHERE service_id = $service_id"
);
// Associated Certificates
$sql_certificates = mysqli_query(
$mysqli,
@@ -63,10 +64,6 @@ $sql_certificates = mysqli_query(
WHERE service_id = $service_id"
);
// Associated URLs ---- REMOVED for now
//$sql_urls = mysqli_query($mysqli, "SELECT * FROM service_urls
//WHERE service_id = '$service_id'");
// Associated Vendors
$sql_vendors = mysqli_query(
$mysqli,
@@ -116,149 +113,99 @@ ob_start();
<!-- Assets -->
<?php
if (mysqli_num_rows($sql_assets) > 0) { ?>
<h5><i class="fas fa-fw fa-desktop mr-2"></i>Assets</h5>
<ul>
<?php
// Reset the $sql_assets pointer to the start - as we've already cycled through once
mysqli_data_seek($sql_assets, 0);
while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id = intval($row['asset_id']);
$asset_name = nullable_htmlentities($row['asset_name']);
if (!empty($row['interface_ip'])) {
$ip = '('.nullable_htmlentities($row["interface_ip"]).')';
} else {
$ip = '';
}
echo "<li><a href='#' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_asset_details.php'
data-ajax-id='$asset_id'>$asset_name</a>$ip</li>";
}
?>
</ul>
<?php
if (mysqli_num_rows($sql_assets) > 0) {
echo "<h5><i class='fas fa-fw fa-desktop mr-2'></i>Assets</h5><ul>";
mysqli_data_seek($sql_assets, 0);
while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id = intval($row['asset_id']);
$asset_name = nullable_htmlentities($row['asset_name']);
$ip = !empty($row['interface_ip']) ? '(' . nullable_htmlentities($row['interface_ip']) . ')' : '';
echo "<li><a href='#' data-toggle='ajax-modal' data-modal-size='lg' data-ajax-url='ajax/ajax_asset_details.php' data-ajax-id='$asset_id'>$asset_name</a>$ip</li>";
}
echo "</ul>";
}
?>
<!-- Networks -->
<?php
$networks = [];
if ($sql_assets) {
$networks = [];
// Reset the $sql_assets pointer to the start
mysqli_data_seek($sql_assets, 0);
// Get networks linked to assets - push name to array
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['network_name'])) {
$network_data = nullable_htmlentities("$row[network_name]:$row[network_vlan]");
array_push($networks, $network_data);
$network_data = nullable_htmlentities($row["network_name"]) . ':' . nullable_htmlentities($row["network_vlan"]);
$networks[] = $network_data;
}
}
// Remove duplicates
$networks = array_unique($networks);
// Display
if (!empty($networks)) { ?>
<h5><i class="fas fa-fw fa-network-wired mr-2"></i>Networks</h5>
<ul>
<?php
if (!empty($networks)) {
echo "<h5><i class='fas fa-fw fa-network-wired mr-2'></i>Networks</h5><ul>";
foreach ($networks as $network) {
$network_parts = explode(":", $network);
$network_name = $network_parts[0];
$network_vlan = $network_parts[1] ?? '';
echo "<li><a href='networks.php?client_id=$client_id&q=$network_name'>$network_name</a> (VLAN $network_vlan)</li>";
}
echo "</ul>";
}
foreach($networks as $network) {
$network = explode(":", $network);
echo "<li><a href=\"networks.php?client_id=$client_id&q=$network[0]\">$network[0] </a>(VLAN $network[1])</li>";
}
?>
</ul>
<?php
}
?>
<!-- Locations -->
<?php
$location_names = [];
if ($sql_assets) {
$location_names = [];
// Reset the $sql_assets pointer to the start - as we've already cycled through once
mysqli_data_seek($sql_assets, 0);
// Get locations linked to assets - push their name and vlan to arrays
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['location_name'])) {
array_push($location_names, $row['location_name']);
$location_names[] = nullable_htmlentities($row['location_name']);
}
}
// Remove duplicates
$location_names = array_unique($location_names);
// Display
if (!empty($location_names)) { ?>
<h5><i class="fas fa-fw fa-map-marker-alt mr-2"></i>Locations</h5>
<ul>
<?php
if (!empty($location_names)) {
echo "<h5><i class='fas fa-fw fa-map-marker-alt mr-2'></i>Locations</h5><ul>";
foreach ($location_names as $location) {
echo "<li><a href='locations.php?client_id=$client_id&q=$location'>$location</a></li>";
}
echo "</ul>";
}
foreach($location_names as $location) {
echo "<li><a href=\"locations.php?client_id=$client_id&q=$location\">$location</a></li>";
}
?>
</ul>
<?php
}
?>
<!-- Domains -->
<?php
if (mysqli_num_rows($sql_domains) > 0) { ?>
<h5><i class="fas fa-fw fa-globe mr-2"></i>Domains</h5>
<ul>
<?php
// Reset the $sql_domains pointer to the start
mysqli_data_seek($sql_domains, 0);
// Showing linked domains
while ($row = mysqli_fetch_array($sql_domains)) {
if (!empty($row['domain_name'])) {
echo "<li><a href=\"domains.php?client_id=$client_id&q=$row[domain_name]\">$row[domain_name]</a></li>";
}
if (mysqli_num_rows($sql_domains) > 0) {
echo "<h5><i class='fas fa-fw fa-globe mr-2'></i>Domains</h5><ul>";
mysqli_data_seek($sql_domains, 0);
while ($row = mysqli_fetch_array($sql_domains)) {
if (!empty($row['domain_name'])) {
$domain_name = nullable_htmlentities($row['domain_name']);
echo "<li><a href='domains.php?client_id=$client_id&q=$domain_name'>$domain_name</a></li>";
}
?>
</ul>
<?php
}
echo "</ul>";
}
?>
<!-- Certificates -->
<?php
if (mysqli_num_rows($sql_certificates) > 0) { ?>
<h5><i class="fas fa-fw fa-lock mr-2"></i>Certificates</h5>
<ul>
<?php
// Reset the $sql_certificates pointer to the start
mysqli_data_seek($sql_certificates, 0);
// Showing linked certs
while ($row = mysqli_fetch_array($sql_certificates)) {
if (!empty($row['certificate_name'])) {
echo "<li><a href=\"certificates.php?client_id=$client_id&q=$row[certificate_name]\">$row[certificate_name] ($row[certificate_domain])</a></li>";
}
if (mysqli_num_rows($sql_certificates) > 0) {
echo "<h5><i class='fas fa-fw fa-lock mr-2'></i>Certificates</h5><ul>";
mysqli_data_seek($sql_certificates, 0);
while ($row = mysqli_fetch_array($sql_certificates)) {
if (!empty($row['certificate_name'])) {
$certificate_name = nullable_htmlentities($row['certificate_name']);
$certificate_domain = nullable_htmlentities($row['certificate_domain']);
echo "<li><a href='certificates.php?client_id=$client_id&q=$certificate_name'>$certificate_name ($certificate_domain)</a></li>";
}
?>
</ul>
<?php
}
echo "</ul>";
}
?>
</div>
</div>
<!-- Right side -->
<div class="col-4">
<div class="col-12">
@@ -267,148 +214,96 @@ ob_start();
<!-- Vendors -->
<?php
// Reset the $sql_vendors pointer to the start
mysqli_data_seek($sql_vendors, 0);
if (mysqli_num_rows($sql_vendors) > 0) { ?>
<h5><i class="fas fa-fw fa-building mr-2"></i>Vendors</h5>
<ul>
<?php
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
echo "<li><a href='#' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_vendor_details.php'
data-ajax-id='$vendor_id'>
$vendor_name
</a>
</li>";
}
?>
</ul>
<?php
if (mysqli_num_rows($sql_vendors) > 0) {
echo "<h5><i class='fas fa-fw fa-building mr-2'></i>Vendors</h5><ul>";
mysqli_data_seek($sql_vendors, 0);
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
echo "<li><a href='#' data-toggle='ajax-modal' data-modal-size='lg' data-ajax-url='ajax/ajax_vendor_details.php' data-ajax-id='$vendor_id'>$vendor_name</a></li>";
}
echo "</ul>";
}
?>
<!-- Contacts -->
<?php
if (mysqli_num_rows($sql_contacts) > 0) { ?>
<h5><i class="fas fa-fw fa-users mr-2"></i>Contacts</h5>
<ul>
<?php
// Reset the $sql_contacts pointer to the start
mysqli_data_seek($sql_contacts, 0);
while ($row = mysqli_fetch_array($sql_contacts)) {
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
echo "<li><a href='#' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_contact_details.php'
data-ajax-id='$contact_id'>
$contact_name
</a>
</li>";
}
?>
</ul>
<?php
if (mysqli_num_rows($sql_contacts) > 0) {
echo "<h5><i class='fas fa-fw fa-users mr-2'></i>Contacts</h5><ul>";
mysqli_data_seek($sql_contacts, 0);
while ($row = mysqli_fetch_array($sql_contacts)) {
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
echo "<li><a href='#' data-toggle='ajax-modal' data-modal-size='lg' data-ajax-url='ajax/ajax_contact_details.php' data-ajax-id='$contact_id'>$contact_name</a></li>";
}
echo "</ul>";
}
?>
<!-- Logins -->
<!-- Credentials -->
<?php
if (mysqli_num_rows($sql_assets) > 0 || mysqli_num_rows($sql_logins) > 0) { ?>
<h5><i class="fas fa-fw fa-key mr-2"></i>Logins</h5>
<ul>
<?php
// Reset the $sql_assets/logins pointer to the start
mysqli_data_seek($sql_assets, 0);
mysqli_data_seek($sql_logins, 0);
// Showing logins linked to assets
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['login_name'])) {
echo "<li><a href=\"credentials.php?client_id=$client_id&q=$row[login_name]\">$row[login_name]</a></li>";
}
if (mysqli_num_rows($sql_assets) > 0 || mysqli_num_rows($sql_credentials) > 0) {
echo "<h5><i class='fas fa-fw fa-key mr-2'></i>Credentials</h5><ul>";
// Credentials linked to assets
mysqli_data_seek($sql_assets, 0);
while ($row = mysqli_fetch_array($sql_assets)) {
$credential_name = nullable_htmlentities($row['credential_name']);
if (!empty($credential_name)) {
echo "<li><a href='credentials.php?client_id=$client_id&q=$credential_name'>$credential_name</a></li>";
}
// Showing explicitly linked logins
while ($row = mysqli_fetch_array($sql_logins)) {
if (!empty($row['login_name'])) {
echo "<li><a href=\"credentials.php?client_id=$client_id&q=$row[login_name]\">$row[login_name]</a></li>";
}
}
// Explicitly linked credentials
mysqli_data_seek($sql_credentials, 0);
while ($row = mysqli_fetch_array($sql_credentials)) {
$credential_name = nullable_htmlentities($row['credential_name']);
if (!empty($credential_name)) {
echo "<li><a href='credentials.php?client_id=$client_id&q=$credential_name'>$credential_name</a></li>";
}
?>
</ul>
<?php
}
echo "</ul>";
}
?>
<!-- URLs -->
<?php
if ($sql_logins || $sql_assets) { ?>
<h5><i class="fas fa-fw fa-link mr-2"></i>URLs</h5>
<ul>
<?php
// Reset the $sql_logins pointer to the start
mysqli_data_seek($sql_logins, 0);
// Showing URLs linked to logins
while ($row = mysqli_fetch_array($sql_logins)) {
if (!empty($row['login_uri'])) {
echo "<li><a href=\"https://$row[login_uri]\">$row[login_uri]</a></li>";
}
}
// Reset the $sql_assets pointer to the start
mysqli_data_seek($sql_assets, 0);
// Show URLs linked to assets, that also have logins
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['login_uri'])) {
echo "<li><a href=\"https://$row[login_uri]\">$row[login_uri]</a></li>";
}
}
?>
</ul>
<?php
$urls = [];
mysqli_data_seek($sql_credentials, 0);
while ($row = mysqli_fetch_array($sql_credentials)) {
if (!empty($row['credential_uri'])) {
$urls[] = sanitize_url($row['credential_uri']);
}
}
mysqli_data_seek($sql_assets, 0);
while ($row = mysqli_fetch_array($sql_assets)) {
if (!empty($row['asset_uri'])) {
$urls[] = sanitize_url($row['asset_uri']);
}
}
$urls = array_unique($urls);
if (!empty($urls)) {
echo "<h5><i class='fas fa-fw fa-link mr-2'></i>URLs</h5><ul>";
foreach ($urls as $url) {
$label = htmlspecialchars(parse_url($url, PHP_URL_HOST) ?: $url);
echo "<li><a href='$url' target='_blank'>$label</a></li>";
}
echo "</ul>";
}
?>
<!-- Documents -->
<?php
if (mysqli_num_rows($sql_docs) > 0) { ?>
<h5><i class="fas fa-fw fa-file-alt mr-2"></i>Documents</h5>
<ul>
<?php
// Reset the $sql_docs pointer to the start
mysqli_data_seek($sql_docs, 0);
while ($row = mysqli_fetch_array($sql_docs)) {
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
echo "<li><a href='#' data-toggle='ajax-modal'
data-modal-size='lg'
data-ajax-url='ajax/ajax_document_view.php'
data-ajax-id='$document_id'>
$document_name
</a>
</li>";
}
?>
</ul>
<?php
if (mysqli_num_rows($sql_docs) > 0) {
echo "<h5><i class='fas fa-fw fa-file-alt mr-2'></i>Documents</h5><ul>";
mysqli_data_seek($sql_docs, 0);
while ($row = mysqli_fetch_array($sql_docs)) {
$document_id = intval($row['document_id']);
$document_name = nullable_htmlentities($row['document_name']);
echo "<li><a href='#' data-toggle='ajax-modal' data-modal-size='lg' data-ajax-url='ajax/ajax_document_view.php' data-ajax-id='$document_id'>$document_name</a></li>";
}
echo "</ul>";
}
?>
<!-- <h5><i class="nav-icon fas fa-file-alt"></i> Services</h5>-->
<!-- <ul>-->
<!-- <li>Related Service - Coming soon!</li>-->
<!-- </ul>-->
</div>
</div>
</div>
@@ -416,3 +311,4 @@ ob_start();
<?php
require_once "../includes/ajax_footer.php";
?>

View File

@@ -18,23 +18,23 @@ $service_updated_at = nullable_htmlentities($row['service_updated_at']);
$service_review_due = nullable_htmlentities($row['service_review_due']);
$client_id = intval($row['service_client_id']);
// Associated Assets (and their logins/networks/locations)
// Associated Assets (and their credentials/networks/locations)
$sql_assets = mysqli_query(
$mysqli,
"SELECT * FROM service_assets
LEFT JOIN assets ON service_assets.asset_id = assets.asset_id
LEFT JOIN asset_interfaces ON interface_asset_id = assets.asset_id AND interface_primary = 1
LEFT JOIN logins ON service_assets.asset_id = logins.login_asset_id
LEFT JOIN credentials ON service_assets.asset_id = credentials.credential_asset_id
LEFT JOIN networks ON interface_network_id = networks.network_id
LEFT JOIN locations ON assets.asset_location_id = locations.location_id
WHERE service_id = $service_id"
);
// Associated logins
$sql_logins = mysqli_query(
// Associated credentials
$sql_credentials = mysqli_query(
$mysqli,
"SELECT * FROM service_logins
LEFT JOIN logins ON service_logins.login_id = logins.login_id
"SELECT * FROM service_credentials
LEFT JOIN credentials ON service_credentials.credential_id = credentials.credential_id
WHERE service_id = $service_id"
);
@@ -211,7 +211,7 @@ ob_start();
<?php
$selected_ids = array_column(mysqli_fetch_all($sql_vendors, MYSQLI_ASSOC), "vendor_id");
$sql_all = mysqli_query($mysqli, "SELECT * FROM vendors WHERE (vendor_archived_at > '$service_created_at' OR vendor_archived_at IS NULL) AND vendor_template = 0 AND vendor_client_id = $client_id");
$sql_all = mysqli_query($mysqli, "SELECT * FROM vendors WHERE (vendor_archived_at > '$service_created_at' OR vendor_archived_at IS NULL) AND vendor_client_id = $client_id");
while ($row_all = mysqli_fetch_array($sql_all)) {
$vendor_id = intval($row_all['vendor_id']);
$vendor_name = nullable_htmlentities($row_all['vendor_name']);
@@ -280,21 +280,21 @@ ob_start();
</div>
<div class="form-group">
<label for="logins">Logins</label>
<select multiple class="form-control select2" name="logins[]">
<label for="credentials">Credentials</label>
<select multiple class="form-control select2" name="credentials[]">
<?php
$selected_ids = array_column(mysqli_fetch_all($sql_logins, MYSQLI_ASSOC), "login_id");
$selected_ids = array_column(mysqli_fetch_all($sql_credentials, MYSQLI_ASSOC), "credential_id");
$sql_all = mysqli_query($mysqli, "SELECT * FROM logins WHERE (login_archived_at > '$service_created_at' OR login_archived_at IS NULL) AND login_client_id = $client_id");
$sql_all = mysqli_query($mysqli, "SELECT * FROM credentials WHERE (credential_archived_at > '$service_created_at' OR credential_archived_at IS NULL) AND credential_client_id = $client_id");
while ($row_all = mysqli_fetch_array($sql_all)) {
$login_id = intval($row_all['login_id']);
$login_name = nullable_htmlentities($row_all['login_name']);
$credential_id = intval($row_all['credential_id']);
$credential_name = nullable_htmlentities($row_all['credential_name']);
if (in_array($login_id, $selected_ids)) {
echo "<option value=\"$login_id\" selected>$login_name</option>";
if (in_array($credential_id, $selected_ids)) {
echo "<option value=\"$credential_id\" selected>$credential_name</option>";
}
else{
echo "<option value=\"$login_id\">$login_name</option>";
echo "<option value=\"$credential_id\">$credential_name</option>";
}
}
?>

View File

@@ -2,16 +2,16 @@
require_once '../includes/ajax_header.php';
$software_id = intval($_GET['id']);
$software_template_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_id = $software_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM software_templates WHERE software_template_id = $software_template_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$software_name = nullable_htmlentities($row['software_name']);
$software_version = nullable_htmlentities($row['software_version']);
$software_description = nullable_htmlentities($row['software_description']);
$software_type = nullable_htmlentities($row['software_type']);
$software_license_type = nullable_htmlentities($row['software_license_type']);
$software_notes = nullable_htmlentities($row['software_notes']);
$software_name = nullable_htmlentities($row['software_template_name']);
$software_version = nullable_htmlentities($row['software_template_version']);
$software_description = nullable_htmlentities($row['software_template_description']);
$software_type = nullable_htmlentities($row['software_template_type']);
$software_license_type = nullable_htmlentities($row['software_template_license_type']);
$software_notes = nullable_htmlentities($row['software_template_notes']);
// Generate the HTML form content using output buffering.
ob_start();
@@ -24,7 +24,7 @@ ob_start();
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="software_id" value="<?php echo $software_id; ?>">
<input type="hidden" name="software_template_id" value="<?php echo $software_template_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">

View File

@@ -18,12 +18,22 @@ $ticket_priority = nullable_htmlentities($row['ticket_priority']);
$ticket_billable = intval($row['ticket_billable']);
$ticket_vendor_ticket_number = nullable_htmlentities($row['ticket_vendor_ticket_number']);
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
$ticket_due_at = nullable_htmlentities($row['ticket_due_at']);
$ticket_assigned_to = intval($row['ticket_assigned_to']);
$contact_id = intval($row['ticket_contact_id']);
$asset_id = intval($row['ticket_asset_id']);
$location_id = intval($row['ticket_location_id']);
$vendor_id = intval($row['ticket_vendor_id']);
$project_id = intval($row['ticket_project_id']);
// Additional Assets Selected
$additional_assets_array = array();
$sql_additional_assets = mysqli_query($mysqli, "SELECT asset_id FROM ticket_assets WHERE ticket_id = $ticket_id");
while ($row = mysqli_fetch_array($sql_additional_assets)) {
$additional_asset_id = intval($row['asset_id']);
$additional_assets_array[] = $additional_asset_id;
}
// Generate the HTML form content using output buffering.
ob_start();
?>
@@ -67,7 +77,7 @@ ob_start();
</div>
<div class="form-group">
<textarea class="form-control tinymce" rows="8" name="details"><?php echo $ticket_details; ?></textarea>
<textarea class="form-control tinymceTicket" rows="8" name="details"><?php echo $ticket_details; ?></textarea>
</div>
<div class="row">
@@ -97,7 +107,7 @@ ob_start();
<select class="form-control select2" name="category">
<option value="0">- Uncategorized -</option>
<?php
$sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL");
$sql_categories = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Ticket' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_categories)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
@@ -120,6 +130,49 @@ ob_start();
</div>
</div>
<div class="row">
<div class="col">
<div class="form-group">
<label>Assign to</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user-check"></i></span>
</div>
<select class="form-control select2" name="assigned_to">
<option value="0">Not Assigned</option>
<?php
$sql = mysqli_query(
$mysqli,
"SELECT user_id, user_name FROM users
WHERE user_role_id > 1
AND user_type = 1
AND user_status = 1
AND user_archived_at IS NULL
ORDER BY user_name ASC"
);
while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']);
$user_name = nullable_htmlentities($row['user_name']); ?>
<option <?php if ($ticket_assigned_to === $user_id) { echo "selected"; } ?> value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
<div class="col">
<div class="form-group">
<label>Due</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar-check"></i></span>
</div>
<input type="datetime-local" class="form-control" name="due" value="<?php echo $ticket_due_at; ?>">
</div>
</div>
</div>
</div>
<?php if ($config_module_enable_accounting && lookupUserPermission("module_sales") >= 2) { ?>
<div class="form-group">
<div class="custom-control custom-switch">
@@ -212,6 +265,31 @@ ob_start();
</div>
</div>
<div class="form-group">
<label>Additional Assets</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-desktop"></i></span>
</div>
<select class="form-control select2" name="additional_assets[]" data-tags="true" data-placeholder="- Select Additional Assets -" multiple>
<option value=""></option>
<?php
$sql_assets = mysqli_query($mysqli, "SELECT asset_id, asset_name, contact_name FROM assets LEFT JOIN contacts ON contact_id = asset_contact_id WHERE asset_client_id = $client_id AND asset_id != $asset_id AND asset_archived_at IS NULL ORDER BY asset_name ASC");
while ($row = mysqli_fetch_array($sql_assets)) {
$asset_id_select = intval($row['asset_id']);
$asset_name_select = nullable_htmlentities($row['asset_name']);
$asset_contact_name_select = nullable_htmlentities($row['contact_name']);
?>
<option value="<?php echo $asset_id_select; ?>"
<?php if (in_array($asset_id_select, $additional_assets_array)) { echo "selected"; } ?>
><?php echo "$asset_name_select - $asset_contact_name_select"; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Location</label>
<div class="input-group">
@@ -250,7 +328,7 @@ ob_start();
<option value="0">- None -</option>
<?php
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id AND vendor_template = 0 AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
$sql_vendors = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
while ($row = mysqli_fetch_array($sql_vendors)) {
$vendor_id_select = intval($row['vendor_id']);
$vendor_name_select = nullable_htmlentities($row['vendor_name']);

View File

@@ -0,0 +1,47 @@
<?php
require_once '../includes/ajax_header.php';
$ticket_reply_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM ticket_replies
LEFT JOIN tickets ON ticket_id = ticket_reply_ticket_id
WHERE ticket_reply_id = $ticket_reply_id
LIMIT 1"
);
$row = mysqli_fetch_array($sql);
$ticket_reply = nullable_htmlentities($row['ticket_reply']);
$client_id = intval($row['ticket_client_id']);
// Generate the HTML form content using output buffering.
ob_start();
?>
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-edit mr-2"></i>Redacting Ticket Reply</h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="ticket_reply_id" value="<?php echo $ticket_reply_id; ?>">
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<div class="modal-body bg-white">
<div class="form-group">
<textarea class="form-control tinymceRedact" name="ticket_reply"><?php echo $ticket_reply; ?></textarea>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="redact_ticket_reply" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fa fa-times mr-2"></i>Cancel</button>
</div>
</form>
<?php
require_once "../includes/ajax_footer.php";

View File

@@ -10,7 +10,7 @@ $row = mysqli_fetch_array($sql);
$task_template_name = nullable_htmlentities($row['task_template_name']);
$task_template_order = intval($row['task_template_order']);
$task_template_completion_estimate = intval($row['task_template_completion_estimate']);
$task_template_description = nullable_htmlentities($row['task_template_description']);
//$task_template_description = nullable_htmlentities($row['task_template_description']);
// Generate the HTML form content using output buffering.
ob_start();

View File

@@ -115,7 +115,7 @@ ob_start();
$sql_users = mysqli_query($mysqli, "SELECT users.user_id, user_name FROM users
LEFT JOIN user_settings on users.user_id = user_settings.user_id
WHERE user_role > 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
WHERE user_role_id > 1 AND user_archived_at IS NULL ORDER BY user_name ASC"
);
while ($row = mysqli_fetch_array($sql_users)) {
$user_id_select = intval($row['user_id']);

View File

@@ -4,7 +4,10 @@ require_once '../includes/ajax_header.php';
$user_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM users, user_settings WHERE users.user_id = user_settings.user_id AND users.user_id = $user_id LIMIT 1");
$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']);
@@ -12,11 +15,11 @@ $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 = intval($row['user_role']);
$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_permissions WHERE user_id = $user_id");
$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']);
@@ -107,13 +110,13 @@ ob_start();
</div>
<select class="form-control select2" name="role" required>
<?php
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE user_role_archived_at IS NULL");
$sql_user_roles = mysqli_query($mysqli, "SELECT * FROM user_roles WHERE role_archived_at IS NULL");
while ($row = mysqli_fetch_array($sql_user_roles)) {
$user_role_id = intval($row['user_role_id']);
$user_role_name = nullable_htmlentities($row['user_role_name']);
$role_id = intval($row['role_id']);
$role_name = nullable_htmlentities($row['role_name']);
?>
<option <?php if ($user_role == $user_role_id) {echo "selected";} ?> value="<?php echo $user_role_id; ?>"><?php echo $user_role_name; ?></option>
<option <?php if ($role_id == $user_role_id) {echo "selected";} ?> value="<?php echo $role_id; ?>"><?php echo $role_name; ?></option>
<?php } ?>
</select>

View File

@@ -11,7 +11,8 @@ $vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_description = nullable_htmlentities($row['vendor_description']);
$vendor_account_number = nullable_htmlentities($row['vendor_account_number']);
$vendor_contact_name = nullable_htmlentities($row['vendor_contact_name']);
$vendor_phone = formatPhoneNumber($row['vendor_phone']);
$vendor_phone_country_code = nullable_htmlentities($row['vendor_phone_country_code']);
$vendor_phone = nullable_htmlentities(formatPhoneNumber($row['vendor_phone'], $vendor_phone_country_code));
$vendor_extension = nullable_htmlentities($row['vendor_extension']);
$vendor_email = nullable_htmlentities($row['vendor_email']);
$vendor_website = nullable_htmlentities($row['vendor_website']);
@@ -103,10 +104,10 @@ ob_start();
<option value="0">- None -</option>
<?php
$sql_vendor_templates = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_template = 1 AND vendor_archived_at IS NULL ORDER BY vendor_name ASC");
$sql_vendor_templates = mysqli_query($mysqli, "SELECT * FROM vendor_templates WHERE vendor_template_archived_at IS NULL ORDER BY vendor_template_name ASC");
while ($row = mysqli_fetch_array($sql_vendor_templates)) {
$vendor_template_id_select = $row['vendor_id'];
$vendor_template_name_select = nullable_htmlentities($row['vendor_name']); ?>
$vendor_template_id_select = $row['vendor_template_id'];
$vendor_template_name_select = nullable_htmlentities($row['vendor_template_name']); ?>
<option <?php if ($vendor_template_id == $vendor_template_id_select) { echo "selected"; } ?> value="<?php echo $vendor_template_id_select; ?>"><?php echo $vendor_template_name_select; ?></option>
<?php } ?>
@@ -118,20 +119,23 @@ ob_start();
<div class="tab-pane fade" id="pills-support<?php echo $vendor_id; ?>">
<label>Support Phone</label>
<label>Support Phone / <span class="text-secondary">Extension</span></label>
<div class="form-row">
<div class="col-8">
<div class="col-9">
<div class="form-group">
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $vendor_phone; ?>">
<input type="tel" class="form-control col-2" name="phone_country_code" value="<?php echo $vendor_phone_country_code; ?>" placeholder="+" maxlength="4">
<input type="tel" class="form-control" name="phone" value="<?php echo $vendor_phone; ?>" placeholder="Phone Number" maxlength="200">
</div>
</div>
</div>
<div class="col-4">
<input type="text" class="form-control" name="extension" placeholder="Prompts" maxlength="200" value="<?php echo $vendor_extension; ?>">
<div class="col-3">
<div class="form-group">
<input type="text" class="form-control" name="extension" value="<?php echo $vendor_extension; ?>" placeholder="ext." maxlength="200">
</div>
</div>
</div>

View File

@@ -2,23 +2,22 @@
require_once '../includes/ajax_header.php';
$vendor_id = intval($_GET['id']);
$vendor_template_id = intval($_GET['id']);
$sql = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_id = $vendor_id LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM vendor_templates WHERE vendor_template_id = $vendor_template_id LIMIT 1");
$row = mysqli_fetch_array($sql);
$vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_description = nullable_htmlentities($row['vendor_description']);
$vendor_account_number = nullable_htmlentities($row['vendor_account_number']);
$vendor_contact_name = nullable_htmlentities($row['vendor_contact_name']);
$vendor_phone = formatPhoneNumber($row['vendor_phone']);
$vendor_extension = nullable_htmlentities($row['vendor_extension']);
$vendor_email = nullable_htmlentities($row['vendor_email']);
$vendor_website = nullable_htmlentities($row['vendor_website']);
$vendor_hours = nullable_htmlentities($row['vendor_hours']);
$vendor_sla = nullable_htmlentities($row['vendor_sla']);
$vendor_code = nullable_htmlentities($row['vendor_code']);
$vendor_notes = nullable_htmlentities($row['vendor_notes']);
$vendor_template = intval($row['vendor_template']);
$vendor_name = nullable_htmlentities($row['vendor_template_name']);
$vendor_description = nullable_htmlentities($row['vendor_template_description']);
$vendor_account_number = nullable_htmlentities($row['vendor_template_account_number']);
$vendor_contact_name = nullable_htmlentities($row['vendor_template_contact_name']);
$vendor_phone = formatPhoneNumber($row['vendor_template_phone']);
$vendor_extension = nullable_htmlentities($row['vendor_template_extension']);
$vendor_email = nullable_htmlentities($row['vendor_template_email']);
$vendor_website = nullable_htmlentities($row['vendor_template_website']);
$vendor_hours = nullable_htmlentities($row['vendor_template_hours']);
$vendor_sla = nullable_htmlentities($row['vendor_template_sla']);
$vendor_code = nullable_htmlentities($row['vendor_template_code']);
$vendor_notes = nullable_htmlentities($row['vendor_template_notes']);
// Generate the HTML form content using output buffering.
ob_start();
@@ -31,18 +30,18 @@ ob_start();
</button>
</div>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="vendor_id" value="<?php echo $vendor_id; ?>">
<input type="hidden" name="vendor_template_id" value="<?php echo $vendor_template_id; ?>">
<div class="modal-body bg-white">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-details<?php echo $vendor_id; ?>">Details</a>
<a class="nav-link active" data-toggle="pill" href="#pills-details<?php echo $vendor_template_id; ?>">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-support<?php echo $vendor_id; ?>">Support</a>
<a class="nav-link" data-toggle="pill" href="#pills-support<?php echo $vendor_template_id; ?>">Support</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-notes<?php echo $vendor_id; ?>">Notes</a>
<a class="nav-link" data-toggle="pill" href="#pills-notes<?php echo $vendor_template_id; ?>">Notes</a>
</li>
</ul>
@@ -52,7 +51,7 @@ ob_start();
<div class="tab-content">
<div class="tab-pane fade show active" id="pills-details<?php echo $vendor_id; ?>">
<div class="tab-pane fade show active" id="pills-details<?php echo $vendor_template_id; ?>">
<div class="form-group">
@@ -117,14 +116,14 @@ ob_start();
<div class="form-group">
<div class="custom-control custom-checkbox">
<input type="checkbox" class="custom-control-input" id="updateVendorsCheckbox<?php echo $vendor_id; ?>" name="update_base_vendors" value="1" >
<label class="custom-control-label" for="updateVendorsCheckbox<?php echo $vendor_id; ?>">Update All Base Vendors</label>
<input type="checkbox" class="custom-control-input" id="updateVendorsCheckbox<?php echo $vendor_template_id; ?>" name="update_base_vendors" value="1" >
<label class="custom-control-label" for="updateVendorsCheckbox<?php echo $vendor_template_id; ?>">Update All Base Vendors</label>
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-support<?php echo $vendor_id; ?>">
<div class="tab-pane fade" id="pills-support<?php echo $vendor_template_id; ?>">
<label>Support Phone</label>
<div class="form-row">
@@ -134,7 +133,7 @@ ob_start();
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-phone"></i></span>
</div>
<input type="text" class="form-control" name="phone" placeholder="Phone Number" maxlength="200" value="<?php echo $vendor_phone; ?>">
<input type="tel" class="form-control" name="phone" value="<?php echo $vendor_phone; ?>">
<div class="input-group-append">
<div class="input-group-text">
<input type="checkbox" name="global_update_vendor_phone" value="1">
@@ -225,7 +224,7 @@ ob_start();
</div>
<div class="tab-pane fade" id="pills-notes<?php echo $vendor_id; ?>">
<div class="tab-pane fade" id="pills-notes<?php echo $vendor_template_id; ?>">
<div class="form-group">
<textarea class="form-control" rows="8" placeholder="Enter some notes" name="notes"><?php echo $vendor_notes; ?></textarea>

View File

@@ -13,7 +13,7 @@ $insert_id = false;
if (!empty($api_key_decrypt_password) && !empty($name) && !(empty($password))) {
// Add credential
$insert_sql = mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id, login_client_id = $client_id");
$insert_sql = mysqli_query($mysqli,"INSERT INTO credentials SET credential_name = '$name', credential_description = '$description', credential_uri = '$uri', credential_uri_2 = '$uri_2', credential_username = '$username', credential_password = '$password', credential_otp_secret = '$otp_secret', credential_note = '$note', credential_important = $important, credential_contact_id = $contact_id, credential_vendor_id = $vendor_id, credential_asset_id = $asset_id, credential_software_id = $software_id, credential_client_id = $client_id");
// Check insert & get insert ID
if ($insert_sql) {

View File

@@ -8,53 +8,53 @@ if (isset($_POST['api_key_decrypt_password'])) {
$api_key_decrypt_password = $_POST['api_key_decrypt_password']; // No sanitization
}
if (isset($_POST['login_name'])) {
$name = sanitizeInput($_POST['login_name']);
} elseif (isset($credential_row) && isset($credential_row['login_name'])) {
$name = $credential_row['login_name'];
if (isset($_POST['credential_name'])) {
$name = sanitizeInput($_POST['credential_name']);
} elseif (isset($credential_row) && isset($credential_row['credential_name'])) {
$name = $credential_row['credential_name'];
} else {
$name = '';
}
if (isset($_POST['login_description'])) {
$description = sanitizeInput($_POST['login_description']);
} elseif (isset($credential_row) && isset($credential_row['login_description'])) {
$description = $credential_row['login_description'];
if (isset($_POST['credential_description'])) {
$description = sanitizeInput($_POST['credential_description']);
} elseif (isset($credential_row) && isset($credential_row['credential_description'])) {
$description = $credential_row['credential_description'];
} else {
$description = '';
}
if (isset($_POST['login_uri'])) {
$uri = sanitizeInput($_POST['login_uri']);
} elseif (isset($credential_row) && isset($credential_row['login_uri'])) {
$uri = $credential_row['login_uri'];
if (isset($_POST['credential_uri'])) {
$uri = sanitizeInput($_POST['credential_uri']);
} elseif (isset($credential_row) && isset($credential_row['credential_uri'])) {
$uri = $credential_row['credential_uri'];
} else {
$uri = '';
}
if (isset($_POST['login_uri_2'])) {
$uri_2 = sanitizeInput($_POST['login_uri_2']);
} elseif (isset($credential_row) && isset($credential_row['login_uri_2'])) {
$uri_2 = $credential_row['login_uri_2'];
if (isset($_POST['credential_uri_2'])) {
$uri_2 = sanitizeInput($_POST['credential_uri_2']);
} elseif (isset($credential_row) && isset($credential_row['credential_uri_2'])) {
$uri_2 = $credential_row['credential_uri_2'];
} else {
$uri_2 = '';
}
if (isset($_POST['login_username'])) {
$username = $_POST['login_username'];
if (isset($_POST['credential_username'])) {
$username = $_POST['credential_username'];
$username = apiEncryptLoginEntry($username, $api_key_decrypt_hash, $api_key_decrypt_password);
} elseif (isset($credential_row) && isset($credential_row['login_username'])) {
$username = $credential_row['login_username'];
} elseif (isset($credential_row) && isset($credential_row['credential_username'])) {
$username = $credential_row['credential_username'];
} else {
$username = '';
}
if (isset($_POST['login_password'])) {
$password = $_POST['login_password'];
if (isset($_POST['credential_password'])) {
$password = $_POST['credential_password'];
$password = apiEncryptLoginEntry($password, $api_key_decrypt_hash, $api_key_decrypt_password);
$password_changed = true;
} elseif (isset($credential_row) && isset($credential_row['login_password'])) {
$password = $credential_row['login_password'];
} elseif (isset($credential_row) && isset($credential_row['credential_password'])) {
$password = $credential_row['credential_password'];
$password_changed = false;
} else {
$password = '';
@@ -63,58 +63,58 @@ if (isset($_POST['login_password'])) {
if (isset($_POST['login_otp_secret'])) {
$otp_secret = sanitizeInput($_POST['login_otp_secret']);
} elseif (isset($credential_row) && isset($credential_row['login_otp_secret'])) {
$otp_secret = $credential_row['login_otp_secret'];
if (isset($_POST['credential_otp_secret'])) {
$otp_secret = sanitizeInput($_POST['credential_otp_secret']);
} elseif (isset($credential_row) && isset($credential_row['credential_otp_secret'])) {
$otp_secret = $credential_row['credential_otp_secret'];
} else {
$otp_secret = '';
}
if (isset($_POST['login_note'])) {
$note = sanitizeInput($_POST['login_note']);
} elseif (isset($credential_row) && isset($credential_row['login_note'])) {
$note = $credential_row['login_note'];
if (isset($_POST['credential_note'])) {
$note = sanitizeInput($_POST['credential_note']);
} elseif (isset($credential_row) && isset($credential_row['credential_note'])) {
$note = $credential_row['credential_note'];
} else {
$note = '';
}
if (isset($_POST['login_important'])) {
$important = intval($_POST['login_important']);
} elseif (isset($credential_row) && isset($credential_row['login_important'])) {
$important = $credential_row['login_important'];
if (isset($_POST['credential_important'])) {
$important = intval($_POST['credential_important']);
} elseif (isset($credential_row) && isset($credential_row['credential_important'])) {
$important = $credential_row['credential_important'];
} else {
$important = '';
}
if (isset($_POST['login_contact_id'])) {
$contact_id = intval($_POST['login_contact_id']);
} elseif (isset($credential_row) && isset($credential_row['login_contact_id'])) {
$contact_id = $credential_row['login_contact_id'];
if (isset($_POST['credential_contact_id'])) {
$contact_id = intval($_POST['credential_contact_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_contact_id'])) {
$contact_id = $credential_row['credential_contact_id'];
} else {
$contact_id = '';
}
if (isset($_POST['login_vendor_id'])) {
$vendor_id = intval($_POST['login_vendor_id']);
} elseif (isset($credential_row) && isset($credential_row['login_vendor_id'])) {
$vendor_id = $credential_row['login_vendor_id'];
if (isset($_POST['credential_vendor_id'])) {
$vendor_id = intval($_POST['credential_vendor_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_vendor_id'])) {
$vendor_id = $credential_row['credential_vendor_id'];
} else {
$vendor_id = '';
}
if (isset($_POST['login_asset_id'])) {
$asset_id = intval($_POST['login_asset_id']);
} elseif (isset($credential_row) && isset($credential_row['login_asset_id'])) {
$asset_id = $credential_row['login_asset_id'];
if (isset($_POST['credential_asset_id'])) {
$asset_id = intval($_POST['credential_asset_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_asset_id'])) {
$asset_id = $credential_row['credential_asset_id'];
} else {
$asset_id = '';
}
if (isset($_POST['login_software_id'])) {
$software_id = intval($_POST['login_software_id']);
} elseif (isset($credential_row) && isset($credential_row['login_software_id'])) {
$software_id = $credential_row['login_software_id'];
if (isset($_POST['credential_software_id'])) {
$software_id = intval($_POST['credential_software_id']);
} elseif (isset($credential_row) && isset($credential_row['credential_software_id'])) {
$software_id = $credential_row['credential_software_id'];
} else {
$software_id = '';
}

View File

@@ -13,17 +13,17 @@ if (isset($_GET['api_key_decrypt_password'])) {
}
// Specific credential/login via ID (single)
if (isset($_GET['login_id']) && !empty($api_key_decrypt_password)) {
if (isset($_GET['credential_id']) && !empty($api_key_decrypt_password)) {
$id = intval($_GET['login_id']);
$id = intval($_GET['credential_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = '$id' AND login_client_id LIKE '$client_id' LIMIT 1");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = '$id' AND credential_client_id LIKE '$client_id' LIMIT 1");
} elseif (!empty($api_key_decrypt_password)) {
// All credentials ("logins")
// All credentials ("credentials")
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_client_id LIKE '$client_id' ORDER BY login_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_client_id LIKE '$client_id' ORDER BY credential_id LIMIT $limit OFFSET $offset");
}
@@ -37,8 +37,8 @@ if ($sql && mysqli_num_rows($sql) > 0) {
$row = array();
while ($row = mysqli_fetch_array($sql)) {
$row['login_username'] = apiDecryptLoginEntry($row['login_username'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['login_password'] = apiDecryptLoginEntry($row['login_password'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['credential_username'] = apiDecryptCredentialEntry($row['credential_username'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['credential_password'] = apiDecryptCredentialEntry($row['credential_password'], $api_key_decrypt_hash, $api_key_decrypt_password);
$return_arr['data'][] = $row;
}

View File

@@ -5,30 +5,30 @@ require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse ID
$login_id = intval($_POST['login_id']);
$credential_id = intval($_POST['credential_id']);
// Default
$update_count = false;
if (!empty($_POST['api_key_decrypt_password']) && !empty($login_id)) {
if (!empty($_POST['api_key_decrypt_password']) && !empty($credential_id)) {
$credential_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = '$login_id' AND login_client_id = $client_id LIMIT 1"));
$credential_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_id = '$credential_id' AND credential_client_id = $client_id LIMIT 1"));
// Variable assignment from POST - assigning the current database value if a value is not provided
require_once 'credential_model.php';
$update_sql = mysqli_query($mysqli,"UPDATE logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id, login_client_id = $client_id WHERE login_id = '$login_id' AND login_client_id = $client_id LIMIT 1");
$update_sql = mysqli_query($mysqli,"UPDATE credentials SET credential_name = '$name', credential_description = '$description', credential_uri = '$uri', credential_uri_2 = '$uri_2', credential_username = '$username', credential_password = '$password', credential_otp_secret = '$otp_secret', credential_note = '$note', credential_important = $important, credential_contact_id = $contact_id, credential_vendor_id = $vendor_id, credential_asset_id = $asset_id, credential_software_id = $software_id, credential_client_id = $client_id WHERE credential_id = '$credential_id' AND credential_client_id = $client_id LIMIT 1");
// Check insert & get insert ID
if ($update_sql) {
$update_count = mysqli_affected_rows($mysqli);
if ($password_changed) {
mysqli_query($mysqli, "UPDATE logins SET login_password_changed_at = NOW() WHERE login_id = $login_id LIMIT 1");
mysqli_query($mysqli, "UPDATE credentials SET credential_password_changed_at = NOW() WHERE credential_id = $credential_id LIMIT 1");
}
// Logging
logAction("Credential", "Edit", "$name via API ($api_key_name)", $client_id, $login_id);
logAction("Credential", "Edit", "$name via API ($api_key_name)", $client_id, $credential_id);
logAction("API", "Success", "Updated credential $name via API ($api_key_name)", $client_id);
}

View File

@@ -13,15 +13,12 @@ $insert_id = false;
if (!empty($name) && !(empty($content))) {
// Create document
$insert_sql = mysqli_query($mysqli,"INSERT INTO documents SET document_name = '$name', document_description = '$description', document_content = '$content', document_content_raw = '$content_raw', document_template = 0, document_folder_id = $folder, document_created_by = 0, document_client_id = $client_id");
$insert_sql = mysqli_query($mysqli,"INSERT INTO documents SET document_name = '$name', document_description = '$description', document_content = '$content', document_content_raw = '$content_raw', document_folder_id = $folder, document_created_by = 0, document_client_id = $client_id");
// Check insert & get insert ID
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);
// Update field document_parent to be the same id as document ID as this is the only version of the document.
mysqli_query($mysqli,"UPDATE documents SET document_parent = $insert_id WHERE document_id = $insert_id");
// Logging
logAction("Document", "Create", "$name via API ($api_key_name)", $client_id, $insert_id);
logAction("API", "Success", "Created document $name via API ($api_key_name)", $client_id);

View File

@@ -18,34 +18,12 @@ if (!empty($document_id)) {
require_once 'document_model.php';
// Documents are a little weird as we update them by *inserting* a new document row
$update_insert_sql = mysqli_query($mysqli,"INSERT INTO documents SET document_name = '$name', document_description = '$description', document_content = '$content', document_content_raw = '$content_raw', document_template = 0, document_folder_id = $folder, document_created_by = 0, document_client_id = $client_id");
$update_insert_sql = mysqli_query($mysqli,"INSERT INTO documents SET document_name = '$name', document_description = '$description', document_content = '$content', document_content_raw = '$content_raw', document_folder_id = $folder, document_created_by = 0, document_client_id = $client_id");
// Check insert & get insert ID
if ($update_insert_sql) {
$insert_id = $new_document_id = mysqli_insert_id($mysqli);
// Update the parent ID of the new document to match its new document ID
mysqli_query($mysqli,"UPDATE documents SET document_parent = $new_document_id WHERE document_id = $new_document_id");
// Link all existing links with old document with new document
mysqli_query($mysqli,"UPDATE documents SET document_parent = $new_document_id, document_archived_at = NOW() WHERE document_parent = $document_id");
// Update Links to the new parent document:-
// Document files
mysqli_query($mysqli,"UPDATE document_files SET document_id = $new_document_id WHERE document_id = $document_id");
// Contact documents
mysqli_query($mysqli,"UPDATE contact_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// Asset documents
mysqli_query($mysqli,"UPDATE asset_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// Software documents
mysqli_query($mysqli,"UPDATE software_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// Vendor documents
mysqli_query($mysqli,"UPDATE vendor_documents SET document_id = $new_document_id WHERE document_id = $document_id");
// Logging
logAction("Document", "Edit", "$name via API ($api_key_name) previous version kept", $client_id, $insert_id);
logAction("API", "Success", "Edited document $name via API ($api_key_name)", $client_id);

View File

@@ -5,7 +5,7 @@ require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Ticket-related settings
require_once "../../../get_settings.php";
require_once "../../../includes/get_settings.php";
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
@@ -39,7 +39,7 @@ if (!empty($subject)) {
// Insert ticket
$url_key = randomString(156);
$insert_sql = mysqli_query($mysqli,"INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_vendor_ticket_number = '$vendor_ticket_number', ticket_vendor_id = $vendor_id, ticket_created_by = 0, ticket_assigned_to = $assigned_to, ticket_contact_id = $contact, ticket_url_key = '$url_key', ticket_client_id = $client_id");
$insert_sql = mysqli_query($mysqli,"INSERT INTO tickets SET ticket_prefix = '$config_ticket_prefix', ticket_number = $ticket_number, ticket_source = 'API', ticket_subject = '$subject', ticket_details = '$details', ticket_priority = '$priority', ticket_status = 1, ticket_billable = $billable, ticket_vendor_ticket_number = '$vendor_ticket_number', ticket_vendor_id = $vendor_id, ticket_created_by = 0, ticket_assigned_to = $assigned_to, ticket_contact_id = $contact, ticket_url_key = '$url_key', ticket_client_id = $client_id");
// Check insert & get insert ID
if ($insert_sql) {

View File

@@ -59,3 +59,11 @@ if (isset($_POST['ticket_assigned_to'])) {
} else {
$assigned_to = '0';
}
if (isset($_POST['ticket_billable'])) {
$billable = intval($_POST['ticket_billable']);
} elseif ($ticket_row) {
$billable = $ticket_row['ticket_billable'];
} else {
$billable = '0';
}

View File

@@ -34,8 +34,8 @@ if (isset($_GET['asset_id'])) {
$asset_model = nullable_htmlentities($row['asset_model']);
$asset_serial = nullable_htmlentities($row['asset_serial']);
$asset_os = nullable_htmlentities($row['asset_os']);
$asset_uri = nullable_htmlentities($row['asset_uri']);
$asset_uri_2 = nullable_htmlentities($row['asset_uri_2']);
$asset_uri = sanitize_url($row['asset_uri']);
$asset_uri_2 = sanitize_url($row['asset_uri_2']);
$asset_status = nullable_htmlentities($row['asset_status']);
$asset_purchase_reference = nullable_htmlentities($row['asset_purchase_reference']);
$asset_purchase_date = nullable_htmlentities($row['asset_purchase_date']);
@@ -81,19 +81,24 @@ if (isset($_GET['asset_id'])) {
// Override Tab Title // No Sanitizing needed as this var will opnly be used in the tab title
$page_title = $row['asset_name'];
// Related Tickets Query
$sql_related_tickets = mysqli_query($mysqli, "SELECT * FROM tickets
LEFT JOIN users on ticket_assigned_to = user_id
$sql_related_tickets = mysqli_query($mysqli, "
SELECT tickets.*, users.*, ticket_statuses.*
FROM tickets
LEFT JOIN users ON ticket_assigned_to = user_id
LEFT JOIN ticket_statuses ON ticket_status_id = ticket_status
WHERE ticket_asset_id = $asset_id
ORDER BY ticket_number DESC"
);
LEFT JOIN ticket_assets ON tickets.ticket_id = ticket_assets.ticket_id
WHERE ticket_asset_id = $asset_id OR ticket_assets.asset_id = $asset_id
GROUP BY tickets.ticket_id
ORDER BY ticket_number DESC
");
$ticket_count = mysqli_num_rows($sql_related_tickets);
// Related Recurring Tickets Query
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_asset_id = $asset_id
ORDER BY scheduled_ticket_next_run DESC"
$sql_related_recurring_tickets = mysqli_query($mysqli, "SELECT recurring_tickets.* FROM recurring_tickets
LEFT JOIN recurring_ticket_assets ON recurring_tickets.recurring_ticket_id = recurring_ticket_assets.recurring_ticket_id
WHERE recurring_ticket_asset_id = $asset_id OR recurring_ticket_assets.asset_id = $asset_id
GROUP BY recurring_tickets.recurring_ticket_id
ORDER BY recurring_ticket_next_run DESC"
);
$recurring_ticket_count = mysqli_num_rows($sql_related_recurring_tickets);
@@ -172,36 +177,35 @@ if (isset($_GET['asset_id'])) {
LEFT JOIN users ON document_created_by = user_id
WHERE asset_documents.asset_id = $asset_id
AND asset_documents.document_id = documents.document_id
AND document_template = 0
AND document_archived_at IS NULL
ORDER BY document_name ASC"
);
$document_count = mysqli_num_rows($sql_related_documents);
// Related Logins Query
$sql_related_logins = mysqli_query($mysqli, "
// Related Credentials Query
$sql_related_credentials = mysqli_query($mysqli, "
SELECT
logins.login_id AS login_id,
logins.login_name,
logins.login_description,
logins.login_uri,
logins.login_username,
logins.login_password,
logins.login_otp_secret,
logins.login_note,
logins.login_important,
logins.login_contact_id,
logins.login_asset_id
FROM logins
LEFT JOIN login_tags ON login_tags.login_id = logins.login_id
LEFT JOIN tags ON tags.tag_id = login_tags.tag_id
WHERE login_asset_id = $asset_id
AND login_archived_at IS NULL
GROUP BY logins.login_id
ORDER BY login_name DESC
credentials.credential_id AS credential_id,
credentials.credential_name,
credentials.credential_description,
credentials.credential_uri,
credentials.credential_username,
credentials.credential_password,
credentials.credential_otp_secret,
credentials.credential_note,
credentials.credential_important,
credentials.credential_contact_id,
credentials.credential_asset_id
FROM credentials
LEFT JOIN credential_tags ON credential_tags.credential_id = credentials.credential_id
LEFT JOIN tags ON tags.tag_id = credential_tags.tag_id
WHERE credential_asset_id = $asset_id
AND credential_archived_at IS NULL
GROUP BY credentials.credential_id
ORDER BY credential_name DESC
");
$login_count = mysqli_num_rows($sql_related_logins);
$credential_count = mysqli_num_rows($sql_related_credentials);
// Related Software Query
$sql_related_software = mysqli_query(
@@ -239,7 +243,7 @@ if (isset($_GET['asset_id'])) {
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fas fa-fw fa-edit"></i>
</button>
<h3 class="text-bold"><i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-3"></i><?php echo $asset_name; ?></h3>
<h4 class="text-bold"><i class="fa fa-fw text-secondary fa-<?php echo $device_icon; ?> mr-3"></i><?php echo $asset_name; ?></h4>
<?php if ($asset_photo) { ?>
<img class="img-fluid img-circle p-3" alt="asset_photo" src="<?php echo "uploads/clients/$client_id/$asset_photo"; ?>">
<?php } ?>
@@ -278,19 +282,19 @@ if (isset($_GET['asset_id'])) {
</div>
<div class="card-body">
<?php if ($asset_ip) { ?>
<div><i class="fa fa-fw fa-globe text-secondary mr-3"></i><?php echo $asset_ip; ?></div>
<div><i class="fa fa-fw fa-globe text-secondary mr-2"></i><?php echo $asset_ip; ?></div>
<?php } ?>
<?php if ($asset_nat_ip) { ?>
<div class="mt-2"><i class="fa fa-fw fa-random text-secondary mr-3"></i><?php echo $asset_nat_ip; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-random text-secondary mr-2"></i><?php echo $asset_nat_ip; ?></div>
<?php }
if ($asset_mac) { ?>
<div class="mt-2"><i class="fa fa-fw fa-ethernet text-secondary mr-3"></i><?php echo $asset_mac; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-ethernet text-secondary mr-2"></i><?php echo $asset_mac; ?></div>
<?php }
if ($asset_uri) { ?>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-3"></i><a href="<?php echo $asset_uri; ?>" target="_blank">Link</a></div>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-2"></i><a href="<?php echo $asset_uri; ?>" target="_blank" title="<?php echo $asset_uri; ?>"><?php echo truncate($asset_uri, 20); ?></a></div>
<?php }
if ($asset_uri_2) { ?>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-3"></i><a href="<?php echo $asset_uri_2; ?>" target="_blank">Link 2</a></div>
<div class="mt-2"><i class="fa fa-fw fa-link text-secondary mr-2"></i><a href="<?php echo $asset_uri_2; ?>" target="_blank" title="<?php echo $asset_uri_2; ?>"><?php echo truncate($asset_uri_2, 20); ?></a></div>
<?php } ?>
</div>
</div>
@@ -302,19 +306,19 @@ if (isset($_GET['asset_id'])) {
</div>
<div class="card-body">
<?php if ($location_name) { ?>
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-3"></i><?php echo $location_name_display; ?></div>
<div><i class="fa fa-fw fa-map-marker-alt text-secondary mr-2"></i><?php echo $location_name_display; ?></div>
<?php }
if ($contact_name) { ?>
<div class="mt-2"><i class="fa fa-fw fa-user text-secondary mr-3"></i><?php echo $contact_name_display; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-user text-secondary mr-2"></i><?php echo $contact_name_display; ?></div>
<?php }
if ($contact_email) { ?>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-3"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<div class="mt-2"><i class="fa fa-fw fa-envelope text-secondary mr-2"></i><a href='mailto:<?php echo $contact_email; ?>'><?php echo $contact_email; ?></a><button class='btn btn-sm clipboardjs' data-clipboard-text='<?php echo $contact_email; ?>'><i class='far fa-copy text-secondary'></i></button></div>
<?php }
if ($contact_phone) { ?>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-3"></i><?php echo formatPhoneNumber($contact_phone); echo " $contact_extension"; ?></div>
<div class="mt-2"><i class="fa fa-fw fa-phone text-secondary mr-2"></i><?php echo formatPhoneNumber($contact_phone); echo " $contact_extension"; ?></div>
<?php }
if ($contact_mobile) { ?>
<div class="mt-2"><i class="fa fa-fw fa-mobile-alt text-secondary mr-3"></i><?php echo formatPhoneNumber($contact_mobile); ?></div>
<div class="mt-2"><i class="fa fa-fw fa-mobile-alt text-secondary mr-2"></i><?php echo formatPhoneNumber($contact_mobile); ?></div>
<?php } ?>
</div>
@@ -356,8 +360,16 @@ if (isset($_GET['asset_id'])) {
<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="#createContactNoteModal<?php echo $contact_id; ?>">
<i class="fa fa-fw fa-sticky-note mr-2"></i>New Note (WIP)
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#addCredentialModal">
<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">
<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">
<i class="fa fa-fw fa-upload mr-2"></i>Upload file(s)
</a>
</div>
</div>
@@ -365,34 +377,47 @@ if (isset($_GET['asset_id'])) {
<div class="dropdown dropleft">
<button type="button" class="btn btn-outline-primary" data-toggle="dropdown"><i class="fas fa-link mr-2"></i>Link</button>
<div class="dropdown-menu">
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkSoftwareModal">
<a class="dropdown-item text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_asset_link_software.php"
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fa fa-fw fa-cube mr-2"></i>License
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkCredentialModal">
<a class="dropdown-item text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_asset_link_credential.php"
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fa fa-fw fa-key mr-2"></i>Credential
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkServiceModal">
<a class="dropdown-item text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_asset_link_service.php"
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fa fa-fw fa-stream mr-2"></i>Service
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkDocumentModal">
<a class="dropdown-item text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_asset_link_document.php"
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fa fa-fw fa-folder mr-2"></i>Document
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#linkFileModal">
<a class="dropdown-item text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_asset_link_file.php"
data-ajax-id="<?php echo $asset_id; ?>">
<i class="fa fa-fw fa-paperclip mr-2"></i>File
</a>
</div>
</div>
</div>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-ethernet mr-2"></i><?php echo $asset_name; ?> Network Interfaces</h3>
<h3 class="card-title mt-2"><i class="fa fa-fw fa-ethernet mr-2"></i>Interfaces</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addAssetInterfaceModal">
@@ -518,7 +543,7 @@ if (isset($_GET['asset_id'])) {
</div>
</div>
<div class="card card-dark <?php if ($login_count == 0) { echo "d-none"; } ?>">
<div class="card card-dark <?php if ($credential_count == 0) { echo "d-none"; } ?>">
<div class="card-header">
<h3 class="card-title"><i class="fa fa-fw fa-key mr-2"></i>Credentials</h3>
</div>
@@ -539,56 +564,56 @@ if (isset($_GET['asset_id'])) {
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_related_logins)) {
$login_id = intval($row['login_id']);
$login_name = nullable_htmlentities($row['login_name']);
$login_description = nullable_htmlentities($row['login_description']);
$login_uri = nullable_htmlentities($row['login_uri']);
if (empty($login_uri)) {
$login_uri_display = "-";
while ($row = mysqli_fetch_array($sql_related_credentials)) {
$credential_id = intval($row['credential_id']);
$credential_name = nullable_htmlentities($row['credential_name']);
$credential_description = nullable_htmlentities($row['credential_description']);
$credential_uri = nullable_htmlentities($row['credential_uri']);
if (empty($credential_uri)) {
$credential_uri_display = "-";
} else {
$login_uri_display = "$login_uri<button class='btn btn-sm clipboardjs' data-clipboard-text='$login_uri'><i class='far fa-copy text-secondary'></i></button><a href='$login_uri' target='_blank'><i class='fa fa-external-link-alt text-secondary'></i></a>";
$credential_uri_display = "$credential_uri<button class='btn btn-sm clipboardjs' data-clipboard-text='$credential_uri'><i class='far fa-copy text-secondary'></i></button><a href='$credential_uri' target='_blank'><i class='fa fa-external-link-alt text-secondary'></i></a>";
}
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
if (empty($login_username)) {
$login_username_display = "-";
$credential_username = nullable_htmlentities(decryptCredentialEntry($row['credential_username']));
if (empty($credential_username)) {
$credential_username_display = "-";
} else {
$login_username_display = "$login_username<button class='btn btn-sm clipboardjs' data-clipboard-text='$login_username'><i class='far fa-copy text-secondary'></i></button>";
$credential_username_display = "$credential_username<button class='btn btn-sm clipboardjs' data-clipboard-text='$credential_username'><i class='far fa-copy text-secondary'></i></button>";
}
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
$login_otp_secret = nullable_htmlentities($row['login_otp_secret']);
$login_id_with_secret = '"' . $row['login_id'] . '","' . $row['login_otp_secret'] . '"';
if (empty($login_otp_secret)) {
$credential_password = nullable_htmlentities(decryptCredentialEntry($row['credential_password']));
$credential_otp_secret = nullable_htmlentities($row['credential_otp_secret']);
$credential_id_with_secret = '"' . $row['credential_id'] . '","' . $row['credential_otp_secret'] . '"';
if (empty($credential_otp_secret)) {
$otp_display = "-";
} else {
$otp_display = "<span onmouseenter='showOTPViaLoginID($login_id)'><i class='far fa-clock'></i> <span id='otp_$login_id'><i>Hover..</i></span></span>";
$otp_display = "<span onmouseenter='showOTPViaCredentialID($credential_id)'><i class='far fa-clock'></i> <span id='otp_$credential_id'><i>Hover..</i></span></span>";
}
$login_note = nullable_htmlentities($row['login_note']);
$login_important = intval($row['login_important']);
$login_contact_id = intval($row['login_contact_id']);
$login_asset_id = intval($row['login_asset_id']);
$credential_note = nullable_htmlentities($row['credential_note']);
$credential_important = intval($row['credential_important']);
$credential_contact_id = intval($row['credential_contact_id']);
$credential_asset_id = intval($row['credential_asset_id']);
// Tags
$login_tag_name_display_array = array();
$login_tag_id_array = array();
$sql_login_tags = mysqli_query($mysqli, "SELECT * FROM login_tags LEFT JOIN tags ON login_tags.tag_id = tags.tag_id WHERE login_id = $login_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_login_tags)) {
$credential_tag_name_display_array = array();
$credential_tag_id_array = array();
$sql_credential_tags = mysqli_query($mysqli, "SELECT * FROM credential_tags LEFT JOIN tags ON credential_tags.tag_id = tags.tag_id WHERE credential_id = $credential_id ORDER BY tag_name ASC");
while ($row = mysqli_fetch_array($sql_credential_tags)) {
$login_tag_id = intval($row['tag_id']);
$login_tag_name = nullable_htmlentities($row['tag_name']);
$login_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($login_tag_color)) {
$login_tag_color = "dark";
$credential_tag_id = intval($row['tag_id']);
$credential_tag_name = nullable_htmlentities($row['tag_name']);
$credential_tag_color = nullable_htmlentities($row['tag_color']);
if (empty($credential_tag_color)) {
$credential_tag_color = "dark";
}
$login_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($login_tag_icon)) {
$login_tag_icon = "tag";
$credential_tag_icon = nullable_htmlentities($row['tag_icon']);
if (empty($credential_tag_icon)) {
$credential_tag_icon = "tag";
}
$login_tag_id_array[] = $login_tag_id;
$login_tag_name_display_array[] = "<a href='client_logins.php?client_id=$client_id&tags[]=$login_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $login_tag_color;'><i class='fa fa-fw fa-$login_tag_icon mr-2'></i>$login_tag_name</span></a>";
$credential_tag_id_array[] = $credential_tag_id;
$credential_tag_name_display_array[] = "<a href='credentials.php?client_id=$client_id&tags[]=$credential_tag_id'><span class='badge text-light p-1 mr-1' style='background-color: $credential_tag_color;'><i class='fa fa-fw fa-$credential_tag_icon mr-2'></i>$credential_tag_name</span></a>";
}
$login_tags_display = implode('', $login_tag_name_display_array);
$credential_tags_display = implode('', $credential_tag_name_display_array);
?>
<tr>
@@ -597,18 +622,18 @@ if (isset($_GET['asset_id'])) {
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<?php echo $login_name; ?>
<?php echo $credential_name; ?>
</a>
</td>
<td><?php echo $login_description; ?></td>
<td><?php echo $login_username_display; ?></td>
<td><?php echo $credential_description; ?></td>
<td><?php echo $credential_username_display; ?></td>
<td>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $login_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $login_password; ?>"><i class="far fa-copy text-secondary"></i></button>
<button class="btn p-0" type="button" data-toggle="popover" data-trigger="focus" data-placement="top" data-content="<?php echo $credential_password; ?>"><i class="fas fa-2x fa-ellipsis-h text-secondary"></i><i class="fas fa-2x fa-ellipsis-h text-secondary"></i></button><button class="btn btn-sm clipboardjs" data-clipboard-text="<?php echo $credential_password; ?>"><i class="far fa-copy text-secondary"></i></button>
</td>
<td><?php echo $otp_display; ?></td>
<td><?php echo $login_uri_display; ?></td>
<td><?php echo $credential_uri_display; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -618,20 +643,20 @@ if (isset($_GET['asset_id'])) {
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-ajax-url="ajax/ajax_credential_edit.php"
data-ajax-id="<?php echo $login_id; ?>"
data-ajax-id="<?php echo $credential_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Login', $login_id"; ?>)">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#shareModal" onclick="populateShareModal(<?php echo "$client_id, 'Credential', $credential_id"; ?>)">
<i class="fas fa-fw fa-share-alt mr-2"></i>Share
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?unlink_credential_from_asset&asset_id=<?php echo $asset_id; ?>&login_id=<?php echo $login_id; ?>">
<a class="dropdown-item" href="post.php?unlink_credential_from_asset&asset_id=<?php echo $asset_id; ?>&credential_id=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-unlink mr-2"></i>Unlink
</a>
<?php if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold" href="post.php?delete_login=<?php echo $login_id; ?>">
<a class="dropdown-item text-danger text-bold" href="post.php?delete_credential=<?php echo $credential_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
@@ -686,11 +711,6 @@ if (isset($_GET['asset_id'])) {
$seat_count = 0;
// Get Login
$login_id = intval($row['login_id']);
$login_username = nullable_htmlentities(decryptLoginEntry($row['login_username']));
$login_password = nullable_htmlentities(decryptLoginEntry($row['login_password']));
// Asset Licenses
$asset_licenses_sql = mysqli_query($mysqli, "SELECT asset_id FROM software_assets WHERE software_id = $software_id");
$asset_licenses_array = array();
@@ -917,29 +937,30 @@ if (isset($_GET['asset_id'])) {
<?php
while ($row = mysqli_fetch_array($sql_related_recurring_tickets)) {
$scheduled_ticket_id = intval($row['scheduled_ticket_id']);
$scheduled_ticket_subject = nullable_htmlentities($row['scheduled_ticket_subject']);
$scheduled_ticket_priority = nullable_htmlentities($row['scheduled_ticket_priority']);
$scheduled_ticket_frequency = nullable_htmlentities($row['scheduled_ticket_frequency']);
$scheduled_ticket_next_run = nullable_htmlentities($row['scheduled_ticket_next_run']);
$recurring_ticket_id = intval($row['recurring_ticket_id']);
$recurring_ticket_subject = nullable_htmlentities($row['recurring_ticket_subject']);
$recurring_ticket_priority = nullable_htmlentities($row['recurring_ticket_priority']);
$recurring_ticket_frequency = nullable_htmlentities($row['recurring_ticket_frequency']);
$recurring_ticket_next_run = nullable_htmlentities($row['recurring_ticket_next_run']);
?>
<tr>
<td class="text-bold">
<a href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_recurring_ticket_edit.php"
data-ajax-id="<?php echo $scheduled_ticket_id; ?>"
data-ajax-id="<?php echo $recurring_ticket_id; ?>"
>
<?php echo $scheduled_ticket_subject ?>
<?php echo $recurring_ticket_subject ?>
</a>
</td>
<td><?php echo $scheduled_ticket_priority ?></td>
<td><?php echo $recurring_ticket_priority ?></td>
<td><?php echo $scheduled_ticket_frequency ?></td>
<td><?php echo $recurring_ticket_frequency ?></td>
<td><?php echo $scheduled_ticket_next_run ?></td>
<td><?php echo $recurring_ticket_next_run ?></td>
<td>
<div class="dropdown dropleft text-center">
@@ -949,19 +970,20 @@ if (isset($_GET['asset_id'])) {
<div class="dropdown-menu">
<a class="dropdown-item" href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_recurring_ticket_edit.php"
data-ajax-id="<?php echo $scheduled_ticket_id; ?>"
data-ajax-id="<?php echo $recurring_ticket_id; ?>"
>
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $scheduled_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<a class="dropdown-item" href="post.php?force_recurring_ticket=<?php echo $recurring_ticket_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fa fa-fw fa-paper-plane text-secondary mr-2"></i>Force Reoccur
</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_recurring_ticket=<?php echo $scheduled_ticket_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_recurring_ticket=<?php echo $recurring_ticket_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
@@ -1005,12 +1027,13 @@ if (isset($_GET['asset_id'])) {
$ticket_number = intval($row['ticket_number']);
$ticket_subject = nullable_htmlentities($row['ticket_subject']);
$ticket_priority = nullable_htmlentities($row['ticket_priority']);
$ticket_status_id = intval($row['ticket_status_id']);
$ticket_status_name = nullable_htmlentities($row['ticket_status_name']);
$ticket_status_color = nullable_htmlentities($row['ticket_status_color']);
$ticket_created_at = nullable_htmlentities($row['ticket_created_at']);
$ticket_updated_at = nullable_htmlentities($row['ticket_updated_at']);
if (empty($ticket_updated_at)) {
if ($ticket_status == "Closed") {
if ($ticket_status_name == "Closed") {
$ticket_updated_at_display = "<p>Never</p>";
} else {
$ticket_updated_at_display = "<p class='text-danger'>Never</p>";
@@ -1031,7 +1054,7 @@ if (isset($_GET['asset_id'])) {
}
$ticket_assigned_to = intval($row['ticket_assigned_to']);
if (empty($ticket_assigned_to)) {
if ($ticket_status == 5) {
if ($ticket_status_id == 5) {
$ticket_assigned_to_display = "<p>Not Assigned</p>";
} else {
$ticket_assigned_to_display = "<p class='text-danger'>Not Assigned</p>";
@@ -1167,7 +1190,7 @@ if (isset($_GET['asset_id'])) {
});
</script>
<!-- Include script to get TOTP code via the login ID -->
<!-- Include script to get TOTP code via the credential ID -->
<script src="js/credential_show_otp_via_id.js"></script>
<?php
@@ -1178,11 +1201,8 @@ require_once "modals/asset_interface_import_modal.php";
require_once "modals/asset_interface_export_modal.php";
require_once "modals/ticket_add_modal.php";
require_once "modals/recurring_ticket_add_modal.php";
require_once "modals/asset_link_software_modal.php";
require_once "modals/asset_link_credential_modal.php";
require_once "modals/asset_link_service_modal.php";
require_once "modals/asset_link_document_modal.php";
require_once "modals/asset_link_file_modal.php";
require_once "modals/credential_add_modal.php";
require_once "modals/client_document_add_modal.php";
require_once "modals/client_file_upload_modal.php";
require_once "includes/footer.php";

View File

@@ -9,10 +9,26 @@ if (isset($_GET['client_id'])) {
require_once "includes/inc_all_client.php";
$client_query = "AND asset_client_id = $client_id";
$client_url = "client_id=$client_id&";
// Overide Filter Header Archived
if (isset($_GET['archived']) && $_GET['archived'] == 1) {
$archived = 1;
$archive_query = "asset_archived_at IS NOT NULL";
} else {
$archived = 0;
$archive_query = "asset_archived_at IS NULL";
}
} else {
require_once "includes/inc_client_overview_all.php";
$client_query = '';
$client_url = '';
// Overide Filter Header Archived
if (isset($_GET['archived']) && $_GET['archived'] == 1) {
$archived = 1;
$archive_query = "(client_archived_at IS NOT NULL OR asset_archived_at IS NOT NULL)";
} else {
$archived = 0;
$archive_query = "(client_archived_at IS NULL AND asset_archived_at IS NULL)";
}
}
// Perms
@@ -53,7 +69,7 @@ if ($client_url && isset($_GET['location']) && !empty($_GET['location'])) {
} else {
// Default - any
$location_query = '';
$location_filter = '';
$location_filter = 0;
}
//Get Asset Counts
@@ -71,7 +87,7 @@ $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
WHERE asset_$archive_query
WHERE $archive_query
$access_permission_query
$client_query
) AS filtered_assets;
@@ -105,7 +121,7 @@ $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
WHERE asset_$archive_query
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 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%')
AND ($type_query)
$access_permission_query
@@ -205,12 +221,20 @@ if (mysqli_num_rows($os_sql) > 0) {
</div>
<?php if ($client_url) { ?>
<div class="col-md-2">
<div class="input-group">
<div class="input-group mb-3 mb-md-0">
<select class="form-control select2" name="location" onchange="this.form.submit()">
<option value="">- All Locations -</option>
<?php
$sql_locations_filter = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id = $client_id AND location_archived_at IS NULL ORDER BY location_name ASC");
$sql_locations_filter = mysqli_query($mysqli, "
SELECT DISTINCT location_id, location_name
FROM locations
LEFT JOIN assets ON asset_location_id = location_id
WHERE location_client_id = $client_id
AND location_archived_at IS NULL
AND (asset_location_id != 0 OR location_id = $location_filter)
ORDER BY location_name ASC
");
while ($row = mysqli_fetch_array($sql_locations_filter)) {
$location_id = intval($row['location_id']);
$location_name = nullable_htmlentities($row['location_name']);
@@ -225,12 +249,19 @@ if (mysqli_num_rows($os_sql) > 0) {
</div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<div class="input-group mb-3 mb-md-0">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_archived_at IS NULL $access_permission_query ORDER BY client_name ASC");
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN assets ON asset_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
@@ -298,6 +329,11 @@ if (mysqli_num_rows($os_sql) > 0) {
type="submit" form="bulkActions" name="bulk_unarchive_assets">
<i class="fas fa-fw fa-redo mr-2"></i>Unarchive
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_assets">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</button>
<?php } else { ?>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger confirm-link"
@@ -318,7 +354,7 @@ if (mysqli_num_rows($os_sql) > 0) {
<div class="table-responsive">
<table class="table border table-hover">
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?>">
<thead class="thead-light <?php if (!$num_rows[0]) { echo "d-none"; } ?> text-nowrap">
<tr>
<td class="bg-light pr-0">
<div class="form-check">
@@ -450,8 +486,8 @@ if (mysqli_num_rows($os_sql) > 0) {
$asset_ipv6 = nullable_htmlentities($row['interface_ipv6']);
$asset_nat_ip = nullable_htmlentities($row['interface_nat_ip']);
$asset_mac = nullable_htmlentities($row['interface_mac']);
$asset_uri = nullable_htmlentities($row['asset_uri']);
$asset_uri_2 = nullable_htmlentities($row['asset_uri_2']);
$asset_uri = sanitize_url($row['asset_uri']);
$asset_uri_2 = sanitize_url($row['asset_uri_2']);
$asset_status = nullable_htmlentities($row['asset_status']);
$asset_purchase_reference = nullable_htmlentities($row['asset_purchase_reference']);
$asset_purchase_date = nullable_htmlentities($row['asset_purchase_date']);
@@ -519,8 +555,8 @@ if (mysqli_num_rows($os_sql) > 0) {
$location_name_display = $location_name;
}
$sql_logins = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_asset_id = $asset_id");
$login_count = mysqli_num_rows($sql_logins);
$sql_credentials = mysqli_query($mysqli, "SELECT * FROM credentials WHERE credential_asset_id = $asset_id");
$credential_count = mysqli_num_rows($sql_credentials);
?>
<tr>
@@ -530,11 +566,7 @@ if (mysqli_num_rows($os_sql) > 0) {
</div>
</td>
<td>
<a class="text-dark" href="#"
data-toggle="ajax-modal"
data-modal-size="lg"
data-ajax-url="ajax/ajax_asset_details.php?<?php echo $client_url; ?>"
data-ajax-id="<?php echo $asset_id; ?>">
<a class="text-dark" href="asset_details.php?client_id=<?php echo $client_id; ?>&asset_id=<?php echo $asset_id; ?>">
<div class="media">
<i class="fa fa-fw fa-2x fa-<?php echo $device_icon; ?> mr-3 mt-1"></i>
<div class="media-body">
@@ -664,14 +696,6 @@ if (mysqli_num_rows($os_sql) > 0) {
<script src="js/bulk_actions.js"></script>
<?php
require_once "modals/asset_add_modal.php";
require_once "modals/asset_import_modal.php";
require_once "modals/asset_export_modal.php";
require_once "includes/footer.php";
?>
<!-- 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>
@@ -687,3 +711,9 @@ require_once "includes/footer.php";
});
});
</script>
<?php
require_once "modals/asset_add_modal.php";
require_once "modals/asset_import_modal.php";
require_once "modals/asset_export_modal.php";
require_once "includes/footer.php";

View File

@@ -12,6 +12,8 @@
<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
@@ -26,6 +28,8 @@ echo getUserAgent();
?>
<br>
<input type="tel" name="phone" id="phone">
<dl>
<dt>Requester</dt>
<dd>Sam Adams</dd>

View File

@@ -89,7 +89,7 @@ require_once "modals/calendar_add_modal.php";
//loop through IDs and create a modal for each
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['event_id']);
$event_title = nullable_htmlentities($row['event_title']);
@@ -170,7 +170,7 @@ while ($row = mysqli_fetch_array($sql)) {
},
events: [
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
$sql = mysqli_query($mysqli, "SELECT * FROM calendar_events LEFT JOIN calendars ON event_calendar_id = calendar_id $client_event_query");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['event_id']);
$event_title = json_encode($row['event_title']);
@@ -245,15 +245,15 @@ while ($row = mysqli_fetch_array($sql)) {
// Recurring Tickets
$sql = mysqli_query($mysqli, "SELECT * FROM clients
LEFT JOIN scheduled_tickets ON client_id = scheduled_ticket_client_id
LEFT JOIN users ON scheduled_ticket_assigned_to = user_id
LEFT JOIN recurring_tickets ON client_id = recurring_ticket_client_id
LEFT JOIN users ON recurring_ticket_assigned_to = user_id
$client_query"
);
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['scheduled_ticket_id']);
$event_id = intval($row['recurring_ticket_id']);
$client_id = intval($row['client_id']);
$username = $row['user_name'];
$frequency = $row['scheduled_ticket_frequency'];
$frequency = $row['recurring_ticket_frequency'];
if (empty($username)) {
$username = "";
} else {
@@ -261,8 +261,8 @@ while ($row = mysqli_fetch_array($sql)) {
$username = "[". substr($row['user_name'], 0, 9) . "...]";
}
$event_title = json_encode("R Ticket ($frequency) - " . $row['scheduled_ticket_subject'] . " " . $username);
$event_start = json_encode($row['scheduled_ticket_next_run']);
$event_title = json_encode("R Ticket ($frequency) - " . $row['recurring_ticket_subject'] . " " . $username);
$event_start = json_encode($row['recurring_ticket_next_run']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: '$event_color', url: 'recurring_tickets.php?client_id=$client_id$client_url' },";
}
@@ -303,7 +303,7 @@ while ($row = mysqli_fetch_array($sql)) {
}
//Vendors Added Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN vendors ON client_id = vendor_client_id $client_query AND vendor_template = 0 ");
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN vendors ON client_id = vendor_client_id $client_query");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['vendor_id']);
$client_id = intval($row['client_id']);

View File

@@ -9,21 +9,46 @@ if (isset($_GET['client_id'])) {
require_once "includes/inc_all_client.php";
$client_query = "AND certificate_client_id = $client_id";
$client_url = "client_id=$client_id&";
// Overide Filter Header Archived
if (isset($_GET['archived']) && $_GET['archived'] == 1) {
$archived = 1;
$archive_query = "certificate_archived_at IS NOT NULL";
} else {
$archived = 0;
$archive_query = "certificate_archived_at IS NULL";
}
} else {
require_once "includes/inc_client_overview_all.php";
$client_query = '';
$client_url = '';
// Overide Filter Header Archived
if (isset($_GET['archived']) && $_GET['archived'] == 1) {
$archived = 1;
$archive_query = "(client_archived_at IS NOT NULL OR certificate_archived_at IS NOT NULL)";
} else {
$archived = 0;
$archive_query = "(client_archived_at IS NULL AND certificate_archived_at IS NULL)";
}
}
// Perms
enforceUserPermission('module_support');
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
if (!$client_url) {
// Client Filter
if (isset($_GET['client']) & !empty($_GET['client'])) {
$client_query = 'AND (certificate_client_id = ' . intval($_GET['client']) . ')';
$client = intval($_GET['client']);
} else {
// Default - any
$client_query = '';
$client = '';
}
}
$sql = mysqli_query($mysqli, "SELECT SQL_CALC_FOUND_ROWS * FROM certificates
LEFT JOIN clients ON client_id = certificate_client_id
WHERE certificate_archived_at IS NULL
WHERE $archive_query
AND (certificate_name LIKE '%$q%' OR certificate_domain LIKE '%$q%' OR certificate_issued_by LIKE '%$q%' OR client_name LIKE '%$q%')
$access_permission_query
$client_query
@@ -56,6 +81,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php if ($client_url) { ?>
<input type="hidden" name="client_id" value="<?php echo $client_id; ?>">
<?php } ?>
<input type="hidden" name="archived" value="<?php echo $archived; ?>">
<div class="row">
<div class="col-md-4">
@@ -67,8 +93,43 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</div>
<div class="col-md-8">
<?php if ($client_url) { ?>
<div class="col-md-2"></div>
<?php } else { ?>
<div class="col-md-2">
<div class="input-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="" <?php if ($client == "") { echo "selected"; } ?>>- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "
SELECT DISTINCT client_id, client_name
FROM clients
JOIN certificates ON certificate_client_id = client_id
WHERE client_archived_at IS NULL
$access_permission_query
ORDER BY client_name ASC
");
while ($row = mysqli_fetch_array($sql_clients_filter)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<option <?php if ($client == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<?php } ?>
<div class="col-md-6">
<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"; } ?>">
<i class="fa fa-fw fa-archive mr-2"></i>Archived
</a>
<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>)
@@ -142,6 +203,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$certificate_issued_by = nullable_htmlentities($row['certificate_issued_by']);
$certificate_expire = nullable_htmlentities($row['certificate_expire']);
$certificate_created_at = nullable_htmlentities($row['certificate_created_at']);
$certificate_archived_at = nullable_htmlentities($row['certificate_archived_at']);
$certificate_expire_ago = timeAgo($certificate_expire);
// Convert the expiry date to a timestamp
@@ -154,9 +216,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
// Determine the class based on the number of days until expiry
if ($days_until_expiry <= 0) {
$tr_class = "table-secondary";
} elseif ($days_until_expiry <= 14) {
} elseif ($days_until_expiry <= 1) {
$tr_class = "table-danger";
} elseif ($days_until_expiry <= 90) {
} elseif ($days_until_expiry <= 7) {
$tr_class = "table-warning";
} else {
$tr_class = '';
@@ -210,14 +272,22 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<?php if ($session_user_role == 3) { ?>
<?php if ($certificate_archived_at) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_certificate=<?php echo $certificate_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
<a class="dropdown-item text-info confirm-link" href="post.php?unarchive_certificate=<?php echo $certificate_id; ?>">
<i class="fas fa-fw fa-redo mr-2"></i>Restore
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_certificate=<?php echo $certificate_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } else { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_certificate=<?php echo $certificate_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<?php } ?>
<?php } ?>
</div>
</div>

View File

@@ -27,7 +27,7 @@ if ($_SESSION['user_type'] !== 2) {
}
// Set Timezone
require_once "../inc_set_timezone.php";
require_once "../includes/inc_set_timezone.php";
// User IP & UA
$session_ip = sanitizeInput(getIP());

View File

@@ -56,6 +56,7 @@ header("X-Frame-Options: DENY"); // Legacy
</a>
<div class="dropdown-menu" aria-labelledby="navbarDropdown1">
<a class="dropdown-item" href="invoices.php">Invoices</a>
<a class="dropdown-item" href="recurring_invoices.php">Recurring Invoices</a>
<a class="dropdown-item" href="quotes.php">Quotes</a>
<a class="dropdown-item" href="autopay.php">Auto Payment</a>
</div>

View File

@@ -5,7 +5,7 @@
*/
require_once '../config.php';
require_once '../get_settings.php';
require_once '../includes/get_settings.php';
require_once '../functions.php';
require_once 'check_login.php';
require_once 'functions.php';

View File

@@ -8,7 +8,235 @@ header("Content-Security-Policy: default-src 'self'");
require_once "includes/inc_all.php";
// Billing Card Queries
//Add up all the payments for the invoice and get the total amount paid to the invoice
$sql_invoice_amounts = mysqli_query($mysqli, "SELECT SUM(invoice_amount) AS invoice_amounts FROM invoices WHERE invoice_client_id = $session_client_id AND invoice_status != 'Draft' AND invoice_status != 'Cancelled' AND invoice_status != 'Non-Billable'");
$row = mysqli_fetch_array($sql_invoice_amounts);
$invoice_amounts = floatval($row['invoice_amounts']);
$sql_amount_paid = mysqli_query($mysqli, "SELECT SUM(payment_amount) AS amount_paid FROM payments, invoices WHERE payment_invoice_id = invoice_id AND invoice_client_id = $session_client_id");
$row = mysqli_fetch_array($sql_amount_paid);
$amount_paid = floatval($row['amount_paid']);
$balance = $invoice_amounts - $amount_paid;
//Get Monthly Recurring Total
$sql_recurring_monthly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_monthly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'month' AND recurring_invoice_client_id = $session_client_id");
$row = mysqli_fetch_array($sql_recurring_monthly_total);
$recurring_monthly_total = floatval($row['recurring_monthly_total']);
//Get Yearly Recurring Total
$sql_recurring_yearly_total = mysqli_query($mysqli, "SELECT SUM(recurring_invoice_amount) AS recurring_yearly_total FROM recurring_invoices WHERE recurring_invoice_status = 1 AND recurring_invoice_frequency = 'year' AND recurring_invoice_client_id = $session_client_id");
$row = mysqli_fetch_array($sql_recurring_yearly_total);
$recurring_yearly_total = floatval($row['recurring_yearly_total']) / 12;
$recurring_monthly = $recurring_monthly_total + $recurring_yearly_total;
// Technical Card Queries
// 8 - 45 Day Warning
// Get Domains Expiring
$sql_domains_expiring = mysqli_query(
$mysqli,
"SELECT * FROM domains
WHERE domain_client_id = $session_client_id
AND domain_expire IS NOT NULL
AND domain_archived_at IS NULL
AND domain_expire > CURRENT_DATE
AND domain_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY domain_expire ASC"
);
// Get Certificates Expiring
$sql_certificates_expiring = mysqli_query(
$mysqli,
"SELECT * FROM certificates
WHERE certificate_client_id = $session_client_id
AND certificate_expire IS NOT NULL
AND certificate_archived_at IS NULL
AND certificate_expire > CURRENT_DATE
AND certificate_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY certificate_expire ASC"
);
// Get Licenses Expiring
$sql_licenses_expiring = mysqli_query(
$mysqli,
"SELECT * FROM software
WHERE software_client_id = $session_client_id
AND software_expire IS NOT NULL
AND software_archived_at IS NULL
AND software_expire > CURRENT_DATE
AND software_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY software_expire ASC"
);
// Get Asset Warranties Expiring
$sql_asset_warranties_expiring = mysqli_query(
$mysqli,
"SELECT * FROM assets
WHERE asset_client_id = $session_client_id
AND asset_warranty_expire IS NOT NULL
AND asset_archived_at IS NULL
AND asset_warranty_expire > CURRENT_DATE
AND asset_warranty_expire < CURRENT_DATE + INTERVAL 45 DAY
ORDER BY asset_warranty_expire ASC"
);
// Get Assets Retiring 7 Year
$sql_asset_retire = mysqli_query(
$mysqli,
"SELECT * FROM assets
WHERE asset_client_id = $session_client_id
AND asset_install_date IS NOT NULL
AND asset_archived_at IS NULL
AND asset_install_date + INTERVAL 7 YEAR > CURRENT_DATE
AND asset_install_date + INTERVAL 7 YEAR <= CURRENT_DATE + INTERVAL 45 DAY
ORDER BY asset_install_date ASC"
);
/*
* EXPIRED ITEMS
*/
// Get Domains Expired
$sql_domains_expired = mysqli_query(
$mysqli,
"SELECT * FROM domains
WHERE domain_client_id = $session_client_id
AND domain_expire IS NOT NULL
AND domain_archived_at IS NULL
AND domain_expire < CURRENT_DATE
ORDER BY domain_expire ASC"
);
// Get Certificates Expired
$sql_certificates_expired = mysqli_query(
$mysqli,
"SELECT * FROM certificates
WHERE certificate_client_id = $session_client_id
AND certificate_expire IS NOT NULL
AND certificate_archived_at IS NULL
AND certificate_expire < CURRENT_DATE
ORDER BY certificate_expire ASC"
);
// Get Licenses Expired
$sql_licenses_expired = mysqli_query(
$mysqli,
"SELECT * FROM software
WHERE software_client_id = $session_client_id
AND software_expire IS NOT NULL
AND software_archived_at IS NULL
AND software_expire < CURRENT_DATE
ORDER BY software_expire ASC"
);
// Get Asset Warranties Expired
$sql_asset_warranties_expired = mysqli_query(
$mysqli,
"SELECT * FROM assets
WHERE asset_client_id = $session_client_id
AND asset_warranty_expire IS NOT NULL
AND asset_archived_at IS NULL
AND asset_warranty_expire < CURRENT_DATE
ORDER BY asset_warranty_expire ASC"
);
// Get Retired Assets
$sql_asset_retired = mysqli_query(
$mysqli,
"SELECT * FROM assets
WHERE asset_client_id = $session_client_id
AND asset_install_date IS NOT NULL
AND asset_archived_at IS NULL
AND asset_install_date + INTERVAL 7 YEAR < CURRENT_DATE -- Assets retired (installed more than 7 years ago)
ORDER BY asset_install_date ASC"
);
?>
<?php
// Billing Cards
if ($session_contact_primary == 1 || $session_contact_is_billing_contact) { ?>
<div class="row">
<?php if ($balance > 0) { ?>
<div class="col-sm-3 offset-1">
<div class="card">
<div class="card-header">
<h3 class="card-title text-bold">Account Balance</h3>
</div>
<div class="card-body">
<div class="h4 text-danger"><b><?php echo numfmt_format_currency($currency_format, $balance, $session_company_currency); ?></b></div>
</div>
</div>
</div>
<?php } ?>
<?php if ($recurring_monthly_total > 0) { ?>
<div class="col-sm-3">
<div class="card">
<div class="card-header">
<h3 class="card-title">Recurring Monthly</h3>
</div>
<div class="card-body">
<div class="h4"><b><?php echo numfmt_format_currency($currency_format, $recurring_monthly_total, $session_company_currency); ?></b></div>
</div>
</div>
</div>
<?php } ?>
</div>
<?php } //End Billing Cards ?>
<?php
// Technical Cards
if ($session_contact_primary == 1 || $session_contact_is_technical_contact) {
?>
<div class="row">
<?php if (mysqli_num_rows($sql_domains_expiring) > 0) { ?>
<div class="col-sm-3 offset-1">
<div class="card">
<div class="card-header">
<h3 class="card-title text-bold">Domains Expiring</h3>
</div>
<div class="card-body">
<?php
while ($row = mysqli_fetch_array($sql_domains_expiring)) {
$domain_id = intval($row['domain_id']);
$domain_name = nullable_htmlentities($row['domain_name']);
$domain_expire = nullable_htmlentities($row['domain_expire']);
$domain_expire_human = timeAgo($row['domain_expire']);
?>
<p class="mb-1">
<i class="fa fa-fw fa-globe text-secondary mr-1"></i>
Domain: <?php echo $domain_name; ?>
<span>-- <?php echo $domain_expire; ?> (<?php echo $domain_expire_human; ?>)</span>
</p>
<?php
}
?>
</div>
</div>
</div>
<?php } ?>
</div>
<?php } ?>
<div class="col-md-2 offset-1">
<a href="ticket_add.php" class="btn btn-primary btn-block">New ticket</a>
</div>

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