2974 Commits

Author SHA1 Message Date
Johnny
0dca0ce4bf Merge pull request #1161 from itflow-org/develop
Release 25.01.2
2025-01-30 15:01:20 -05:00
johnnyq
b5be8605d6 Final Version Fix in Changelog 2025-01-30 14:58:18 -05:00
johnnyq
2268a41b00 Update App version to 25.01.2 2025-01-30 14:55:06 -05:00
johnnyq
8efd22f47b Fix App Versioning 2025-01-30 14:54:09 -05:00
Johnny
e3aafcbc68 Merge pull request #1160 from itflow-org/develop
Release 25.01.01
2025-01-30 14:45:57 -05:00
johnnyq
2e5b0d1429 Increased version to 25.01.1 for a hotfix release 2025-01-30 14:17:08 -05:00
johnnyq
dd94e594a1 Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-01-30 11:38:51 -05:00
johnnyq
b3c7b00e61 Fix broken image link in user pref and company details ig not avatar or company logo is present update nav user icon 2025-01-30 11:38:34 -05:00
wrongecho
badda09245 Prevent users disabling MFA when it is enforced 2025-01-29 21:29:04 +00:00
wrongecho
bf019f374a Minor changelog wording tweaks 2025-01-29 21:19:26 +00:00
johnnyq
aa87a11f12 Removed setup from the cron script wording 2025-01-29 15:59:21 -05:00
johnnyq
6df465a4d1 Update Changelog 2025-01-29 15:25:25 -05:00
johnnyq
c4980a1241 Update Changelog 2025-01-29 15:22:52 -05:00
johnnyq
ffca7ff445 Added back warning about the old script path 2025-01-29 12:43:29 -05:00
johnnyq
34b94af965 Copied the cron scripts from /script dir back to / and updated all require pathes 2025-01-29 12:32:45 -05:00
johnnyq
5b32127de2 Add Tooltips on hover to better explain what to do with the MFA enformcement info 2025-01-29 11:41:37 -05:00
johnnyq
22a5c90d21 Reworked MFA Enforcement page to use login page style for smoother transition 2025-01-29 11:35:14 -05:00
johnnyq
6cbd4ffebe Add members column in roles and other UI tidying 2025-01-28 20:03:23 -05:00
johnnyq
033a5d1f4f Remove comment 2025-01-28 19:25:29 -05:00
johnnyq
02fdc66af9 Updated UI / UX MFA enforcement 2025-01-28 19:23:25 -05:00
johnnyq
52ad2ba322 Reworked the MFA Enforcement 2025-01-28 18:57:04 -05:00
johnnyq
677bb6b400 Updated Changelog removed crons and cron key 2025-01-28 17:32:27 -05:00
johnnyq
c282e22228 Updated Changelog 2025-01-28 17:29:15 -05:00
Johnny
5b5e01df4b Merge pull request #1157 from itflow-org/bulk-mail
Bulk mail - only show active clients
2025-01-28 17:20:00 -05:00
Johnny
f4173354bb Merge pull request #1156 from itflow-org/tck-assign
Fix ticket assign modal/filter
2025-01-28 17:19:29 -05:00
Johnny
47eddfdf9c Merge pull request #1155 from itflow-org/rec-payment-stripe
Autopay
2025-01-28 17:18:23 -05:00
johnnyq
706a77c5d3 Added btn-responsive style class to define buttons to go full block level while in mobile and to stay defined size in non mobile response 2025-01-28 17:14:47 -05:00
johnnyq
a4c9b4efa4 fix right margin on forms in user details when in mobile response 2025-01-28 16:55:47 -05:00
johnnyq
9ea5fdf425 Further improve the MFA process, now when verification fails the modal will stay open and the secret remain the same 2025-01-28 16:34:07 -05:00
johnnyq
ec9572c2ec Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-01-28 15:08:41 -05:00
johnnyq
c150fb02bb Fix Profit and Loss Report getting the wrong total expense amount for Quarter 2 April - June due to wrong var being used this does not affect actual expense data and will show correctly after update and also does not affect total expense for all 4 quarters 2025-01-28 15:06:43 -05:00
wrongecho
92ef31d861 Bulk mail - only show active clients
Bulk mail shouldn't show archived clients
2025-01-28 12:31:09 +00:00
wrongecho
5fa8363ad7 Fix ticket assign modal/filter 2025-01-28 11:50:38 +00:00
wrongecho
20a862f020 Fix redirect to /client if no login key is set 2025-01-28 11:24:08 +00:00
wrongecho
071352e32f Autopay
- Stripe wasn't showing as an option in the modal
- Show the current payment method at the top of the recurring invoice
2025-01-28 11:19:56 +00:00
johnnyq
39adab734b Enhanced the MFA Setup Flow 2025-01-27 23:26:10 -05:00
johnnyq
8221ef2927 Global Ticket View make contact secondary text in table header and remove tasks from the table header 2025-01-27 11:20:24 -05:00
johnnyq
ab7273bf39 Reduce Global Ticket view padding by not displaying contact's email 2025-01-27 11:15:43 -05:00
johnnyq
96809c7f85 Update db.sql 2025-01-25 21:47:24 -05:00
johnnyq
d5a03d3afc remove cron key from the code and remove old cron script and setup and update cli scripts as they now reside in scripts directory 2025-01-25 21:44:46 -05:00
johnnyq
052d5a6dbe Remove cron key from setup 2025-01-25 21:30:23 -05:00
johnnyq
227b87b1cb Fix Show OTP on hover in asset and contact details logins section 2025-01-25 19:53:00 -05:00
Johnny
e8c3cabde7 Merge pull request #1154 from itflow-org/develop
Release 25.01
2025-01-25 12:48:43 -05:00
johnnyq
33f80cb6b5 Adjust Version to use double digit for month 2025-01-25 12:42:11 -05:00
johnnyq
bf382f3aeb Bump ITFlow Version from 24.12 to 25.01 2025-01-25 12:35:19 -05:00
johnnyq
f4c4fe655b Update Changelog 2025-01-25 12:06:45 -05:00
johnnyq
6473a84fb2 Bump plugin stripe-php from 10.5.0 to 16.4.0 and update links 2025-01-25 11:47:58 -05:00
johnnyq
17f7b8be1c Minor UI update on Client Saved Payment Methods 2025-01-25 00:51:21 -05:00
johnnyq
cd40a97ae8 Use company currency code when autopay creates an expense, sort Invoices DESC 2025-01-25 00:30:48 -05:00
johnnyq
ce7406b632 Fix stripe library link in invoice 2025-01-24 23:55:30 -05:00
johnnyq
eef67194c4 Bump plugin Inputmask from 5.0.8 to 5.0.9 2025-01-24 22:30:52 -05:00
johnnyq
79d1914fe8 Bump Plugin DataTables from 2.1.8 to 2.2.1 2025-01-24 22:23:20 -05:00
johnnyq
b47c79d90a Bump plugin pdfmake from 0.2.8 to 0.2.18 2025-01-24 22:18:13 -05:00
johnnyq
fb17dbb1fb Bump php-mime-mail-parser library to 9.0.1 2025-01-24 22:07:49 -05:00
johnnyq
927725de7d Initialize TinyMCE using gpl license 2025-01-24 21:58:12 -05:00
johnnyq
156fcb7379 Bump TinyMCE from 7.5.1 to 7.6.1 2025-01-24 21:52:52 -05:00
johnnyq
6a2489865d Garbage Collect .git 2025-01-24 21:47:03 -05:00
johnnyq
5cecbe6ed1 Revert app version link 2025-01-24 21:30:03 -05:00
johnnyq
7863935a20 Fix app_version.php link in inc_all_admin.php 2025-01-24 21:28:23 -05:00
johnnyq
87e1371318 Move app_version.php and database_version.php to includes folder update all assocoiated links, remove 2 legacy php files maintence and legacy_debug 2025-01-24 21:25:04 -05:00
johnnyq
f29d122376 Move totp.php out of functions folder into plugins then removed functions folder 2025-01-24 21:07:01 -05:00
johnnyq
772b47f2c0 Remove unused css files in css folder along with the css folder 2025-01-24 20:58:28 -05:00
Johnny
38fced55a5 Merge pull request #1153 from itflow-org/hide-files
Hide the .git and .github folders as well as config.php
2025-01-24 20:51:58 -05:00
johnnyq
e9b011ea90 Update remainder strip lib links 2025-01-24 20:48:27 -05:00
johnnyq
6733d3cd24 Removed unused libs in the vendor folder and moved stripe to the plugins folder then elininated the vendor folder all together, updated all the stripe links 2025-01-24 20:44:36 -05:00
johnnyq
bf0d3de393 totp.php link fix 2025-01-24 20:32:00 -05:00
johnnyq
8e04e10753 Combine base32static.php and rfc6238.php into 1 file called totp.php and place it into the functions folder 2025-01-24 20:26:46 -05:00
johnnyq
d80d4803db Moved TOTP dependent files rfc6238.php and base32static.php to /includes folder and updated links in pages 2025-01-24 19:20:49 -05:00
wrongecho
2b3ff954c3 Hide the .git and .github folders as well as config.php 2025-01-24 19:30:22 +00:00
johnnyq
b1f0cfa29a Add back bootstrap5 css for select2 2025-01-24 13:19:18 -05:00
johnnyq
4965bcadc5 Update some wording on select boxes and and UI tiday on Send Mass Email in contacts 2025-01-24 13:16:49 -05:00
wrongecho
fcbb083cfb Mention SSO breaking 2025-01-24 15:25:18 +00:00
wrongecho
cce2e937da Hide settings for disabled modules in the admin sidebar 2025-01-24 15:18:49 +00:00
wrongecho
a3e94d1171 - Finish updating URLs from /portal to /client
- Add a basic Stripe management page to admin settings to remove cards/reset Stripe customer IDs
2025-01-24 15:08:09 +00:00
wrongecho
57deea2785 Hyperlink primary contact name on overview 2025-01-24 09:42:59 +00:00
wrongecho
6d94c32818 Hyperlink primary contact name on overview 2025-01-24 09:41:36 +00:00
wrongecho
6f2ae10e39 Fix portal password reset link (portal -> client) 2025-01-24 09:01:49 +00:00
johnnyq
0558358627 Added breaking changes to the Changelog specifically /guest/ and /client/ 2025-01-23 17:29:13 -05:00
johnnyq
2b8778b205 Fix some lingering dead links 2025-01-23 17:21:49 -05:00
johnnyq
5f76a7989b Move portal to client and rename and reorganize some client portal files 2025-01-23 17:12:11 -05:00
johnnyq
70dd3ab5c8 Remove Cron Key Requirement from cron scripts in /scripts folder and set to only run on the cli 2025-01-23 14:01:15 -05:00
johnnyq
c8e3e37d87 Update top right corner logo on setup, add more default common income, expense, referral, payment method categories 2025-01-23 12:53:26 -05:00
johnnyq
49682e4362 Fix Adminlte Paths in setup 2025-01-23 11:47:21 -05:00
johnnyq
faa1f789b8 Update Function in bulk mail 2025-01-22 21:07:11 -05:00
johnnyq
2c51289d75 Remove mysqli connection vars when passing mail data to addToMailQueue Function 2025-01-22 20:56:24 -05:00
johnnyq
c5c809791a Fix Default order by 2025-01-22 19:32:47 -05:00
johnnyq
606f3061d0 Simplify / rework some of the filter header logic and update filter vars in the rest of the code 2025-01-22 18:55:05 -05:00
johnnyq
4fc39a7203 Update Filter Vars in expenses 2025-01-22 17:31:04 -05:00
johnnyq
e403526321 Better var naming for filter vars for clients and contacts 2025-01-22 16:36:55 -05:00
johnnyq
5765144770 Disable HTML Purifier Caching in Guest and Portal Areas ass well 2025-01-22 14:42:45 -05:00
johnnyq
bff04e947b Disable HTML Purifier Caching 2025-01-22 14:39:39 -05:00
johnnyq
502ebf5080 Update Changelog 2025-01-22 11:25:02 -05:00
johnnyq
823c9eb030 Reduce the Max amount of Records per page to 100 instead of 500 to prevent performance issues 2025-01-22 11:22:09 -05:00
johnnyq
679291217d Fix Regression with TinyMCE not loading when editing or adding a ticket template 2025-01-22 11:17:47 -05:00
johnnyq
2abc6cd8ef Fix Editing Recurring Expenses, update Changelog 2025-01-20 23:28:46 -05:00
johnnyq
9d2f509694 Add tooltips to the client badge count on the side nav menu to explain what it counts 2025-01-19 20:53:02 -05:00
johnnyq
22e9699b20 Fix Archive Taxes 2025-01-18 16:48:39 -05:00
johnnyq
5382676fc1 Reduce padding in Rack units, use thumnail class for rack image 2025-01-18 14:54:33 -05:00
johnnyq
a90e08cb2d UI Update to rack devices, added a table header to Device Units removed border between action and device 2025-01-18 14:48:59 -05:00
johnnyq
37e792402f Update Change log 2025-01-18 14:26:32 -05:00
johnnyq
034dc4a745 Row span and center each Rack Devices instead of repeating same device for each unit the device utilizes 2025-01-18 14:09:06 -05:00
johnnyq
5fb4d2a197 Tidy some code in client contacts 2025-01-18 13:38:55 -05:00
johnnyq
657d766fbd Update Table UI for domain history 2025-01-18 13:20:39 -05:00
johnnyq
eee5a9cd8d Updated CHANGELOG 2025-01-18 13:09:37 -05:00
johnnyq
360974d9f4 Refactor interface linking system:
- Remove 'interface_connected_asset_interface' column usage
- Introduce 'asset_interface_links' table for one-to-one connections
- Update add/edit/delete queries and modals to handle new schema
- Exclude already-connected interfaces in dropdowns
- Improve data integrity and simplify linking logic
2025-01-18 13:04:56 -05:00
wrongecho
d2b3970a7b Update SECURITY.md 2025-01-18 12:19:00 +00:00
wrongecho
317d45c60b Update README.md 2025-01-18 12:06:45 +00:00
wrongecho
85cee68d15 Update README.md 2025-01-18 11:20:23 +00:00
wrongecho
c425c37fbf Update CHANGELOG.md 2025-01-18 11:00:08 +00:00
johnnyq
d1ebdcf92c Add Force Recur ticket to client Recurring, client details and asset details 2025-01-17 17:34:37 -05:00
johnnyq
57cbcf4e1d Update some UI elements in User Preferences 2025-01-17 17:05:41 -05:00
Johnny
bddc406c1d Merge pull request #1151 from itflow-org/domain-history
Add domain history
2025-01-17 16:47:05 -05:00
johnnyq
43337ff138 Update User Details Page to mimic company Details layout 2025-01-17 16:44:00 -05:00
wrongecho
ecd83b6b11 Add domain history to domain refresher 2025-01-17 21:39:11 +00:00
johnnyq
e68c8b7922 Reduce Card Header Padding in Company Details 2025-01-17 16:25:54 -05:00
johnnyq
269bddee9d Feature: Ability to remove Company Logo, also small UI touch up in company details 2025-01-17 16:23:29 -05:00
johnnyq
505ad52950 Update Changelog 2025-01-17 15:58:14 -05:00
wrongecho
e0c8155943 Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-01-17 20:55:18 +00:00
wrongecho
d22c2b5265 Refactor changelog 2025-01-17 20:55:10 +00:00
johnnyq
5baecf6982 Add Payment Deletion Capabilities from payments and client payments page 2025-01-17 15:54:26 -05:00
wrongecho
fd59709af5 Fix stripe auto-pay not fetching publishable key 2025-01-17 20:28:09 +00:00
wrongecho
9dcd9abdc6 Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-01-17 20:27:35 +00:00
wrongecho
55b324621e Fix stripe auto-pay not fetching publishable key 2025-01-17 20:27:22 +00:00
johnnyq
e3623dce5e Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-01-17 15:27:18 -05:00
johnnyq
cb7965a84f Stripe Var Passthru attempt 2025-01-17 15:26:40 -05:00
Johnny
2ce32731aa Merge pull request #1150 from itflow-org/services-db-charset
Services table has a weird character set - removed
2025-01-15 20:22:54 -05:00
wrongecho
99c4f9b92d Add domain history 2025-01-15 18:04:56 +00:00
wrongecho
c5058b26de Services table has a weird character set - removed
https://tasks.dev.itflow.org/task_details.php?task_id=41
2025-01-15 12:05:03 +00:00
johnnyq
e4a4687e8c Added Connected Asset Interface ID to asset interface table to eventual link to anothr assets interface/port 2025-01-14 23:50:08 -05:00
johnnyq
1c971ca88c Reduce Padding for Network Interfaces table 2025-01-14 22:40:32 -05:00
johnnyq
a5d3c73249 Sort Interface Ports ASC instead of DESC in asset details 2025-01-14 22:33:31 -05:00
johnnyq
5d3b4c8ff7 Update JS for stripe autopay to fetch value of Publishable Key from hidden form element instead of using hard coded key 2025-01-14 16:39:34 -05:00
Johnny
47657e462a Merge pull request #1149 from itflow-org/modal-maxlength
Modal maxlength
2025-01-14 12:55:26 -05:00
Johnny
5567dfe968 Merge pull request #1148 from itflow-org/stripe-autopay
Initial add Stripe Auto-payment with saved card
2025-01-14 12:54:36 -05:00
wrongecho
f774218b6d Cron - log retention should include the new app and audit logs tables too 2025-01-14 17:48:42 +00:00
wrongecho
34daca31b8 Include rather than require for the admin/xcustom includes to avoid breaking notifications/logout on pages that don't have a post handler (e.g. app logs) 2025-01-14 17:47:56 +00:00
wrongecho
6d9de98a71 Add maxlength attribute to modals 2025-01-14 17:24:43 +00:00
wrongecho
6c234968cb Fix top_nav_tickets_modal path 2025-01-14 15:39:33 +00:00
wrongecho
54dde984ac nullable_htmlentities - prevent Passing null to parameter error 2025-01-14 15:37:24 +00:00
wrongecho
9a36ad2cea Initial add Stripe Auto-payment with saved card 2025-01-14 00:28:49 +00:00
wrongecho
88c1b8cb8b Initial add Stripe Auto-payment with saved card 2025-01-13 22:58:23 +00:00
johnnyq
701df8db38 Update Changelog 2025-01-13 16:15:51 -05:00
johnnyq
97723da633 Windows/Tab Titles now reflect the current page your on along with the company name or selected client. Pages contact details, asset details, tickets, projects, documents, invoices, quotes, recurring invoices overide to include more detail in tab title 2025-01-13 14:40:05 -05:00
wrongecho
2693bbf81a Initial add Stripe Auto-payment with saved card 2025-01-13 00:11:04 +00:00
wrongecho
b72c3f23af Initial add Stripe Auto-payment with saved card 2025-01-12 23:59:39 +00:00
wrongecho
f153ae8ff3 Initial add Stripe Auto-payment with saved card 2025-01-12 22:02:49 +00:00
wrongecho
cd374b7b21 Initial add Stripe Auto-payment with saved card 2025-01-12 21:42:02 +00:00
wrongecho
a15081ac67 Initial add Stripe Auto-payment with saved card 2025-01-12 20:56:38 +00:00
johnnyq
0cb3cdc26d Moved all modals into /modals and updated all require links 2025-01-12 13:55:31 -05:00
wrongecho
e7f19dc69d Fix portal invoices 2025-01-12 09:25:13 +00:00
wrongecho
2c6b1a83d6 Fix portal confirm modal include 2025-01-12 09:22:21 +00:00
johnnyq
d57caed793 tidy 2025-01-11 17:41:50 -05:00
johnnyq
5b2b3d2821 Add index.php in /guest to redirect to the portal 2025-01-11 17:28:49 -05:00
wrongecho
731927d49c Allow archiving roles 2025-01-11 22:08:28 +00:00
wrongecho
2b07b03560 Update URLs for guest being in subdir 2025-01-11 21:46:34 +00:00
johnnyq
ae7b7d1157 Update AdminLTE CSS/JS links in client Portal's login, login_reset and header and footer 2025-01-11 16:20:40 -05:00
johnnyq
cc0b456312 Update all email content links to use the /guest directory now for ticket viewing, invoice, quote and item 2025-01-11 16:07:48 -05:00
johnnyq
d29aa55411 Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-01-11 15:48:31 -05:00
johnnyq
7a23cf245d Fix index.php, Move Guest files to /Guest directory, fix adminlte path 2025-01-11 15:48:10 -05:00
wrongecho
677823d19d Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-01-11 19:51:41 +00:00
wrongecho
25e7ed6a6e Guest ticket feedback now shows friendly ticket prefix & number 2025-01-11 19:51:32 +00:00
johnnyq
08b91ead25 Merge branch 'develop' of github.com:itflow-org/itflow into develop 2025-01-11 14:49:14 -05:00
johnnyq
98f9083bcb Structure rework: Moved most php files that are included to /includes renamed pagination.php to filter_footer.php, updated all file to reference new filter_footer and includes 2025-01-11 14:47:32 -05:00
wrongecho
2ca92744f3 mv 2025-01-11 19:40:36 +00:00
wrongecho
5baae71dc7 Auto-acknowledgement email for email parsed tickets now contains guest link 2025-01-11 19:33:48 +00:00
johnnyq
a9179462c4 Moved client location modals inside /modals and updated the require links in location listing 2025-01-11 13:05:26 -05:00
johnnyq
69fb9f682b Created modals and includes folder moved client contact modals to /modals and updsated contact details and contact listing code 2025-01-11 12:55:23 -05:00
wrongecho
7bd47b1cca All cron scripts should set the running directory for consistency 2025-01-09 19:01:31 +00:00
wrongecho
12d8894c8f Mail queue - duh, it actually sees to be a fix.. 2025-01-09 18:59:24 +00:00
wrongecho
73c711095a Mail queue - undo file inclusion, not a fix 2025-01-09 18:53:11 +00:00
wrongecho
8914f4afe7 Mail parser - fix billable 2025-01-09 17:02:03 +00:00
wrongecho
50e252efb7 Mail queue - fix file inclusion following move to subdir 2025-01-09 16:58:09 +00:00
wrongecho
22d1a1809c Tickets created via portal/email not being marked as billable 2025-01-09 16:29:07 +00:00
wrongecho
64fd761934 Don't require a contact for recurring tickets 2025-01-09 16:23:35 +00:00
wrongecho
90e53981f6 Credential add modal - URI placeholder text was off 2025-01-09 16:11:52 +00:00
wrongecho
a67de7a8f1 Prevent post pages being accessed directly 2025-01-09 16:09:39 +00:00
wrongecho
ec54b28b02 Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-01-09 15:32:22 +00:00
wrongecho
d3d3d37595 Show git branch on debug page 2025-01-09 15:32:11 +00:00
wrongecho
cf511b2c4b Update CHANGELOG.md 2025-01-09 15:21:20 +00:00
wrongecho
0871833f48 Merge branch 'develop' of https://github.com/itflow-org/itflow into develop 2025-01-09 15:14:57 +00:00
wrongecho
e8c7b3616b Tweak docs link 2025-01-09 15:14:46 +00:00
wrongecho
9845991413 Merge pull request #1147 from itflow-org/new-admin-check
Implement new admin check
2025-01-09 15:13:04 +00:00
wrongecho
fe94036b3a Implement new admin check
Uses the new $session_is_admin rather than the old validateAdminRole.
Reverts #1065
2025-01-09 15:11:07 +00:00
wrongecho
77b3eca687 Merge pull request #1146 from itflow-org/stripe-account-ui
Stripe payments - Account selection
2025-01-09 15:01:46 +00:00
wrongecho
1e777afa50 Stripe payments - Account selection
https://tasks.dev.itflow.org/task_details.php?task_id=22
2025-01-09 15:01:04 +00:00
wrongecho
2f57bdb677 Merge pull request #1145 from itflow-org/stripe-account-ui
Stripe payments - Account selection
2025-01-09 14:58:42 +00:00
wrongecho
d32e3a698f Stripe payments - Account selection
https://tasks.dev.itflow.org/task_details.php?task_id=22
2025-01-09 14:56:36 +00:00
wrongecho
3c697617f9 Update README.md
Remove issues shield, as we'll be using our own system for roadmapping
2025-01-08 13:42:37 +00:00
johnnyq
bc417b7cf3 Fix creating a recurring expense due to bad var name 2025-01-02 21:46:40 -05:00
johnnyq
3e52155d1c Fix editing recurring expense due to bad var name 2025-01-02 21:26:29 -05:00
wrongecho
5d734e58af Merge pull request #1144 from itflow-org/bug-asset-network
Bugfix: Asset interface DHCP vanishing
2025-01-02 22:58:58 +00:00
wrongecho
b0d398618d Bugfix: Asset interface DHCP vanishing
Fixes a bug that removes the DHCP setting on asset interfaces when changing their network interface from the asset details page
2025-01-02 22:57:13 +00:00
wrongecho
87f0cb295f Merge pull request #1143 from itflow-org/bug-tickets-projects
Bugfix - tickets <=> projects
2025-01-02 22:24:46 +00:00
wrongecho
65873eb46f Bugfix: Ticket edit modal not showing multi-client/no-client projects 2025-01-02 22:22:37 +00:00
wrongecho
cb2f620343 Bugfix: Ticket edit modal not showing multi-client/no-client projects 2025-01-02 22:21:02 +00:00
wrongecho
2dad616f42 Merge pull request #1142 from itflow-org/cron-scripts-move
Domain Refresh - Tidy old debug message
2025-01-02 22:02:03 +00:00
wrongecho
afc03634d6 Tidy old debug message 2025-01-02 22:01:01 +00:00
wrongecho
e677d5f7ca Merge pull request #1141 from itflow-org/cron-scripts-move
config.php has to be written to parent dir
2025-01-02 21:57:23 +00:00
wrongecho
43ccf8a026 config.php has to be written to parent dir 2025-01-02 21:55:25 +00:00
wrongecho
4167381fb1 Merge pull request #1140 from itflow-org/cron-scripts-move
uploads have to be written to parent dir
2025-01-02 21:48:54 +00:00
wrongecho
ff4f8a9a18 uploads have to be written to parent dir 2025-01-02 21:48:02 +00:00
wrongecho
c2f82bbe0e Merge pull request #1139 from itflow-org/cron-scripts-move
config.php has to be written to parent dir
2025-01-02 21:45:36 +00:00
wrongecho
b0a960547c config.php has to be written to parent dir 2025-01-02 21:43:23 +00:00
wrongecho
04def2e434 Merge pull request #1138 from itflow-org/cron-scripts-move
db.sql also needs to be called from the parent directory
2025-01-02 21:38:41 +00:00
wrongecho
a529eca414 db.sql also needs to be called from the parent directory 2025-01-02 21:37:10 +00:00
wrongecho
942004a6a7 Merge pull request #1137 from itflow-org/cron-scripts-move
Adjust cron/cli scripts in subdir to load required scripts from parent
2025-01-02 21:31:28 +00:00
wrongecho
7ebac0a674 Sonar recommendations 2025-01-02 21:30:18 +00:00
wrongecho
50371558c6 Adjust cron/cli scripts in subdir to load required scripts from parent 2025-01-02 21:27:14 +00:00
wrongecho
ee49c2c5c6 Update CHANGELOG.md
wip
2025-01-02 21:14:15 +00:00
wrongecho
740f477d4c Merge pull request #1136 from itflow-org/cron-scripts-move
Move cli/cron scripts
2025-01-02 21:11:11 +00:00
wrongecho
2d403415d4 Tidying per sonar recommendations 2025-01-02 21:09:27 +00:00
wrongecho
f39b0eb367 Tidying per sonar recommendations 2025-01-02 21:05:03 +00:00
wrongecho
db6d2fb534 Move cron scripts
Move cron scripts to their own subfolder.
2025-01-02 20:59:05 +00:00
wrongecho
3b0d24f5a5 Delete test.md 2024-12-31 16:26:42 +00:00
wrongecho
c7b0f1222f Update test.md 2024-12-31 16:10:29 +00:00
wrongecho
bf53d5b0fe Also move setup and update cli to scripts folder for better organisation 2024-12-31 11:49:48 +00:00
wrongecho
fd2339e17c Merge pull request #1135 from itflow-org/add-changelog
Add changelog
2024-12-30 17:47:22 +00:00
wrongecho
df19709c2f Move cron scripts
Move cron scripts to their own subfolder.
2024-12-30 17:31:34 +00:00
wrongecho
5bf009f052 Add changelog 2024-12-30 16:54:16 +00:00
wrongecho
0bde1ccee4 Merge pull request #1133 from itflow-org/develop
Release system - 24.12
2024-12-30 14:26:38 +00:00
wrongecho
955f7c3f3b Merge pull request #1134 from itflow-org/add-release-system
Add release system - with admin update
2024-12-30 14:25:51 +00:00
wrongecho
8c3ea6404e Add versioning/release system - December 2024 / 24.12 2024-12-30 14:24:56 +00:00
wrongecho
e6f5c6c484 Merge pull request #1132 from itflow-org/add-release-system
Add versioning/release system - December 2024 / 24.12
2024-12-30 13:16:05 +00:00
wrongecho
469c495a73 Add versioning/release system - December 2024 / 24.12 2024-12-30 12:58:50 +00:00
wrongecho
4711955e17 Merge pull request #1131 from itflow-org/develop
Test - Merge develop into master
2024-12-30 11:59:16 +00:00
wrongecho
b014ddd6bd Merge pull request #1130 from itflow-org/test-my-feat
Test - ignore
2024-12-30 11:48:25 +00:00
wrongecho
6800a48cd4 Test - ignore 2024-12-30 11:39:34 +00:00
johnnyq
8a8af5525c Renamed header Sales to Billing on Main side nav 2024-12-28 14:24:37 -05:00
johnnyq
e56b4019e4 Rename client side menu header from Finance to Billing as its more suitable name 2024-12-28 13:10:04 -05:00
Johnny
eddf8d4016 Merge pull request #1129 from itflow-org/tidying
Tidying/General quality of life updates
2024-12-28 12:41:19 -05:00
Johnny
c78d0a175b Merge pull request #1128 from itflow-org/font-tidy
Stop using Source Sans Pro intermittently for some pages
2024-12-28 12:37:48 -05:00
Johnny
343365d31c Merge pull request #1127 from itflow-org/ticket-client-attachments
Client Portal Ticketing - Show attachments
2024-12-28 12:35:37 -05:00
Marcus Hill
c85626a937 Tidying/General quality of life updates
General quality of life updates:

- Ticket contact edit: 'No one' should be logged when ticket isn't associated with any contact, rather than a blank space; also fix email content
- Ticket portal/guest: Only show 'Assigned to' if someone is actually assigned
- Ticket tasks: Don't allow adding/modifying tasks for tickets in a resolved state
- Portal contacts: Properly align word 'Contacts' in a similar way all other page headings are aligned
- Client PDF export/handover: Now opens in a new self-closing window
2024-12-28 01:12:59 +00:00
Marcus Hill
fcfc6ff5e2 Stop using Source Sans Pro for some pages, we seem to use Sans Serif everywhere else 2024-12-27 23:02:24 +00:00
Marcus Hill
a6451c787e Client Portal Ticketing - Show attachments for each reply 2024-12-27 20:57:38 +00:00
johnnyq
a2f0f392be Moved Create and Disable Auto Pay from Hamburger menu to a button by Email Notify, also Tidied up the Header in add payment 2024-12-21 20:50:21 -05:00
johnnyq
74770a976a Added Auto Pay Options to Recurring Invoice Details 2024-12-21 20:37:46 -05:00
johnnyq
5611ac103d Recurring Payments - Added Auto Pay via cron, removed auto pay amount as it uses the recurring invoice amount, next up integrate with stripe 2024-12-21 20:25:21 -05:00
johnnyq
87a86803ee Added Recurring Payment Creation and Deletion and display in the recurring Invoice sections, still not operational need to add to cron 2024-12-21 18:49:42 -05:00
johnnyq
63015ab22d Feature: Recurring Payments created DB Structure 2024-12-21 16:46:21 -05:00
Johnny
3e0e30a480 Merge pull request #1126 from itflow-org/roles-perms
Move more things to new role perms system
2024-12-20 12:17:52 -05:00
Marcus Hill
bd7a156800 Move more things to new role perms system 2024-12-20 11:23:41 +00:00
wrongecho
dacbc51f95 Merge pull request #1125 from git-kup/master
tidy roles warning & global search
2024-12-19 12:04:33 +00:00
gt-business
8e385d8599 Update global_search.php 2024-12-18 18:57:10 -05:00
gt-business
7007c34e8d Update global_search.php 2024-12-18 18:56:26 -05:00
gt-business
c5cbfd50d2 Update global_search.php 2024-12-18 18:49:38 -05:00
gt-business
7ee04fa26a Update global_search.php 2024-12-18 18:48:42 -05:00
git-kup
4627736a8c make global search nicer 2024-12-18 18:10:22 -05:00
git-kup
56f00fe366 Update global_search.php 2024-12-18 17:50:33 -05:00
git-kup
d0998b7d0d Update admin_role.php 2024-12-18 16:35:08 -05:00
git-kup
5fccf5ffd4 Update admin_role.php 2024-12-18 16:33:20 -05:00
wrongecho
1281b7758f Merge pull request #1124 from Whit3XLightning/patch-1
client_files - check if file shared before assigning variables to prevent errors
2024-12-17 23:37:58 +00:00
Clayton Brown
608c9ef711 check if file shared before assigning variables.
Fixed an issue that produced warnings in the event a file had not been shared. The program was attempting to access a null ($row) array. Also fixed an issue where the author of an uploaded file ($file_uploaded_by) had not been declared in the scope it was being called.
2024-12-17 16:31:52 -06:00
johnnyq
829ee37a53 Add Current App Version by checking the current commit hash, also moved Database version on top with App Version in Debug 2024-12-16 14:24:38 -05:00
Johnny
803704c1ed Merge pull request #1123 from itflow-org/rec-tck-runnow
Recurring tickets
2024-12-16 14:03:47 -05:00
Marcus Hill
ac4a9b8ef2 Recurring tickets
- Allow forcing recurring tickets to run (e.g. cron broke, or you want to do a task early)
- Use new permissions system for recurring UI
- Bugfix: Ticket billable status wasn't saving/displaying on the edit modal
2024-12-16 12:11:29 +00:00
wrongecho
fae4f1e59d readme - we didn't hit stable in 2024, probs early next year now 2024-12-16 09:50:53 +00:00
Johnny
32ef744d6b Merge pull request #1122 from itflow-org/anon-tck-watcher
Anonymous/Guest tickets - Add the anon email as a watcher
2024-12-14 14:28:03 -05:00
Johnny
83cbb3daa3 Merge pull request #1121 from itflow-org/api-tck-fix-2
API - New tickets
2024-12-14 14:27:48 -05:00
wrongecho
68cfa12f1e Anonymous/Guest tickets - Add the anon email as a watcher 2024-12-14 17:31:06 +00:00
wrongecho
3eda726b2b API - New tickets
- Allow creating tickets for no client / no contact
- Set URL view key
- Fix line break after ticket details that causes odd email formatting
2024-12-14 17:06:03 +00:00
Johnny
19221b8749 Merge pull request #1119 from itflow-org/typeahead-os
Assets: Suggest operating systems when adding an asset
2024-12-14 11:53:33 -05:00
wrongecho
7577f505d5 Merge pull request #1120 from itflow-org/api-tck-fix
API - New ticket bugfix
2024-12-14 13:59:32 +00:00
wrongecho
e417badf92 API - New ticket bugfix
Ticket status should be 1, not 'New'
2024-12-14 13:55:39 +00:00
wrongecho
6d23cca51b Assets: Suggest operating systems when adding an asset 2024-12-14 13:37:40 +00:00
johnnyq
1a972d6a3e Added Fax in the UI 2024-12-13 15:59:20 -05:00
johnnyq
a21cb08914 DB Structure Update: Add Fax to location, Delete Vendor Contacts tables decided to merge vendor contacts and conacts as one table as contacts table already had a reference to vendor_id 2024-12-13 15:12:48 -05:00
Johnny
10496c2971 Merge pull request #1118 from itflow-org/bugfix-tck-feedback
Bugfix: Ticket feedback notifications
2024-12-13 11:49:10 -05:00
wrongecho
6df53db9da Bugfix: Ticket feedback notifications 2024-12-13 16:29:02 +00:00
johnnyq
0ffb39980f Started work on vendor contact post code 2024-12-12 19:27:19 -05:00
johnnyq
768511f6e5 Fix Non Existent warning file causing Javascipt to break in Users section 2024-12-12 17:55:55 -05:00
johnnyq
4681a340dc Fix Non Existent warning file causing Javascipt to break in Client Assets section 2024-12-12 11:37:34 -05:00
johnnyq
3eb1530dbc Initial Work on Vendor Details 2024-12-11 18:58:01 -05:00
johnnyq
580b7cd4c0 Added Vendor Contact Create and Edit Modals 2024-12-11 18:01:52 -05:00
johnnyq
4689b8c5c7 Remove ridicelous Export CSV Warning message 2024-12-11 16:30:42 -05:00
johnnyq
8ab82d9edf Really fix it now 2024-12-10 22:26:05 -05:00
johnnyq
41f60e6b21 Dont show update successfull if already updated 2024-12-10 22:23:53 -05:00
johnnyq
3b079de8ad Fix update_cli to get the proper latest db version 2024-12-10 22:19:41 -05:00
johnnyq
32d5e333c6 Renamed error_logs to app_logs, created app logs list view and renamed function logError to logApp, updated some of the log functions in cron and ticket mail parser to use the new appLog 2024-12-10 22:06:35 -05:00
johnnyq
d5e5a13fe7 Automatically select the current asset in asset details whjen creating a recurring or regular ticket 2024-12-10 20:51:16 -05:00
johnnyq
0bff350463 Add Recurring tickets list to contact details as well as the ability to Create and Edit Recurring contacts all witihin contact details 2024-12-10 20:40:47 -05:00
johnnyq
e24c79fbaf Add Recurring Tickets to asset details, added ability to open a ticket for asset in asset details, also recurring ticket 2024-12-10 20:23:04 -05:00
johnnyq
c0928e9b68 Dropped the Vendor Templates Table decided to use the same table, added Vendor Contacts Table to allow for more than 1 contact for a vendor 2024-12-10 17:47:41 -05:00
Johnny
d35d6a93b0 Merge pull request #1117 from ssteeltm/master
Ticket Summary with detected language
2024-12-10 15:48:34 -05:00
johnnyq
bb6a1c3cc7 Feature: Allow AI to Generate Document Templates with a prompt example Generate AD Structure Documentation, File Share etc 2024-12-10 15:47:12 -05:00
Hugo Sampaio
52da072711 Ticket Summary with detected language 2024-12-10 16:54:57 -03:00
johnnyq
1e05c7d524 Fix Ticket Summary move js inline with ticket.php as js files cant read php vars 2024-12-10 14:24:48 -05:00
johnnyq
c9a5df30d8 PHP Tag fix 2024-12-10 14:07:46 -05:00
johnnyq
2ac32ab0c5 AI Feature Ticket Summary: Summarieze an entire ticket 2024-12-10 14:03:43 -05:00
johnnyq
501c5fce15 Update update_cli script to only allow the script to run as the owner of the script preventing any permissions issues when updating via git. Also removed the --user option. to run the script you can use sudo -u USER php update_cli.php while in its path 2024-12-10 12:40:22 -05:00
johnnyq
f3faaa2a4e Revert Wireless Access Point to Access Point 2024-12-09 11:29:00 -05:00
johnnyq
1d8a78b279 Add Image Thumbnails and Previews for better image optimization update view image modal to JS and allow to move between images using previous and next arrows 2024-12-08 15:22:37 -05:00
johnnyq
c4870e49cf Ensure All commands are executed within the update and setup scripts directory 2024-12-07 15:53:17 -05:00
johnnyq
2cf2545f32 name script finalized 2024-12-07 15:49:07 -05:00
johnnyq
41743a529f Update CLI show help screen and show if an argument is invalid 2024-12-07 15:46:48 -05:00
johnnyq
6b8d02c6ef DB Update Add vendor_templates table to eventually seperate out templates from the vendors table 2024-12-07 15:38:35 -05:00
johnnyq
29f75fc69c Update CLI - Added option to specify a when update the app otherwise default to www-data 2024-12-07 15:26:29 -05:00
johnnyq
5f8b68ac3c Setup CLI Fix Country Example to include full country name and add additonal eg for timezones 2024-12-07 15:21:20 -05:00
johnnyq
a8328172e6 Allow force_update to be seperate from --update 2024-12-07 15:16:46 -05:00
johnnyq
926935ceb6 Add help to the update_cli and execute standard update by default also fix getting the current DB version 2024-12-07 15:09:29 -05:00
johnnyq
b43a7ec16d Initial work on update script via cli the update_cli.php can only be run via command line preventing web public dir execution 2024-12-07 14:46:08 -05:00
johnnyq
0a59ab33b9 Added setup_cli.php to allow to setup via the command line via interactive prompts and non intertactive by argument switches this allows for better automation of installing itflow in places like docker, ansible, HestiaCP Auto Install scripts etc 2024-12-07 14:09:15 -05:00
johnnyq
6501fc528e Add IP back to the default shown columns in assets 2024-12-07 12:45:09 -05:00
johnnyq
095c5b95ac Removed Physical Asset location in show additonal columns instead show Physical Location below location 2024-12-07 12:26:41 -05:00
johnnyq
193e9e3e01 Make Company Name clickable 2024-12-06 19:44:14 -05:00
johnnyq
e1b30f6c25 Update Side nav to use icon next to company 2024-12-06 19:40:10 -05:00
johnnyq
804164bc3f Center Align Company Name in side bar and downsize the font size 2024-12-06 19:17:15 -05:00
johnnyq
324f66b5fd Update the UI Header for Asset Selection on in the client assets and reports sections 2024-12-06 18:45:34 -05:00
johnnyq
74e7507f7d Change asset TV to Display, changed Firewall icon to Fire 2024-12-06 17:00:52 -05:00
johnnyq
acf5268139 Wording Fix for Share Link 2024-12-06 16:21:01 -05:00
johnnyq
26ca2ab907 Fix View After Delete and turn it into a switch 2024-12-06 16:10:56 -05:00
johnnyq
6ae18dbc43 Update UI in share Model Remove Views instead use Delete after view and set long expiration dates and chnage them to a radio buttons instead of select 2024-12-06 14:11:51 -05:00
Johnny
22f5bdb1c0 Merge pull request #1113 from itflow-org/invoice-guest-cancelled
Guest invoice view - cancelled
2024-12-06 11:42:39 -05:00
Johnny
9312aac7fc Merge pull request #1112 from itflow-org/portal-contacts-bugfix
Portal contacts
2024-12-06 11:42:24 -05:00
wrongecho
9bc1ebd7ea Merge pull request #1115 from itflow-org/fix-contact-related-logins
Bugfix contact related logins
2024-12-04 23:03:28 +00:00
wrongecho
8954287047 Merge pull request #1114 from itflow-org/tt-bulk-reply
Add time tracking for bulk ticket replies
2024-12-04 22:17:26 +00:00
wrongecho
4213a33652 TT for bulk resolve too 2024-12-04 21:14:35 +00:00
wrongecho
1caf33b7c2 Bugfix contact related logins. This was caused by login_id being used more than once due to joins 2024-12-04 17:20:13 +00:00
wrongecho
7afa1760f3 Add time tracking for bulk ticket replies
- TT for bulk replies
- Encourage the correct time format using a placeholder, pattern and required field (client-side validation only - still results in server error if you intentionally break it, for now)
2024-12-04 16:49:51 +00:00
wrongecho
425b06e550 Add time tracking for bulk ticket replies
- TT for bulk replies
- Encourage the correct time format using a placeholder and pattern (client-side validation only)
2024-12-04 16:43:09 +00:00
wrongecho
ab19d37f5f Guest invoice view
Make it clearer to guests when an invoice has been cancelled
2024-12-04 16:26:27 +00:00
wrongecho
da1b3b55b1 Portal contacts
- Bugfix not being able to edit contacts after the switch to storing contact creds in the users table
- Prevent a client adding contacts with duplicated emails
2024-12-02 18:01:29 +00:00
johnnyq
a31387720c Fix self avatar uploading 2024-11-27 13:34:39 -05:00
johnnyq
439d1bc3db Move Extension down one line in contact details 2024-11-27 12:55:17 -05:00
johnnyq
ad62edb7f6 Fix networks page not displaying dns if secondary dns server was not entered 2024-11-27 12:42:09 -05:00
johnnyq
f731104375 Fix Credential Deleting 2024-11-27 12:24:37 -05:00
johnnyq
53c888c4b8 Add User Type to session, along with user type check 2024-11-27 11:50:45 -05:00
johnnyq
8eb32a09b2 Feature You can now Add and Remove User type Software Licenses in Contact Details 2024-11-26 16:58:37 -05:00
johnnyq
bbed55a8ff Added Linking and unlinking services in contact details 2024-11-26 16:16:24 -05:00
johnnyq
5e8a6bfcd6 Added Unlinking of credentials and assets to contact details 2024-11-26 15:29:40 -05:00
johnnyq
cbbf8c27ba Fix Ticket Watchers not getting emails when No Contact is selected on a ticket, and add the ability to link files in contact details 2024-11-26 14:06:34 -05:00
johnnyq
8968476b7c Added Many to Many Linkage between contacts and documents, asset, credential linkage and unlinkage in contact details, more to come 2024-11-25 23:55:33 -05:00
johnnyq
8c296de205 Do not check to see if session is set before setting timezone always set timezone, Fixes MFA when switching timezones 2024-11-25 12:20:56 -05:00
johnnyq
5a8234db13 Remove branding from downloaded files via link and use original filename replaced old logging function in download with new logAction funtion 2024-11-25 11:58:08 -05:00
johnnyq
8050dffbb8 Enhancement: DB Structure Update: Seperate Logs into 3 seperate log tables error_logs, auth_logs, audit_logs. This will provide huge performance benefits and organization 2024-11-24 15:04:23 -05:00
johnnyq
94e2a4b1f0 Added Placeholder for Linking items to a contact in contact details 2024-11-24 13:06:26 -05:00
johnnyq
137438f873 Added Archive, Unarchive functions for contact notes along with the ability to add a note under client contact details page 2024-11-24 12:38:59 -05:00
johnnyq
8599729602 Defined a note_type_array in get_settings to define note type and associated icon incorporated the array into the Selectboxes to create note and the UI display in contact details 2024-11-24 12:11:31 -05:00
Johnny
276e3c79a0 Merge pull request #1107 from ColDog5044/master
Fix typos in admin_settings
2024-11-24 10:58:02 -05:00
Collin Laney
ffa677db30 Fix typo in admin_settings_quote.php
Fixed typo in placeholder for email address to notify when quotes are accepted/declined.

... leave bank for none -> ...leave blank for none.
2024-11-24 02:22:12 -05:00
Collin Laney
44a8431960 Fix typo in admin_settings_ticket.php
Fixed typo in placeholder for email address to notify when new tickets are raised.

... leave bank for none -> ...leave blank for none.
2024-11-24 02:20:45 -05:00
Collin Laney
47b720b063 Fix typo in admin_settings_invoice.php
Fixed typo in placeholder for email address to notify when invoices are paid online.

... leave bank for none -> ...leave blank for none.
2024-11-24 02:13:05 -05:00
johnnyq
a80fddfc0d Delete Contact Notes when contact is deleted also delete contact references when delting a client 2024-11-23 18:18:22 -05:00
johnnyq
724d4a347a Feature: Contact Notes / Interactions - Create an Add Model and display cpontact notes under contact details 2024-11-23 17:52:03 -05:00
johnnyq
1766b95fc4 Fixed table layout in Client Portal Documents, put pretty content in the portal footer instead as it caused issues with the XSS Protection Content-Security-Policy 2024-11-23 16:43:16 -05:00
johnnyq
1c0441060e FEATURE: Added Tables for Multiple Notes with note type to keep track of interactions and notes for clients, contacts, assets and vendors. UI to come next 2024-11-23 15:36:39 -05:00
johnnyq
504b28ee4c Fix Create / Copy Trips missing trip_id 2024-11-23 11:45:32 -05:00
wrongecho
b2651f7445 Merge pull request #1106 from itflow-org/user-create-fix
Bugfix: Creating users
2024-11-20 21:44:03 +00:00
wrongecho
a216f1bbf8 Bugfix: Creating users 2024-11-20 21:43:33 +00:00
johnnyq
c96833a977 When adding a ticket from contact details page make sure sure the contact is selected by default 2024-11-20 14:08:40 -05:00
johnnyq
fe24e3bcea Update Breadcrumbs to always have a link to the client for fast access to the client section. The breadcrumb order will change depending how you access using the global view or within the client section on Invoice, Quote, Ticket, Recurring Invoice 2024-11-20 12:41:29 -05:00
johnnyq
1e4306381f DB Optimizing in Ticket Selections and relogicify mark billable also more logging 2024-11-19 18:46:07 -05:00
johnnyq
dea702b45f Fix missing ) in Portal Post was a logging regression which also fixes poral logout 2024-11-19 18:22:53 -05:00
johnnyq
050d15579d More in depth logging ticket history and less passing vars from POT in ticket POAST 2024-11-19 18:18:32 -05:00
johnnyq
bbe2b1d2c9 Bump TinyMCE from 7.4.1 to 7.5.1 2024-11-19 16:08:20 -05:00
johnnyq
a10486a95c Breaking AI Change you must update the URL to include the full URL in settings > AI example for openai: https://api.openai.com/v1/chat/completions 2024-11-19 15:42:48 -05:00
johnnyq
dcedddcad6 Moved AI Reword Buttons to the WYSISYG toolbar, Seperated Document and ticket toolbars. Ticket Toolbar has items related to tickets while document has additional items related to documents 2024-11-19 15:33:14 -05:00
johnnyq
9d44d3e849 Uncomment contact add alert 2024-11-19 12:03:09 -05:00
johnnyq
b7163dad6d Add isset check on file upload 2024-11-19 11:59:52 -05:00
johnnyq
c181954960 Fix alert 2024-11-19 11:45:01 -05:00
johnnyq
ff3df12523 allow webp for users and profile 2024-11-18 18:19:57 -05:00
johnnyq
097e1c7b5f Add Acceptable File formats on the Client side, also allow webp for image file uploads in assets, locations, expenses and contact 2024-11-18 18:14:13 -05:00
johnnyq
34e09f32e0 Remove unessesary check if file has been uploaded as the function already does that 2024-11-18 16:29:42 -05:00
johnnyq
06314e136e Replicated previous fix by using enctype=multipart/form-data for bulk forms that have subforms that require a file upload 2024-11-18 16:16:00 -05:00
johnnyq
9d5818050e Fix Contact Photo not uploading when editing the first contact, odd fix but worked the edit contact forms are wrapped in a parent form on the entire table itself for Bulk changes. For some reason it wouldnt take the first edit modal form if we didnt enctype = multipart/form-data fo the parent form even though each edit subform has it already. it doesnt make sense but works 2024-11-18 16:07:22 -05:00
johnnyq
1a968abb35 Fix var for Reccuring Item added alert 2024-11-18 14:10:07 -05:00
johnnyq
32158872b2 get client id for logging when adding recurring items 2024-11-18 14:08:13 -05:00
johnnyq
c9b38b2b5f Show only logged in user notifications 2024-11-17 15:14:40 -05:00
johnnyq
eacb345c70 Only show notificaiton in alert window for logged in user and increase the limit from 5 to 8 2024-11-17 15:11:03 -05:00
johnnyq
cf6df1c2b1 Only show dismissed notifications pertaining to the logged in user 2024-11-17 15:09:30 -05:00
johnnyq
a81bcf350c When Dismiss all notifications are clicked only dismiss the notificaitons of the logged in user only 2024-11-17 15:03:05 -05:00
johnnyq
acec430e28 Fix var name in client edit post 2024-11-17 14:59:54 -05:00
johnnyq
9c24a780be More Checkbox enhancements, remove js from dashboard if finanacial isnt selected 2024-11-17 14:54:16 -05:00
johnnyq
b2fff24bd9 Change theme on click now instead of selecting them then hitting submit more ?? 0s for the form checkboxes 2024-11-17 14:33:31 -05:00
johnnyq
c2be946f7a Switched contact to use ?? 0 in post for checkbox items that are not checked, this save from creating an extra hidden form field in the form model hence cleaner code 2024-11-16 17:45:16 -05:00
johnnyq
978c7c5db4 Switched location to use ?? 0 in post for checkbox items that are not checked, this save from creating an extra hidden form field hence cleaner code 2024-11-16 17:38:19 -05:00
johnnyq
20a24b6ec6 Fix PHP error on login check if Array last_visited is set 2024-11-16 16:33:23 -05:00
johnnyq
20c87044b9 Only accept jpg, jpeg and png for company logo 2024-11-16 15:09:38 -05:00
johnnyq
5f4356546f Fix ticket post missing ) 2024-11-16 14:03:03 -05:00
johnnyq
7fd0a40ea1 logAction is used everywhere in ticket post, also did some logic tiday updates, but way more need to happen within ticket post so more to come 2024-11-16 14:01:08 -05:00
johnnyq
235d1641f0 Update Edit Ticket Logic, Moved fetching ticket info before check notify for logging and alerting and to reduce the amount of post data received 2024-11-16 12:34:13 -05:00
johnnyq
d5524f75b0 Format Alerting / Logging Currency for transfers 2024-11-15 16:05:57 -05:00
johnnyq
9d15721845 Fix Payment Amount logging 2024-11-15 16:00:02 -05:00
johnnyq
4ca9fbe655 wording 2024-11-15 15:31:47 -05:00
johnnyq
95ec0b2979 UI Update Setup: Move locale settings to its own screen 2024-11-15 15:28:20 -05:00
johnnyq
278ba079c3 Updated cron mail queue and cron email ticket parser to use new logAction and tidy up code 2024-11-15 13:40:04 -05:00
johnnyq
bc5e089e95 Updated login to use new logAction and tidy up code 2024-11-15 13:07:38 -05:00
johnnyq
7b9229d926 Updated Portal post to use new logAction and tidy up code 2024-11-15 12:53:41 -05:00
johnnyq
881f498237 Wording Updates Azure to Entra 2024-11-15 12:31:10 -05:00
johnnyq
a6a94e3ccd More logAction function updates to client portal entra login amd cleaned up the client entra login portal for better presentation of vars 2024-11-15 12:29:46 -05:00
johnnyq
412462a4c0 More logAction function updates to client portal login amd cleaned up the client login portal for better presentation of vars 2024-11-15 12:21:55 -05:00
johnnyq
577d97b471 Updated ajax.php to use the new logAction function 2024-11-15 11:53:43 -05:00
johnnyq
ed92592aa6 Check to see if arrays are set before executing for each loops to prevent php errors 2024-11-14 19:13:56 -05:00
johnnyq
e9f023f0c7 Updated all API functions to use the new logAction Function 2024-11-14 18:27:31 -05:00
johnnyq
bfffec7363 Temp added vars session_ip and session_user_agent to validate_api_key so IP and User agent is logged with the new logAction function 2024-11-14 17:55:35 -05:00
johnnyq
ba5e2b216b Updated asset API to use new logAction function 2024-11-14 17:42:01 -05:00
johnnyq
77aede8bab Updated the remaining posts except ticket to use new logAction function, tidy and added more details to logging 2024-11-14 17:32:26 -05:00
johnnyq
5bdd5d1f79 Finished Updating admin / settings posts to use new logAction function, tidy and added more details to logging 2024-11-14 17:20:52 -05:00
johnnyq
ef651f5248 Updated admin posts to use new logAction function, tidy and added more details to logging 2024-11-14 16:07:35 -05:00
johnnyq
8ffa90ae28 Updated vendor post to use new logAction function, tidy and added more details to logging 2024-11-14 13:39:17 -05:00
johnnyq
670390f1d3 Updated trip post to use new logAction function, tidy and added more details to logging 2024-11-14 13:16:23 -05:00
johnnyq
2047a6d18d removed old logging line in transfer 2024-11-14 12:52:56 -05:00
johnnyq
5d8b9ac600 Updated transfer post to use new logAction function, new role checking, tidy and added more details to logging 2024-11-14 12:51:26 -05:00
johnnyq
22f54886e2 Fix: Broken Create Quote - regression in logging 2024-11-14 11:56:12 -05:00
Johnny
653b174830 Merge pull request #1105 from itflow-org/import-chk
Import CSV - Check file uploaded
2024-11-14 11:17:11 -05:00
Johnny
b5256fb529 Merge pull request #1104 from itflow-org/quote-notifs
Quote notifications
2024-11-14 11:16:18 -05:00
Johnny
99b482ab30 Merge pull request #1103 from itflow-org/debug-tweak
Clarify notes on debug
2024-11-14 11:12:46 -05:00
Johnny
45b61da29a Merge pull request #1102 from itflow-org/archive-typo
Fix typo in ticket archived logging
2024-11-14 11:12:20 -05:00
wrongecho
7a561a8c2e Import CSV - Check file uploaded
Check the file was uploaded when importing a CSV. Can probably convert this into a function at a later date.
2024-11-14 11:51:39 +00:00
wrongecho
28a0343a97 Quote notifications
- Send an internal email when quotes are accepted/declined
- Clients are prompted to confirm accept/decline with confirm-link
- Tidy
2024-11-14 11:23:28 +00:00
wrongecho
9fe9d8e9ff Clarify notes on debug 2024-11-14 08:44:08 +00:00
wrongecho
fc94d71795 Fix typo in ticket archived logging 2024-11-14 08:08:52 +00:00
johnnyq
e4f618c150 More work on Updating ticket post to use new logAction function, added more ticket history updates, tidy and added more details to logging, lots of logic changes need to happen here 2024-11-13 18:46:28 -05:00
johnnyq
52284231bb Remove Dup Edit Priority Logic from ticket post and fix priority from > to 2024-11-13 17:56:28 -05:00
Johnny
05ff7e145c Merge pull request #1101 from ThaMunsta/feedback-notification
Update guest_post.php
2024-11-13 22:49:37 +00:00
johnnyq
56361c7008 Partially Updated ticket post to use new logAction function, added some ticket history updates, tidy and added more details to logging 2024-11-13 17:48:24 -05:00
ThaMunsta
93b5c6aab1 Update guest_post.php
fix hotlink on notification
2024-11-13 17:25:58 -05:00
johnnyq
47a4fa78a8 Updated task post to use new logAction function, tidy and added more details to logging 2024-11-13 17:22:07 -05:00
johnnyq
2ec4be8154 Updated software post to use new logAction function, rework array handling tidy and added more details to logging 2024-11-13 17:13:55 -05:00
johnnyq
a86eecf63b Updated service post to use new logAction function, rework adding / ediing arrays tidy and added more details to logging 2024-11-13 17:02:06 -05:00
johnnyq
ed02c2aa3e Updated revenue post to use new logAction function, new role check function tidy and added more details to logging 2024-11-13 16:23:35 -05:00
johnnyq
b408a31cde Updated rack post to use new logAction function, new role check function tidy and added more details to logging 2024-11-13 15:46:20 -05:00
johnnyq
cf22f01df4 Updated quote post to use new logAction function, tidy and added more details to logging 2024-11-13 15:28:24 -05:00
johnnyq
96649af18b Updated project post to use new logAction function, tidy and added more details to logging 2024-11-12 18:50:30 -05:00
johnnyq
c5aa22a832 Updated profile post to use new logAction function, tidy and added more details to logging 2024-11-12 18:26:04 -05:00
johnnyq
115640fc89 Updated product post to use new logAction function, tidy and added more details to logging and add permission check 2024-11-12 18:09:00 -05:00
johnnyq
08c8153d64 Updated network post to use new logAction function, tidy and added more details to logging 2024-11-12 17:41:56 -05:00
johnnyq
640a068026 Fix forloop regressions forgot to include POST duh 2024-11-12 17:30:53 -05:00
johnnyq
b88e111c64 Updated location post to use new logAction function, tidy and added more details to logging 2024-11-12 17:22:22 -05:00
johnnyq
e45b543ff8 Format Payment for currenct in alerting 2024-11-12 15:16:57 -05:00
johnnyq
b305758152 Finished Updating invoice post to use new logAction function, and appNotify function tidy and added more details to logging 2024-11-12 15:09:55 -05:00
johnnyq
651726c9ea Fix broken client link in audit logs 2024-11-12 11:26:43 -05:00
johnnyq
808b190c8d Fix broken AI Settings 2024-11-12 11:01:24 -05:00
johnnyq
e91c0b09b7 wording, fix 2024-11-11 17:46:10 -05:00
johnnyq
c61ec7def6 Partially Updated invoice post to use new logAction function, tidy and added more details to logging 2024-11-11 17:39:18 -05:00
johnnyq
1b8722eb90 Updated folder post to use new logAction function, tidy and added more details to logging 2024-11-11 16:13:44 -05:00
johnnyq
2a5945816d Updated file post to use new logAction function, tidy and added more details to logging 2024-11-10 14:37:02 -05:00
johnnyq
e58bf3d558 Updated epenses post to use new logAction function, tidy and added more details to logging 2024-11-10 13:32:42 -05:00
johnnyq
1ebd537d9d Updated Cron to use new logAction function, also updated logAction cron to make session_user_id 0 if not set 2024-11-10 12:44:10 -05:00
johnnyq
5d147c0d7a Replaced old logging with new logging function in domain event post along with tidy, wording updates and better logging and replaced one line with appNotify function 2024-11-10 12:16:30 -05:00
johnnyq
bd8ef62133 Replaced old logging with new logging function in domain post along with tidy, wording updates and better logging 2024-11-09 19:14:53 -05:00
johnnyq
51a6f7fa8f Removed left over old logging functionality in document post 2024-11-09 18:10:58 -05:00
johnnyq
93c64c7467 more wording updates 2024-11-09 18:08:19 -05:00
johnnyq
9e9c1100f8 wording update 2024-11-09 18:04:00 -05:00
johnnyq
0917633848 Replaced old logging with new logging function in document post along with tidy, wording updates and better logging 2024-11-09 18:01:59 -05:00
johnnyq
ae06ddb068 Replaced old logging with new logging function in credential post along with tidy, wording updates 2024-11-09 15:07:55 -05:00
johnnyq
60a0ebeeb6 added domain name in client creation logging 2024-11-09 13:23:40 -05:00
johnnyq
659aa7a788 Replaced old logging with new logging function in client post along with tidy, wording updates 2024-11-09 13:19:57 -05:00
johnnyq
cc97331676 Replaced old logging with new logging function in certificate post 2024-11-09 12:41:24 -05:00
johnnyq
ac2bbd55a7 Replaced old logging with new logging function in budget post 2024-11-09 12:29:15 -05:00
johnnyq
59cf67814a Functionalize Logging and tidy Asset Posts 2024-11-08 18:07:22 -05:00
johnnyq
365cd6dcae Functionlized logging for account post and wording tidy updates to account post as well 2024-11-08 16:37:05 -05:00
johnnyq
119b2d0fbc Functionalized logging for contact post and some tidying there as well 2024-11-08 16:23:24 -05:00
johnnyq
7b4dda0ad6 Functionalize logging, replaced old logging in contact add with new logging function 2024-11-08 14:40:14 -05:00
johnnyq
3d5e1a1811 Bulk Logic update for files to mimic document bulk deletion 2024-11-08 13:06:42 -05:00
johnnyq
e2f7537517 Add Bulk Document Deletion 2024-11-08 13:02:03 -05:00
johnnyq
1090794f7f Added Bulk File Delete support, Added new user role / permission enforcement on the file posts 2024-11-08 12:20:18 -05:00
johnnyq
01c9e8604f Updated the cron php script to use app notify removed the _esc from ids in cron ticket email parser as ids are always escaped as ints 2024-11-07 12:30:07 -05:00
johnnyq
a5cd1e1f1a Replaced old notification with new appNotify in all the Guest_ PHP Scripts 2024-11-07 12:13:05 -05:00
johnnyq
53724c3012 Clarify Contact Billing Role that they will receive a copy of invoices 2024-11-07 11:46:37 -05:00
johnnyq
68c47ee87d Updated appNotify function to allow null for client_id entity_id and action, also updated all the notification instances to use the new appNotify in cron.php, starting to drop the entity_id as well 2024-11-06 20:56:28 -05:00
johnnyq
db621a97fa FEATURE: appNotify Function added so each user can get their own notificaiton and can individually dismiss and see their own notifications, only works under invoice viewed right now 2024-11-06 18:58:45 -05:00
johnnyq
af9ec9ca85 Fix broken portal login and password reset due to the timezone set before the session was initiated, now we set the timezone after session has started 2024-11-06 17:55:46 -05:00
Johnny
6dbf6f0778 Merge pull request #1100 from itflow-org/admin-footer-banner
Add banner to admin footer
2024-11-06 15:13:59 -05:00
wrongecho
1dd6a02a15 Add banner to admin footer
To contain the app version, once we move to doing dev/master branches with releases.

Also adding the standard links to the forum, docs and sponsor services page.
2024-11-06 12:56:29 +00:00
wrongecho
1a66ad9070 Add banner to admin footer
To contain the app version, once we move to doing dev/master branches with releases.

Also adding the standard links to the forum, docs and sponsor services page.
2024-11-06 12:54:38 +00:00
johnnyq
351bb484a7 Reworked the entire debugger, only grather nessesary info and database comparison to existing and db.sql works now 2024-11-05 17:36:50 -05:00
johnnyq
2250269820 small Fixes UI Cleanups in checks 2024-11-05 15:35:58 -05:00
johnnyq
0d935fa221 Run various Checks (required PHP extentions, shell commands, ssl checks, fqdn check, directory permissions check, php settings check etc during setup 2024-11-05 15:19:23 -05:00
johnnyq
c41b391cb1 SET SQL TIMEZONE on Session, this fixes the issue where created,deleted,updated,archived_ats using SQLs current_timestamp() are set to UTC-0 in SQL causing issues with displaying data in ITFlow as PHP is set to the timezone selected. Note its optional to set system timezone 2024-11-05 13:47:38 -05:00
johnnyq
a3a0a3e8c6 Add xcustom and /post/xcustom to the git ignore list so git doesnt overwrite them except for the readme.php inside them 2024-11-04 22:03:57 -05:00
johnnyq
304623fc05 Guest View Invoice - Fix extra <th> tag in Outsanding Invoices Table 2024-11-04 16:41:57 -05:00
johnnyq
23cc47f8f5 DB Stucture Update: Added Ticket History Table to keep track of ticket events such as priority changes, ticket status, assignment, task completion etc 2024-11-04 12:21:47 -05:00
johnnyq
5211ba73d5 Moved Create Edit User code block towards the top of edit contact user to reduce the query by 1 2024-11-02 16:45:59 -04:00
johnnyq
593f09f6fd Fix issue with creating a contact without a user and then trying to create a user by editing the contact. 2024-11-02 16:25:50 -04:00
Johnny
ada0d52dc0 Merge pull request #1099 from itflow-org/aad-to-entra
Portal SSO - Rename AAD to Entra
2024-11-02 12:40:03 -04:00
Johnny
b71bc508f9 Merge pull request #1098 from itflow-org/cal-rep-dis
Disable calendar repeat for now until we properly add it
2024-11-02 12:39:54 -04:00
Johnny
b4f1cb7d8f Merge pull request #1097 from itflow-org/ticket-status-no-reply
Ticketing updates
2024-11-02 12:39:37 -04:00
Johnny
3dd7006ba4 Merge pull request #1096 from itflow-org/db-prune
Prune old database update logic (2+ yrs old)
2024-11-02 12:39:27 -04:00
Marcus Hill
2e2a992c32 Portal SSO - Rename AAD to Entra 2024-11-02 10:54:19 +00:00
Marcus Hill
d074ddad9f Disable calendar repeat for now until we properly add it 2024-11-02 10:50:30 +00:00
Marcus Hill
13f89d2118 Ticketing updates
- Allow changing ticket status without adding a reply (just leave the response blank)
- Bugfix: Contact change email didn't include URL key
- Make it clearer when nobody is assigned to a ticket
2024-11-02 10:22:31 +00:00
Marcus Hill
d8d455e324 Prune old database update logic (2+ yrs old) 2024-11-02 09:56:09 +00:00
johnnyq
eb70aba430 Also fix the credential tagging in client asset details page 2024-11-01 17:49:48 -04:00
johnnyq
5215ff9a7e Add Group By to logins to prevent duplicated logins from appearing, fixed client contact details from breaking because of missing login tag query 2024-11-01 17:21:55 -04:00
johnnyq
631163d691 Fix Extra spacing in Ticket to Invoice Description 2024-10-31 17:21:47 -04:00
johnnyq
2f182d8c3c tidy 2024-10-31 16:33:15 -04:00
johnnyq
08830fd21f CONTINUE BIG FIX: Adjust the breadcrumbs according to if you are in client section or main section when view ticket, invoice, quote, recurring ticket details 2024-10-31 16:30:34 -04:00
johnnyq
72240462a0 CONTINUE BIG FIX: Adjust the reaminder of links within client section 2024-10-31 15:56:20 -04:00
johnnyq
4e72925c21 BIG FIX: When accessing ticket, invoice, recurring invoice or quote details while in the client section of ITFlow keep the Client Side Nav instead of redirecting back to the Main Nav. This caused much confusion in the past. This will improve naviagtion in those areas greatly 2024-10-31 15:40:02 -04:00
johnnyq
5a6cf0ccac Revert Reoslved count as ins included when you click on Closed Add Mouse Hover Effects to Header Open and Closed Status 2024-10-31 13:39:51 -04:00
johnnyq
5af8d6934b Add Resolved Tickets Count and Select option for tickets 2024-10-31 13:26:34 -04:00
johnnyq
d35880e658 Disabled logging execution time of the mail parser 2024-10-30 21:04:16 -04:00
johnnyq
0ee5828bf3 Fix contact creation when emailing into the ticket parser with domain matching a client 2024-10-30 19:54:47 -04:00
johnnyq
910787c81c Fix Custom Links in the Top nav from breaking ITFlow if the database isnt updated to 1.4.6 2024-10-30 19:49:39 -04:00
johnnyq
1df98166bd Fix issue with Contacts API - Removed contact_auth from Contacts call to the API 2024-10-30 19:35:26 -04:00
johnnyq
c3321dcb0b Removed temp admin_fix file 2024-10-30 19:18:21 -04:00
johnnyq
70569fc226 Scans all files and matches them with the reference file in DB then sets the file size and Mime Type. Note this update doesnt do any DB Structure changes 2024-10-30 19:17:21 -04:00
johnnyq
241b0008e8 Updated DB Structure 2024-10-30 18:39:49 -04:00
johnnyq
3cc9c0720d FEATURE: Files now shows File Size, Mime Type, and who uploaded the file. These fields will only populate on newly uplaoded files, existing ones will show 0 or blank 2024-10-30 18:39:00 -04:00
johnnyq
883976529d UI Update to files, add Breadcrumbs, change file icon to dark 2024-10-30 17:05:58 -04:00
johnnyq
d60f5a9f86 FEATURE: Nested folders in Files 2024-10-30 16:55:19 -04:00
johnnyq
5d9b161b19 Wording Updates 2024-10-30 15:49:39 -04:00
johnnyq
96bdca5a4d UI Update: Reworked the Documents UI Folder Path is not located on the Right, Moved Search on the top when in root directory it searches all files when in a directory searches in current directory 2024-10-30 15:43:15 -04:00
johnnyq
a6ac215f8d FEATURE: Added Bulk Tag Assignment to Credentials 2024-10-30 15:07:51 -04:00
johnnyq
3b45f8e255 Remove login id beside the name, this was for debugging only 2024-10-30 14:53:48 -04:00
johnnyq
807bbef3e2 Use Tag array instead of querying by tag name when clicking on a tag to reveal other items with the same tag, this allow more narrowed searches 2024-10-30 14:51:39 -04:00
johnnyq
873df63c76 FEATURE: Added Credential Tagging Support 2024-10-30 14:40:02 -04:00
johnnyq
58738debc6 Fix for users on DB 1.5.9 updating to 1.6.0 check to see if login_folder_id exists before adding it and Makming sure all ticket statuses are a number 2024-10-30 12:13:26 -04:00
johnnyq
219028c6d1 Updated Anon and Archive Function to archive the user and set names to Archived - UnixTimeStamp 2024-10-30 11:41:39 -04:00
johnnyq
11f68a59f3 Fix Archive Contact, removed unused fields 2024-10-30 11:26:07 -04:00
johnnyq
990335838e Added First Asset History Item, Asset Created, also delete asset history when you delete an asset 2024-10-29 19:00:02 -04:00
johnnyq
c08ac330be FEATURE: Credential Tags Initial DB Structure Commit 2024-10-29 18:33:17 -04:00
johnnyq
926a796602 Replaced logs, with asset_history in client assets 2024-10-29 18:23:05 -04:00
johnnyq
f52beed3d0 Added asset history table 2024-10-29 18:16:28 -04:00
johnnyq
c3379a5576 Increase DB Field Sizes 2024-10-29 15:41:10 -04:00
johnnyq
ab3d915bdc Mail Ticket Parser Fix: Allow Unencrypted IMAP connections 2024-10-29 13:36:30 -04:00
johnnyq
af123d3978 Fix Only show Document Folders, Removed Create Subfolder as this is now merged into Create Folder Dependign on what folder you are in 2024-10-28 22:12:45 -04:00
johnnyq
1d4165f41a Updated Bulk Document Move to include the indented folder and sub folder structure 2024-10-28 18:47:43 -04:00
Johnny
bc211f3824 Merge pull request #1095 from itflow-org/tidy-28
Tidying
2024-10-28 18:31:13 -04:00
Johnny
5f708f6003 Merge pull request #1094 from itflow-org/force-mfa
Force setup of MFA on login
2024-10-28 18:21:32 -04:00
johnnyq
cb611a764b Rework Move Document to not utilize a function 2024-10-28 18:05:45 -04:00
johnnyq
580e6a55ce Remove garbage code 2024-10-28 17:54:33 -04:00
johnnyq
77fce6a69d FEATURE: Implemented SubFolders within Documents UI 2024-10-28 17:53:44 -04:00
wrongecho
91c01d2cdb Tidying 2024-10-28 21:16:15 +00:00
wrongecho
334829c23e Force setup of MFA on login 2024-10-28 21:01:55 +00:00
johnnyq
9491643a4b Fix issue where sometimes the due date is invisible when viewing an invoice from the guest link 2024-10-28 13:32:41 -04:00
johnnyq
56feefe612 Remove Create Ticket from Template dropdown in Contact Details 2024-10-26 19:20:06 -04:00
johnnyq
5094453550 Define processed and unprocessed email count for logging 2024-10-26 13:48:54 -04:00
johnnyq
41f2177788 Ticket Email Parser Add Debugging after each run to calculate emails processed and unprocessed including the execution time of the script 2024-10-26 13:42:48 -04:00
johnnyq
d3cca2e633 Fix Invalid var 2024-10-26 13:21:13 -04:00
johnnyq
07d89ad09d Re-add Functions after test 2024-10-26 13:14:56 -04:00
johnnyq
01db0ddc3c Do not use the autoloader to load php mime mail parser 2024-10-26 13:09:21 -04:00
johnnyq
46572afc77 Mail Parser: Use UIDs instead of Message Sequence Numbers, this could potentially fix the issue of repeating tickets 2024-10-26 13:06:53 -04:00
johnnyq
6c402942e4 Mail Parser: Better way to set important flag then remove seen flag 2024-10-26 12:48:41 -04:00
johnnyq
72eaf3d269 Email Ticket Parser: Fix Flagged Email from getting marked as read, use imap_store function to flag emails not processed as this function keeps the email as unread 2024-10-26 12:26:03 -04:00
johnnyq
71f7fa2683 Started working on Archiving Contact Options Dialog for when archiving a contact 2024-10-26 11:58:04 -04:00
johnnyq
ae561d3195 FEATURE: New Invoice Status Non-Billable 2024-10-25 14:33:12 -04:00
johnnyq
58f995ed37 Fix Invalid Field change in cron.php causing cron to break 2024-10-24 22:30:16 -04:00
johnnyq
aa2e0ed5c5 carry over the Task Completion estimate When creating a new ticket from a template 2024-10-23 14:13:05 -04:00
johnnyq
636c74dbb0 FEATURE: Added Task Completion Estimate to the UI 2024-10-23 14:06:41 -04:00
johnnyq
dffc97859d FEATURE: Estimated Time Completion on Tasks - Phase 1 DB Structure update 2024-10-23 13:28:46 -04:00
johnnyq
808fdf5f76 When Archiving, Unarchiving, Deleting and Bulk Actions also update the associated user as well 2024-10-23 12:40:32 -04:00
johnnyq
55c9c76194 Fix Self Password Reset via Portal 2024-10-23 00:46:02 -04:00
Johnny
0a63ed2cd6 Merge pull request #1091 from itflow-org/bugfix-tck-schd-notif
Bugfix: Ticket scheduling emails
2024-10-23 00:29:00 -04:00
johnnyq
f2dedbf8e8 Cmplete Migrate Contact Users to Users 2024-10-22 23:53:14 -04:00
johnnyq
ee19e1b967 Check for user type of during login and set a temp if condition on check_login.php to see if user_type field exists and query user based off that result, the condition will be removed at a later date 2024-10-22 17:06:18 -04:00
johnnyq
ba64a179c6 Add contact_user_id to contacts table to associate a contact with a user 2024-10-22 16:34:08 -04:00
wrongecho
30738ed9fd Bugfix: Ticket scheduling emails
Scheduling a ticket should only send an email if config_ticket_client_general_notifications is enabled
2024-10-22 19:42:40 +01:00
johnnyq
499f9456f8 DB Update add user_role_type to differentiate between itflow users, client users and api permissions 2024-10-22 14:08:50 -04:00
johnnyq
48b306452c Phase 1 - Combining contact logins with users table - Add User Type field to users table 2024-10-22 13:47:44 -04:00
johnnyq
ea494a8b5c Fix FullCalendar Links 2024-10-21 13:53:40 -04:00
johnnyq
b456caa129 Bump FullCalendar from 6.1.10 to 6.1.15 2024-10-21 13:48:29 -04:00
johnnyq
b1de0c86f6 Fix Broken Client Details page 2024-10-21 13:36:44 -04:00
johnnyq
47c6c70c67 Bump DataTables from 2.0.8 to 2.1.8 2024-10-21 12:29:05 -04:00
johnnyq
a93187fdf8 Add Number of Tasks in the ticket template selection when creating a ticket 2024-10-20 14:49:50 -04:00
johnnyq
c214c12d00 FEATURE: Auto Populate Create Ticket when selecting a template, remove old ticket mail parser code 2024-10-20 14:34:09 -04:00
johnnyq
061e912123 Tidy 2024-10-20 12:48:14 -04:00
johnnyq
fccc8ab8fd Fix adding a device to a rack: Unit Start number cannot be higher than Unit End number 2024-10-19 16:34:03 -04:00
johnnyq
c32c47785e Fix notification action log path for cron successully run 2024-10-19 16:13:36 -04:00
johnnyq
ab9ae71ac7 Do not resanitize subject after passed to the create/update ticket function as its sanitized before passing to the functon, this caused unessesary slashes in the subject line if sql escape chars were used 2024-10-19 15:56:26 -04:00
johnnyq
051fdda9a8 Bump TinyMCE from 7.3.0 to 7.4.1 2024-10-18 18:08:39 -04:00
johnnyq
36af07c837 Bump PHPMailer from 6.9.1 to 6.9.2 2024-10-18 18:02:09 -04:00
johnnyq
1e964fe90a Remove WEBKLEX-PHP_IMAP Libraries 2024-10-18 17:44:43 -04:00
johnnyq
6cd5290f4c Migrate cron_ticket_email_parser.php back to using php-mime-mail-parser libraries and php extensions php imap and php Mailparse while still keeping the new functionality from the webklex php-imap version of this script. There were wayyy to many dependcies with WebKlex and ran into way too many problems. This delays OAAUTH2 until we can find a better solution 2024-10-18 17:29:45 -04:00
johnnyq
02e3ca3f52 Wording 2024-10-18 16:12:11 -04:00
johnnyq
64a3f8f1cc UI Update of Client Add / Edit Modals - Moved Lead Checkbox next to Name, Moved Shortned Name and tags to main tab 2024-10-18 16:00:41 -04:00
johnnyq
b15a175044 When creating Ticket from main ticket listing and not the client listing make Client Selectable first 2024-10-18 15:42:09 -04:00
johnnyq
8dca7bc183 Simplify Ticket Creation and Edit Model by removing unessesary tabs and combining fields to fewer tabs 2024-10-18 15:40:17 -04:00
johnnyq
6c1c5d6523 Simplify Ticket Template Creation by putting all fields into 1 modal tab instead of multiple and removing the ability to ass tasks via add ticket template, this should be done in the details 2024-10-18 15:11:54 -04:00
johnnyq
d01d912154 Move logout to a file logout.php in /post fixes issue where one cant logout if in admin section, also redirect to login page with or without login key if set 2024-10-18 00:12:08 -04:00
johnnyq
fe86ca0dd7 Bump php-mime-mail-parser from 8.0 to 8.0.4 2024-10-17 23:33:53 -04:00
johnnyq
77ed7aa7ff Updated new cron mail parser 2024-10-17 23:15:39 -04:00
johnnyq
646b94d8ab Initial work on new Mail Parser that uses the old php imap libraries and not the new webklex 2024-10-17 20:55:23 -04:00
johnnyq
878e145550 When Editing Recurring Expense use the Next Month Date instead of selecting the month that the recurring expense was initially created 2024-10-15 18:28:53 -04:00
johnnyq
bfd5973be8 Fix Bulk Actions by removing input form requirements for Create asset ticket as they share one giant form 2024-10-12 15:38:43 -04:00
johnnyq
5bc260e0c0 Wording Fix 2024-10-11 12:31:55 -04:00
johnnyq
0fc6a2f02c Keep contact contact within the media body 2024-10-10 18:13:35 -04:00
johnnyq
4289ba3026 Display Link Location Name in the Custom Links Listing 2024-10-10 17:37:53 -04:00
johnnyq
22086bef24 Optimize Guest Post to only selecting the required Database Table Fields and Tidy 2024-10-10 17:01:40 -04:00
johnnyq
0954579216 rename admin to administration and use user-shield icon 2024-10-10 16:57:27 -04:00
johnnyq
e37df8bf4b Fix Custom Link Order to ASC instead of DESC as well 2024-10-10 16:53:31 -04:00
johnnyq
ab1c5ac631 FEATURE: Custom Links can be added to the Top Nav Note must have icons 2024-10-10 16:51:00 -04:00
johnnyq
eaab9b75de Send InApp Notification when Quotes have been Declined or Accepted, also show status under guest url 2024-10-10 15:28:30 -04:00
johnnyq
2b2840a43c When Adding a Ticket Template to a Project Template use the Template name and not the subject also optimized Query 2024-10-10 14:42:57 -04:00
johnnyq
4963f2f385 Add Ticket Category to New Ticket and Bulk add Tickets through assets 2024-10-10 01:38:21 -04:00
johnnyq
a9ebc1395c Fix Repeating ticket number when adding bulk tickets via assets 2024-10-10 01:08:12 -04:00
johnnyq
70ae55eacb Tidy 2024-10-09 15:49:42 -04:00
johnnyq
134f4f9ad3 FEATURE: Create Ticket for each asset in Bulk 2024-10-09 15:24:40 -04:00
johnnyq
bbdc83e57e Add Cron Execution Notify placeholder to notifications 2024-10-09 14:01:42 -04:00
johnnyq
ef3c87f5d9 Added some headings to notifications to help seperate them 2024-10-09 13:25:34 -04:00
johnnyq
6fa3aea520 Add placeholder for ITFlow Update Notification to Notifications Settings 2024-10-09 13:15:53 -04:00
johnnyq
51578cd743 Update Wording 2024-10-09 13:12:35 -04:00
johnnyq
66a28685a3 Add Place Holders for Certificate, Asset Warranty and Shared Item View to the Notifications settings, also removed 120 Days from the Notifications Settings page 2024-10-09 13:10:52 -04:00
johnnyq
246878a32f Create Notification if a shared item was viewed 2024-10-09 12:56:55 -04:00
johnnyq
ce9a0b903f Added Shared Item Recipient to Files, Documents and Credentials 2024-10-09 12:36:22 -04:00
johnnyq
d0769b9f6b Added Shared Item Recipient Email to the Shared Items list in overview 2024-10-09 12:13:26 -04:00
johnnyq
f1a90156c2 Expose more Admin Options in the Side menu without having to expand sub menus 2024-10-08 18:44:08 -04:00
Johnny
b0c592831e Merge pull request #1090 from itflow-org/tidy
Tidying
2024-10-08 18:24:06 -04:00
wrongecho
b9e37d4052 Tidying
- Move more things to new permissions system
- Deduplicate assets post logic into model
- Swap out some "SELECT *" queries when only a couple of rows are actually needed
2024-10-08 23:10:27 +01:00
wrongecho
987cd59764 Tidying
- Move more things to new permissions system
- Deduplicate assets post logic into model
- Swap out some "SELECT *" queries when only a couple of rows are actually needed
2024-10-08 23:08:05 +01:00
johnnyq
ac3ab1dedb Add Notes about setting up cron, Add ITFlow Docs Custom Link when you setup ITFlow 2024-10-08 17:49:41 -04:00
johnnyq
7eee69366a Show Example of what Phone masking Enable vs Disabled 2024-10-08 16:13:03 -04:00
Johnny
e90200aebe Merge pull request #1089 from itflow-org/bugfix-template
Ticket templates - edit bugfix
2024-10-07 11:37:14 -04:00
wrongecho
ff954b0060 Ticket templates - edit bugfix 2024-10-07 12:18:09 +01:00
wrongecho
3c73c4d34a README.md - Add Sponsor: F1 For Help 2024-10-07 07:49:24 +01:00
Johnny
4309fcc48c Merge pull request #1088 from itflow-org/doc-revisions-updatedby
Docs - Show user updated by in revisions
2024-10-06 21:36:47 -04:00
Johnny
893eb16819 Merge pull request #1087 from itflow-org/invoice-pay-addr
Invoices - Send email notif when paid
2024-10-06 21:36:13 -04:00
Johnny
e5472e2cb1 Merge pull request #1086 from itflow-org/portal-login-logs
Portal login logs
2024-10-06 21:35:53 -04:00
Johnny
315a90a913 Merge pull request #1085 from itflow-org/debug
Add notes to debug page
2024-10-06 21:35:38 -04:00
wrongecho
ab18005d72 Docs - Show user updated by in revisions 2024-10-06 21:43:07 +01:00
wrongecho
a9de75aa99 Invoices - Send email notif when paid 2024-10-06 20:59:54 +01:00
Marcus Hill
377c5952d7 Portal login logs
- Mention contact ID in audit log if password is incorrect
- Mention in audit logs if invalid email/auth method
2024-10-06 16:38:48 +01:00
Marcus Hill
afe378d2f3 Add notes to debug page 2024-10-06 16:25:58 +01:00
Johnny
c948ccff5c Merge pull request #1084 from itflow-org/budget-perms
Budget - CSRF + Perms
2024-10-03 16:52:28 -04:00
Johnny
5ea271662b Merge pull request #1083 from itflow-org/tax-report-tidy
Tidy up the tax report + perms
2024-10-03 16:52:18 -04:00
Johnny
3bc9b28712 Merge pull request #1082 from itflow-org/ticket-invoice-tidy
Tidy up the ticket_invoice_add_modal
2024-10-03 16:52:04 -04:00
Johnny
c77246c7f8 Merge pull request #1081 from itflow-org/more-permss
Move account/asset post logic to new permissions system
2024-10-03 16:51:55 -04:00
wrongecho
f8c6a5ef19 Budget - CSRF + Perms 2024-10-03 20:52:37 +01:00
wrongecho
90fb28e32b Tidy up the tax report + perms 2024-10-03 20:42:56 +01:00
wrongecho
5635cd9b8c Tidy up the tax report 2024-10-03 20:41:28 +01:00
wrongecho
e433c819a8 Tidy up the tax report 2024-10-03 20:41:12 +01:00
wrongecho
4d7d9baba8 Tidy up the ticket_invoice_add_modal 2024-10-03 20:25:41 +01:00
wrongecho
18889d228a Move account/asset post logic to new permissions system 2024-10-03 19:42:48 +01:00
Johnny
6d6689e7c5 Merge pull request #1080 from itflow-org/cert-dont-blank
Certificate cron bugfix
2024-10-02 12:34:57 -04:00
Johnny
11230d655f Merge pull request #1079 from itflow-org/custom-actions
Add custom event handler
2024-10-02 12:34:45 -04:00
Johnny
10fab109eb Merge pull request #1078 from itflow-org/cert-perms-model
Certificates - perms and model
2024-10-02 12:30:01 -04:00
wrongecho
63579d5a8f Certificate cron bugfix
Don't try to update certificates if expiry is empty (connection error)
2024-10-02 12:00:56 +01:00
wrongecho
fa6aa4318b tidy 2024-10-02 11:42:30 +01:00
wrongecho
d7b5e0e591 tidy 2024-10-02 11:35:14 +01:00
wrongecho
4a625183fb Certificates - perms and model
Move certificates to the new permissions system
Deduplicate add/edit using a model
2024-10-02 11:26:58 +01:00
wrongecho
1c404b9cf1 Add custom event handler to be triggered by some actions affecting tickets/quotes/invoices/contacts 2024-10-02 11:26:13 +01:00
wrongecho
4e9afd3e6b Certificates - perms and model
Move certificates to the new permissions system
Deduplicate add/edit using a model
2024-10-02 08:32:42 +01:00
johnnyq
c352f6e3cb Do not show Send Invoice or Add Payment if Invoice Amount is 0 2024-10-02 01:04:59 -04:00
johnnyq
6a55abaf50 Fix Error 500 when adding or editing network 2024-10-01 22:50:30 -04:00
Johnny
1f846f4164 Merge pull request #1076 from cybershieldms/ticket-features
cron_ticket_email_parser.php - send new ticket opened email to unknown clients
2024-10-01 14:49:56 -04:00
johnnyq
7ccfad80de Add Client name to the paid notification when client pays via stripe 2024-10-01 12:09:42 -04:00
Craig Hodges
d506790135 Merge branch 'itflow-org:master' into ticket-features 2024-09-30 19:08:30 -05:00
Craig Hodges
da3a6d636e Changed regex to only exclude from postmaster or daemon. 2024-09-30 19:07:01 -05:00
Johnny
b318872ba8 Merge pull request #1077 from itflow-org/projects
Projects fixups
2024-09-30 17:53:28 -04:00
wrongecho
e0b088b76b Projects
- Add archive and unarchive ability
- Improve logic around Open > Close > Archive > Delete
- Change to new perms system
- Tidy and formatting
- TODO: CSRF
2024-09-30 21:31:04 +01:00
wrongecho
10a223b5b8 Projects
- Add archive and unarchive ability
- Improve logic around Open > Close > Archive > Delete
- Change to new perms system
- TODO: CSRF
2024-09-30 21:27:42 +01:00
wrongecho
81844cea2e Update credential.Php - model fix path 2024-09-30 18:47:22 +01:00
Craig Hodges
bd5621ce1e Sends new ticket notifications to unknown (client id = 0) including logic to not process e-mail bounce messages. Fixed ticket description missing from new ticket notifications to others ().Added e-mail From: display name () to beginning of ticket description. 2024-09-29 23:46:45 -05:00
Johnny
7945d8b998 Merge pull request #1075 from itflow-org/tck-eml-urls
Add guest ticket URL to emails
2024-09-29 21:14:48 -04:00
wrongecho
478d81b0f9 Add guest ticket URL to emails 2024-09-29 22:00:15 +01:00
wrongecho
a414f279b1 Fix admin nav modules 2024-09-29 21:35:33 +01:00
Johnny
13d9d01e22 Merge pull request #1074 from itflow-org/more-perms
Refactor POST handling
2024-09-29 14:39:30 -04:00
Marcus Hill
0c0cf2f427 Refactor POST handling.
- Split into admin and user handlers, each admin page gets its own file now
- Enforce role access once for admin POST requests
- Automatically load POST logic for admin-based requests based on the referring page, otherwise automatically load all user request logic
- Add support for using custom POST handlers
2024-09-29 19:08:59 +01:00
Marcus Hill
6363d265ca Refactor POST handling.
- Split into admin and user handlers, each admin page gets its own file now
- Enforce role access once for admin POST requests
- Automatically load POST logic for admin-based requests based on the referring page, otherwise automatically load all user request logic
- Add support for using custom POST handlers
2024-09-29 19:02:28 +01:00
Johnny
e911bde66c Merge pull request #1073 from itflow-org/stripe-note
Add note re payment providers
2024-09-29 10:48:06 -04:00
Marcus Hill
99a6562d1e Add note re payment providers 2024-09-29 12:18:41 +01:00
Johnny
635b1f903a Merge pull request #1072 from itflow-org/post-perms-maint
More enforcing user permissions
2024-09-29 00:30:25 -04:00
wrongecho
928d723a77 More enforcing user permissions 2024-09-28 20:07:54 +01:00
wrongecho
654b590033 More enforcing user permissions 2024-09-28 20:04:33 +01:00
Johnny
e94aae7940 Merge pull request #1071 from ThaMunsta/download-filename-fix
Update expenses.php
2024-09-26 16:54:43 -04:00
johnnyq
cbcb793b64 Remove temp Debugging snippet for calculating recurring expenses 2024-09-26 16:52:17 -04:00
johnnyq
aca45d39aa Fix Monthly Recurring Expenses always showing 0 in Dashboard 2024-09-26 16:50:32 -04:00
ThaMunsta
e3df5c02bf Update expenses.php
Downloaded filename was hardcoded and assumed only ever PDF would be uploaded and downloads any jpg/png as a PDF filename. Fix takes into account the database filename and extension and updated iconography for more general file indication.
2024-09-25 22:57:31 -04:00
johnnyq
0cd7e7a9f5 Fix Notification Number 2024-09-25 20:25:34 -04:00
johnnyq
7d0c9b738f Fix Icons 2024-09-25 19:26:28 -04:00
johnnyq
f245d1a7b4 Revert notification Icon and badge color 2024-09-25 19:22:02 -04:00
johnnyq
2290e7ba32 UI Top Nav: Reposition Notification badge count and change color to warning 2024-09-25 17:07:17 -04:00
johnnyq
4f0e74520c Removed Destructive delete option in assets, Added Delete to assets if archived 2024-09-24 16:17:02 -04:00
johnnyq
c5e9d02edf UI Update Client Vendors: Give Description its own column, add account number if exists below Vendor Name and fix copy website button submitting instead of copying the site 2024-09-24 13:34:22 -04:00
Johnny
8e9654927a Merge pull request #1070 from itflow-org/email-parse-eml
Email parser - bugfix saving the original message
2024-09-22 01:33:00 -04:00
wrongecho
eb831b5ca1 Email parser - bugfix saving the original message 2024-09-21 16:59:38 +01:00
johnnyq
3c6b9ea206 Added Archive Button for Vendors 2024-09-21 11:47:54 -04:00
Johnny
d33e5cd08d Merge pull request #1069 from itflow-org/client-http-header-loginfail
Show a 401 header for unsuccessful portal logins
2024-09-21 11:27:16 -04:00
Johnny
c5575e749e Merge pull request #1068 from itflow-org/http-header-blocked
Show a 429 header when logins are blocked
2024-09-21 11:27:08 -04:00
Johnny
f1ce116fb5 Merge pull request #1067 from itflow-org/encoding
Detect and convert non-UTF8 encoding as part of input sanitization
2024-09-21 11:27:00 -04:00
wrongecho
0e4f57eaed Show a 401 header for unsuccessful portal logins 2024-09-21 13:45:47 +01:00
wrongecho
19dc33a836 Show a 429 header when logins are blocked 2024-09-21 13:08:30 +01:00
wrongecho
b509090530 Detect and convert non-UTF8 encoding as part of input sanitization 2024-09-21 11:07:53 +01:00
johnnyq
c5e13fdba6 Fix Dead Link 2024-09-20 21:45:23 -04:00
Johnny
eff4c9c725 Merge pull request #1066 from itflow-org/updates-db-first
Show DB updates before git updates
2024-09-20 20:02:38 -04:00
johnnyq
04f0905397 Added sort order visual cues to every listing 2024-09-20 20:00:21 -04:00
wrongecho
9d0f553422 Update CODE_OF_CONDUCT.md
rm discord
2024-09-20 23:32:05 +01:00
wrongecho
2e74e1756c Show DB updates before git updates 2024-09-20 21:51:51 +01:00
johnnyq
f9897e811c Added Sort order visual cue to invoices 2024-09-20 16:45:45 -04:00
wrongecho
3c413ae0be Merge pull request #1065 from itflow-org/revert-admin-check
Temp revert new admin check to allow DB updates
2024-09-20 21:42:03 +01:00
wrongecho
b6e4d6dd34 Temp revert new admin check to allow DB updates 2024-09-20 21:40:05 +01:00
Johnny
26e4dc5fb3 Merge pull request #1064 from itflow-org/roles-enforce-2
Permissions - clients and tickets
2024-09-20 16:16:59 -04:00
johnnyq
b658cf09dc Opps settings_localization_array.php should have not have amin_ prepended reverting 2024-09-20 16:15:05 -04:00
johnnyq
3fff623674 Add visual sort order cues to quotes 2024-09-20 16:13:38 -04:00
wrongecho
23f776efa3 Permissions - clients and tickets
Enforce new permissions model in clients and tickets
2024-09-20 21:10:24 +01:00
johnnyq
2d13dab61e Add Visual sort cues to Recurring Tickets, and projects 2024-09-20 16:02:59 -04:00
johnnyq
91e4dd5dba Add Recurring Invoices, Tickets, Expenses instead of just Recurring back to the side navs, makes for easier navigation 2024-09-20 15:45:37 -04:00
johnnyq
42ffa9b4ab Move /post/settings.php into /post/admin.php 2024-09-20 15:23:50 -04:00
johnnyq
3c4275e2c6 Preappend admin_ to the settings files for consistency 2024-09-20 15:14:28 -04:00
Johnny
9c92831f70 Merge pull request #1062 from ThaMunsta/rep-tk-client-fix-round2
Update report_ticket_by_client.php
2024-09-20 15:00:38 -04:00
Johnny
dd1994e881 Merge pull request #1061 from itflow-org/rec-delete
Recurring invoices - hide delete when active
2024-09-20 15:00:12 -04:00
Johnny
49341782a9 Merge pull request #1059 from itflow-org/func-acc-tidy
Tidy unused accounting functions
2024-09-20 14:57:19 -04:00
ThaMunsta
c02386f439 Update report_ticket_by_client.php
Sorry I thought I had this sorted out the first time but the monthly report section was still wrong.
2024-09-20 14:51:18 -04:00
johnnyq
847870a45a Fixed undefined sort var by using php isset function in the filter header, added sort order icons to tickets 2024-09-20 14:35:26 -04:00
wrongecho
ce3264db04 Recurring invoices - hide delete when active
Adjust recurring invoices so they have to be made inactive to delete them
2024-09-20 19:33:32 +01:00
wrongecho
eeac235c1d Tidy unused accounting functions 2024-09-20 19:24:28 +01:00
Johnny
e714b80af2 Merge pull request #1058 from ThaMunsta/settings-online-payment-fix
Update settings_online_payment.php
2024-09-20 14:11:43 -04:00
ThaMunsta
65b4f97e37 Update settings_online_payment.php
Removed account type as I understand that isn't used anymore.
2024-09-20 14:07:25 -04:00
johnnyq
8498f01f6c Rename pagination_head.php to filter_header.php as this is a more suitable name for its function 2024-09-20 13:58:30 -04:00
Johnny
c9f3d17f12 Merge pull request #1057 from itflow-org/roles-enforce-1
Custom Roles & Permissions
2024-09-20 13:29:31 -04:00
wrongecho
3d1e333ff0 Custom Roles & Permissions
Initial enforcement of custom roles & permissions - only on some pages via GET for now.
2024-09-20 18:17:59 +01:00
wrongecho
3c9995cb01 Custom Roles & Permissions
Initial enforcement of custom roles & permissions - only on some pages via GET for now.
2024-09-20 18:09:00 +01:00
johnnyq
55c832bde6 Feature: Inititial functionality for sort order icons on table headers 2024-09-20 13:01:41 -04:00
wrongecho
10fafacefe Custom Roles & Permissions
Initial enforcement of custom roles & permissions - only on some pages via GET for now.
2024-09-20 17:59:49 +01:00
Johnny
5a20c7fdbe Merge pull request #1056 from itflow-org/client-import
Client import - resiliency
2024-09-20 11:43:42 -04:00
Johnny
5eb9f3f5ee Merge pull request #1055 from itflow-org/tag-delete-fix
Fix deleting tags
2024-09-20 11:42:54 -04:00
wrongecho
0886a6c41d Client import - resiliency
- Add some resiliency to the client import function to better account for blank fields (may also fix some import errors)
- Fix the default settings page not loading due to the removal of account types
2024-09-20 11:38:15 +01:00
wrongecho
677d80d770 Fix deleting tags 2024-09-20 10:44:22 +01:00
Johnny
1390ca07f9 Merge pull request #1054 from ThaMunsta/report-fix
Update mysql query for report_ticket_by_client.php
2024-09-20 00:26:05 -04:00
ThaMunsta
2898084851 Update mysql query for report_ticket_by_client.php
Fix empty report
2024-09-19 23:51:17 -04:00
johnnyq
547f9282d3 Fix Dead link to domains in dashboard 2024-09-19 14:21:06 -04:00
johnnyq
8c4b021168 Added UI elements for the new custom link fields, new tab, order and location 2024-09-18 21:25:59 -04:00
johnnyq
0a1ab84140 DB Structure Update for additonal feature of custom links include nav location, order and open in new tab option 2024-09-18 18:22:37 -04:00
johnnyq
4dd24531cb Fix Main, user account, reports and admin side nav bars to prevent text overflow when collapsed now only show back button when collapsed 2024-09-18 17:52:19 -04:00
johnnyq
5f46536a85 Update Secure Message with the intended recipient, also added a confidential disclosure method to the email and Secure message link, added number of views left and expire date, and other minor ui updates 2024-09-18 17:22:39 -04:00
johnnyq
415f536cd7 DB Structure Update: Remove Account Types, Add Account Description Field, Change is admin from INT to TINYINT for performance 2024-09-18 16:30:55 -04:00
Johnny
62a2ed7430 Merge pull request #1052 from itflow-org/perms-2
Permissions overhaul - Define permissions in the database
2024-09-18 14:20:05 -04:00
johnnyq
eaee42f1f5 Add the ability to edit ticket reply types to puiblic or internal, note there is no client email option here 2024-09-17 14:55:02 -04:00
johnnyq
7b2566b654 Remove all reminense of Account Types next is deleting the DB Tables for account types 2024-09-17 13:59:58 -04:00
johnnyq
10ecb8b7c9 Phase 2 Removal of Account Types: Removed files 2024-09-17 13:32:37 -04:00
johnnyq
4286588446 Initial Removal of Account Types: Removed from Admin side nav 2024-09-17 13:29:31 -04:00
johnnyq
a2766bd67f Allow Techs to remove units from a rack 2024-09-17 13:24:08 -04:00
johnnyq
273483151f Add Expiration Date Column to Software Licenses 2024-09-17 13:18:46 -04:00
johnnyq
7e9b924927 Allow Columns to be sorted in Recurring Tickets 2024-09-17 12:45:47 -04:00
johnnyq
b251b7a15f Remove 120 Day Notifications for Domain, Cert, Warranty 2024-09-16 18:16:13 -04:00
wrongecho
0d0483b0a4 Update README.md
Move 'Built With' to docs
2024-09-15 00:18:12 +01:00
wrongecho
147df7f292 Update SECURITY.md
Add badge
2024-09-15 00:10:42 +01:00
wrongecho
970efa7731 Merge pull request #1053 from itflow-org/tidy
Tidying
2024-09-14 23:58:09 +01:00
wrongecho
4a6d312ea0 Tidying 2024-09-14 23:50:05 +01:00
wrongecho
5dc9f47799 Tidying 2024-09-14 23:47:19 +01:00
wrongecho
c65db3431d Tidying 2024-09-14 23:43:54 +01:00
wrongecho
ee9a2789e9 Permissions overhaul - Define permissions in the database
2nd attempt at this one!
Similar to #1008 but separately defining the roles, modules and associated permissions in the database.
Also has admin being a defined role automatically having full access.

Parent issue: #530
2024-09-14 19:14:35 +01:00
wrongecho
c7340ca0d4 Permissions overhaul - Define permissions in the database
2nd attempt at this one!
Similar to #1008 but separately defining the roles, modules and associated permissions in the database.
Also has admin being a defined role automatically having full access.

Parent issue: #530
2024-09-14 18:55:00 +01:00
wrongecho
271019b16b Permissions overhaul - Define permissions in the database
2nd attempt at this one!
Similar to #1008 but separately defining the roles, modules and associated permissions in the database.
Also has admin being a defined role automatically having full access.

Parent issue: #530
2024-09-14 18:29:44 +01:00
johnnyq
6975d6ef44 Fixed Broken Link to all assets on the dashboard, added link for all domains, updated all domains report to highlight domains, expired and expiring 2024-09-13 14:35:46 -04:00
johnnyq
07df444561 Added Bulk Delete Expenses Option 2024-09-13 13:52:47 -04:00
johnnyq
6bb56f7c51 UI Improvement to Domains, Certificates and Licenses listing: Updated Expire to show TimeAgo as well and to highlight table rows red if expiring within 14 Days, yellow for 90 days and gray if expired also updated side badges to refelect the badge color as well 2024-09-13 13:31:18 -04:00
johnnyq
208e56e784 Added Additonal Export Options to Expenses Including Account, Vendor and Category, removed CSV Warning on Export Model 2024-09-13 12:32:16 -04:00
johnnyq
e0ca3f15a8 Added Ubuntu, Fedora and DuckDuckGo to user agents 2024-09-12 12:42:15 -04:00
johnnyq
168a298a55 Dont Show windows version as this is inaccurate, show just Windows for OS, fix Opera String, and removed iPod 2024-09-12 12:28:24 -04:00
Johnny
86f1beb687 Merge pull request #1051 from itflow-org/allow-clear-avatar
Allow users to clear their avatar
2024-09-12 12:16:12 -04:00
Johnny
412eed7554 Merge pull request #1050 from itflow-org/ticket-reply-layout
Adjust ticket reply layout
2024-09-12 12:16:02 -04:00
johnnyq
f2a3299ef0 Update getOS Function to include Windows 11, Fix get Web Browser when using Microsoft Edge 2024-09-12 12:13:51 -04:00
wrongecho
80884bab47 Allow users to clear their avatar 2024-09-12 15:34:51 +01:00
wrongecho
77b7250703 Adjust ticket reply layout 2024-09-12 15:04:52 +01:00
Johnny
5ef8bd5720 Merge pull request #1049 from itflow-org/api
API Tidy
2024-09-11 18:05:55 -04:00
Johnny
7324c21c1f Merge pull request #1047 from itflow-org/share-modal-anyone
Guest Link Sharing
2024-09-11 18:05:45 -04:00
Johnny
f0456705ca Merge pull request #1046 from itflow-org/network-show-id
Show network ID when editing items
2024-09-11 18:05:32 -04:00
wrongecho
f3e9c9c867 API Tidy
- Remove old client ID queries, these are now built into the API keys. If a key has access to all clients, a client ID can be provided in the query.
- Small fixes to assets URI lookup
- Add read endpoint for vendors
2024-09-11 18:06:45 +01:00
wrongecho
0ad0c2c955 Guest Link Sharing
- Allow links to be emailed to non-contacts by typing their email
- Don't show archived contacts on the dropdown
- Removed unused email send check (handled via queue now)
2024-09-11 17:12:30 +01:00
wrongecho
8df3896f69 Show network ID when editing items
Shows the database object ID when editing networks on the Notes tab, to allow for use in the API.
2024-09-11 11:17:54 +01:00
Johnny
2e202df3ff Merge pull request #1045 from itflow-org/show-db-ids
Show object ID when editing items
2024-09-10 21:30:46 -04:00
Johnny
e8c27e9234 Merge pull request #1043 from itflow-org/email-send-tidy
Email Send - Tidy
2024-09-10 21:25:07 -04:00
Johnny
c863b8b033 Merge pull request #1042 from itflow-org/rm-stripe-client-pays
Stripe - Client pays removal
2024-09-10 21:22:33 -04:00
Johnny
9a53f65cdf Merge pull request #1041 from itflow-org/next-num
Ticket next number should not be lower than the last ticket number
2024-09-10 21:18:55 -04:00
Johnny
deb9ae0065 Merge pull request #1040 from itflow-org/tickets-export
Add resolved date to ticket export csv
2024-09-10 21:18:40 -04:00
wrongecho
586f0f1c57 Show object ID when editing items
Shows the database object ID when editing on the Notes tab, to allow for use in the API.
Needs further work as we move things to dynamic modals for editing.
2024-09-10 23:04:12 +01:00
wrongecho
517e8d42f0 Email Send - Tidy
- Enhance error logging in cron_mail_queue.php
- Prevent invalid sender addresses
- Prevent potential SQL injections in the sender name (admin settings and should be sanitized before being sent to queue anyway)
2024-09-10 22:34:20 +01:00
wrongecho
549868e3bf Stripe - Client pays removal
- Complete removal of client paying Stripe fees feature
- Add PHP error logging to the Stripe payment process
2024-09-10 20:26:16 +01:00
wrongecho
9e4f9cbd74 Ticket next number should not be lower than the last ticket number to prevent collisions 2024-09-10 19:20:06 +01:00
wrongecho
ce1fc04468 Add resolved date to ticket export csv 2024-09-10 19:14:47 +01:00
wrongecho
24cc593162 Add resolved date to ticket export csv 2024-09-10 19:13:13 +01:00
johnnyq
760f07e665 Removed old comment 2024-09-09 18:06:59 -04:00
johnnyq
05b50519b1 Remove the hidden form name for bulk merge and just leave the id 2024-09-09 17:55:08 -04:00
johnnyq
27dbbbb660 Fixed Bulk Merge issues by renaming ticket_id name var in bulk merge modal 2024-09-09 17:49:53 -04:00
Johnny
765850b22f Merge pull request #1038 from itflow-org/csrf
Enforce CSRF for post/asset and post/account
2024-09-09 13:14:28 -04:00
wrongecho
a10ff7963a Update README.md
Add supporters to readme
2024-09-09 10:41:18 +01:00
wrongecho
64684e1248 Enforce CSRF for post/asset and post/account
Tiny bit of tidying
2024-09-08 22:52:38 +01:00
Johnny
d1410ef967 Merge pull request #1037 from itflow-org/tech-loc-perms
Allow techs to manage locations
2024-09-07 12:05:11 -04:00
Johnny
6cbc4c584e Merge pull request #1035 from itflow-org/document-portal-visibility
Add ability to choose whether document is visible in client portal
2024-09-07 11:35:06 -04:00
wrongecho
6b850553cc Allow techs to manage locations 2024-09-07 12:25:19 +01:00
wrongecho
43d6847126 Fix images in docs not showing in client portal 2024-09-07 11:51:27 +01:00
wrongecho
40c400240f Add ability to choose whether document is visible in client portal 2024-09-07 11:21:36 +01:00
Johnny
c20f9942f1 Merge pull request #1034 from itflow-org/add-db-docs-client-visible
Docs - DB Structure to hide from client portal
2024-09-06 22:08:48 -04:00
johnnyq
903bd47f5a Allow Bulk Adding tickets to a Project from the Main Tickets Listing Page 2024-09-06 18:44:53 -04:00
johnnyq
09f2072d27 Add Client Field to Project Tickets, combine Ticket Number and Subject to 1 column 2024-09-06 18:18:41 -04:00
johnnyq
fdd8faf46a Included the Project Prefix and Number in Project Details 2024-09-06 18:08:55 -04:00
johnnyq
99c6321fbb Do not require Client for Projects, allow to add multiple tickets at once when adding tickets to a project 2024-09-06 17:53:35 -04:00
wrongecho
7edf03f79f Add DB Structure that will allow hiding specific docs from the client portal 2024-09-06 22:12:20 +01:00
johnnyq
b605f62175 In client overview Expiring / Expired / Retiring / Retired Asset links now point to the asset details page when clicked 2024-09-06 16:05:33 -04:00
johnnyq
cf535372f5 Show most recent activity first in client overview 2024-09-06 15:55:55 -04:00
johnnyq
4f0c7c5bf7 Added within context to the upcoming expire select box 2024-09-06 15:41:35 -04:00
johnnyq
9dfc7d35cc In the client overview allow the widget Expiring in Days to be Selectable with 7 30 and 90 Day Options 2024-09-06 15:39:00 -04:00
johnnyq
96c59422ea Added Cerificates Expiring/Expired and created a seperate card for expired items under client overview 2024-09-06 15:15:10 -04:00
johnnyq
25bc1d9055 Update Client Overview to Show Recents ASC not DESC so most recent shows first and do not show already Expired Items, will reseve that for a new card 2024-09-06 14:54:46 -04:00
Johnny
68458e49f2 Merge pull request #1033 from itflow-org/en-whitelabel-pt1
Add ITFlow attribution to client portal (1/2)
2024-09-06 14:19:48 -04:00
johnnyq
65f72665ad Update All Assets Report to be more like client assets 2024-09-06 14:18:00 -04:00
wrongecho
208d6cadc4 Add ITFlow attribution to client portal (1/2) 2024-09-06 18:53:48 +01:00
johnnyq
1130c17196 Added purchase date, warranty expire to show addiitonal columns in client assets 2024-09-06 13:26:17 -04:00
johnnyq
41276b55f0 Feature: Custom Links on main side nav 2024-09-05 17:08:43 -04:00
johnnyq
6879300fe8 DB Structure Update for Custom Links 2024-09-05 16:23:35 -04:00
Johnny
d890a27731 Merge pull request #1031 from itflow-org/portal-certs-domains
Portal - allow clients to see certs/domains
2024-09-05 14:24:06 -04:00
Johnny
0185452cf5 Merge pull request #1030 from itflow-org/portal-contact-add
Portal - allow adding contacts
2024-09-05 14:23:52 -04:00
Johnny
323224bc85 Merge pull request #1028 from itflow-org/whitelabel
Initial implementation of whitelabelling (disabled)
2024-09-05 14:23:43 -04:00
Johnny
fa7c99fcc5 Merge pull request #1027 from ssteeltm/fix-paging-hidden
fix pagination hidden
2024-09-05 14:19:26 -04:00
wrongecho
f2c15b4650 Portal - allow clients to see certs/domains 2024-09-05 17:56:42 +01:00
wrongecho
54c8d6d74a Portal - allow adding contacts 2024-09-05 17:26:28 +01:00
wrongecho
91fb4b663a Merge pull request #1029 from itflow-org/portal-updates
Portal - allow editing client contacts
2024-09-05 15:48:46 +01:00
wrongecho
726aaac56a Portal - allow editing client contacts, few tweaks to header incl session notifications 2024-09-05 15:44:06 +01:00
wrongecho
92681a86b3 Portal - allow editing client contacts, few tweaks to header incl session notifications 2024-09-05 15:21:05 +01:00
wrongecho
766813a326 Portal - allow editing client contacts, few tweaks to header incl session notifications 2024-09-05 15:19:52 +01:00
wrongecho
7827522b40 Portal - allow editing client contacts, few tweaks to header incl session notifications 2024-09-05 15:19:17 +01:00
wrongecho
49fddd4f1e Portal - allow editing client contacts, few tweaks to header incl session notifications 2024-09-05 15:16:11 +01:00
wrongecho
a23005babe Portal - show client contacts 2024-09-05 14:05:51 +01:00
wrongecho
3d16431d32 Initial implementation of whitelabelling 2024-09-05 10:44:50 +01:00
wrongecho
4458c87463 Initial implementation of whitelabelling 2024-09-05 10:31:18 +01:00
johnnyq
34b9e2978a Added Physical Location to the additonal asset columns option 2024-09-04 19:39:06 -04:00
johnnyq
1a359a207f Show Additional Columns in Assets 2024-09-04 19:20:32 -04:00
Hugo Sampaio
bb12b02099 Update pagination.php
makes more sense 5 because its the minimum page to set
2024-09-04 18:03:39 -03:00
Hugo Sampaio
b3e6039ec5 fix pagination hidden
fix pagination hidden, when number of rows is smaller than 10
2024-09-04 17:37:20 -03:00
Johnny
0f6ed69008 Merge pull request #1025 from itflow-org/export-validation
Hide export function when module is empty
2024-09-04 11:43:08 -04:00
Marcus Hill
f433535a8b Hide export function when module is empty 2024-09-04 08:52:08 +01:00
Johnny
5b496ff1ac Merge pull request #1024 from itflow-org/rep-tck-by-client
Enhance tickets by client report
2024-09-03 23:27:40 -04:00
Johnny
cebb6e2dd1 Merge pull request #1023 from itflow-org/ticketing-disable-modals-resolved
Do not load most edit modals if ticket is closed, as the data doesn't need to be changed
2024-09-03 23:27:26 -04:00
Johnny
16b08afa75 Merge pull request #1022 from itflow-org/client-export-log
Log when client pack is exported to PDF
2024-09-03 23:27:12 -04:00
Johnny
397765032c Merge pull request #1021 from itflow-org/hide-export-null
Hide the Export function when there are no records
2024-09-03 23:27:01 -04:00
Johnny
3ecd05b963 Merge pull request #1020 from itflow-org/logging-credentials
Log when users navigate to the credentials page for a client
2024-09-03 23:26:16 -04:00
Johnny
281bdcbaf9 Merge pull request #1019 from itflow-org/hide-debug-logins
Logins - Hide debug
2024-09-03 23:25:52 -04:00
Marcus Hill
91db3e2f37 Enhance tickets by client report
Enhancements ot the tickets by client report
- Breakdown tickets by priority (low/med/high)
- Breakdown stats per month, in addition to the existing per-year breakdown
2024-09-03 21:49:52 +01:00
Marcus Hill
d9668f3086 Do not load most edit modals if ticket is closed. 2024-08-30 23:15:48 +01:00
Marcus Hill
00e4e8a24b Log when client pack is exported to PDF 2024-08-30 23:05:04 +01:00
Marcus Hill
aeeac12f11 Log when client pack is exported to PDF 2024-08-30 23:04:20 +01:00
Marcus Hill
cf322b17bc Hide the Export function when there are no records (locations, tickets, vendors) 2024-08-30 22:57:58 +01:00
Marcus Hill
78eead24f7 Log when users navigate to the credentials page for a client 2024-08-30 22:49:18 +01:00
Marcus Hill
a59a6ce2b1 Check that a credential is shared before attempting to display the details to prevent debug error messages 2024-08-30 22:45:03 +01:00
Johnny
8ddb450f6f Merge pull request #1016 from itflow-org/resolved-ticket-report
Change ticket by client report to report on resolved, not closed tickets
2024-08-29 15:34:31 -04:00
Johnny
b42a4db6ca Merge pull request #1015 from itflow-org/rm-legacy-fetchdomainexpiration
Remove the old function for fetching domain expiration
2024-08-29 15:34:21 -04:00
wrongecho
437067fcc7 Change ticket by client report to report on resolved not closed tickets 2024-08-29 20:16:43 +01:00
wrongecho
75846adc28 Remove the old function for fetching domain expiration 2024-08-29 19:42:53 +01:00
wrongecho
ed446e18b5 Merge pull request #1013 from itflow-org/update-show-branch
Show name of branch you are on in admin update
2024-08-29 19:24:19 +01:00
wrongecho
b7d1503044 Show name of branch you are on in admin update 2024-08-29 19:21:33 +01:00
Johnny
d700289671 Merge pull request #1012 from itflow-org/assets-report-custom-columns
All asset report - custom columns
2024-08-28 18:47:46 -04:00
Johnny
99b5758839 Merge pull request #1011 from itflow-org/ticket-unbilled-perms
Bugfix: Unbilled tickets perms
2024-08-28 18:46:58 -04:00
Johnny
af62ba8b89 Merge pull request #1010 from itflow-org/asset-purchase-ordering
Re-order asset purchase and install date fields to make more sense
2024-08-28 18:46:47 -04:00
Johnny
ddf936c859 Merge pull request #1009 from itflow-org/client-perms-rectickets-projects
Bugfix: Client Access Permissions
2024-08-28 18:45:44 -04:00
wrongecho
64997acaa5 All asset report - custom columns
Created a new version of the all asset report allowing custom columns to be used
2024-08-28 23:25:03 +01:00
wrongecho
7739b31bb5 Bugfix: Remove two role checks on unbilled ticket report that prevents any non-admins viewing it 2024-08-28 22:21:02 +01:00
wrongecho
11005fef58 Re-order asset purchase and install date fields to make more sense 2024-08-28 22:11:04 +01:00
wrongecho
26d6737468 Bugfix: Client Access Permissions
Fix bug that allows users to view recurring tickets and projects they shouldn't have access to
2024-08-28 20:17:41 +01:00
johnnyq
a4a110f1e7 Show Red Badge Count next to client domains if Domain is expired or expires within 5 days 2024-08-27 20:40:12 -04:00
johnnyq
3eb6ee57fb Fix Contact Bulk Actions, removed required fields from Bulk Mail since its all under 1 big form you cant have required fields 2024-08-27 12:05:45 -04:00
johnnyq
27a9697542 Temporary diabled Bulk Ticket Merge in the Main Ticket view as it was not allowing a tech to be assigned from that view 2024-08-25 22:49:54 -04:00
Johnny
d05c5b7ca2 Merge pull request #1007 from itflow-org/api-logins-tweak
Tweak credentials read api
2024-08-25 15:31:01 -04:00
wrongecho
ec0e1c395c Tweak credentials read api 2024-08-25 20:29:14 +01:00
Johnny
c0c810764a Merge pull request #1006 from itflow-org/bulk-merge
Add bulk merge ticket feature
2024-08-25 15:20:43 -04:00
Johnny
442681a49a Merge pull request #1005 from itflow-org/debug-db-info
Debug - clarify database engine
2024-08-25 15:20:24 -04:00
Johnny
6e3dcc0237 Merge pull request #1004 from itflow-org/bugfix-ticket-client-access-perms
Tickets - Client access permissions bugfix
2024-08-25 15:20:10 -04:00
Johnny
21a31a1fe1 Merge pull request #1002 from itflow-org/api-logins
Allow decrypting logins/credentials via the API
2024-08-25 15:18:34 -04:00
wrongecho
f964d8245b Add bulk merge ticket feature 2024-08-25 19:10:06 +01:00
wrongecho
c69655a5bb Add bulk merge ticket feature 2024-08-25 19:06:57 +01:00
wrongecho
4cfa4c6e85 Debug - clarify database engine 2024-08-25 17:53:34 +01:00
wrongecho
573e2340df Fix a bug that allows technicians to view tickets they shouldn't have access to 2024-08-25 15:32:40 +01:00
wrongecho
24ff6f5c84 WIP: Allow decrypting logins/credentials via the API 2024-08-25 12:45:18 +01:00
wrongecho
9ef3099495 WIP: Allow decrypting logins/credentials via the API 2024-08-25 12:32:21 +01:00
wrongecho
d37bdcdbcb WIP: Allow decrypting logins/credentials via the API 2024-08-25 12:31:15 +01:00
johnnyq
2202f31a61 fix 2024-08-24 20:08:14 -04:00
johnnyq
26e12e1edb More UI/UX updates to the ticket reply bar 2024-08-24 20:07:06 -04:00
johnnyq
1bf80d3b15 Use TimeAgo for Ticket Created At column, use tooltip to show real date and time 2024-08-24 19:28:07 -04:00
johnnyq
f0086c8844 More Ticket Details UI/UX use btn-toolbar class instead of btn-group for the header action button this allows padding and rounding of both edges of the button, decreased the bottom padding of the ticket reply card, updated the billable status 2024-08-24 18:55:54 -04:00
johnnyq
9a3b42c623 More UI/UX Reduced the Padding in the Ticket Details Header to make more room, Use TimeAgo and tooltips for the exact times, updated the Ticket Subject display, made the Submit button green instead of primary to offset all the primary buttons, also updated other button to reduce the distraction of orimary and secondary buttons 2024-08-24 18:34:05 -04:00
johnnyq
0ea2e78c78 More UI/UX Work to ticket details 2024-08-24 18:11:57 -04:00
johnnyq
9afab6e5e5 Removed the Dark Outline border on the side cards in ticket details 2024-08-24 17:59:41 -04:00
johnnyq
ed315c3979 UI/UX Updates to the Ticket Details Header 2024-08-24 17:57:05 -04:00
johnnyq
7168cffba7 Ticket Details UI/UX Removed Prepend icon to tasks and removed the fa-fw for the checkmark next to add task 2024-08-24 16:40:01 -04:00
johnnyq
08b94dcae4 Bump TinyMCE from 7.1.1 to 7.3.0 2024-08-24 16:36:29 -04:00
johnnyq
918c202e83 Remove Dup AI Reword Button 2024-08-24 16:29:01 -04:00
johnnyq
d9299e8e28 Fix AI Reword Button, removed Status Icon 2024-08-24 16:24:14 -04:00
johnnyq
bdd7c7e993 UI/UX Updates to Ticket Details, Reduce the start, pause timer and reset button and use pause and play icons instead, use block buttons for Type of Response 2024-08-24 16:14:40 -04:00
johnnyq
a152a4a1a0 Update Ticket Details Page, remove the non working selectable comment type ad wrapped the Ticket Reply in a card body 2024-08-24 15:58:45 -04:00
johnnyq
2e0841abb3 Do not show Outstanding Balance table if no outstanding invoices exist 2024-08-24 15:06:35 -04:00
johnnyq
b14da05b17 Add more prominant Highlight of the current invoice being viewed 2024-08-24 14:57:23 -04:00
johnnyq
dd017da140 Several UX/UI Updates to Guest Invoice, Added Account Balance to the Top Right, removed Invoice History as this should be viewed via the client portal. Update the wording for Previous unpaid invoices to Outstanding Invoices, added invoice counts, reduced margin and padding in invoice tables, reworded Pay Online to Pay Now 2024-08-24 14:47:27 -04:00
johnnyq
8f5854c76e Add Full Account Balance on Guest Invoice View 2024-08-24 14:11:16 -04:00
johnnyq
04f33ac375 Add Tooltips with expire time for shared links 2024-08-24 13:36:55 -04:00
johnnyq
5588ad953e Show if a Credential, Document or File is Shared by a Link, added a new status column 2024-08-24 13:30:01 -04:00
johnnyq
374ca2a89b Fix New client Link in Dashboard 2024-08-23 18:31:54 -04:00
johnnyq
d9b8b12c17 Reworked tooltips 2024-08-23 18:27:20 -04:00
johnnyq
9225efdc9e Added Tooltips to Deactivate Action and Type under shared Links 2024-08-23 18:17:41 -04:00
johnnyq
a10b9bf93a Removed Company Name prepended to invoice email subjects as this name should be in the From Email Name Example CompanyName Billing or Just CompanyName 2024-08-23 17:49:23 -04:00
johnnyq
436b10c577 Updated the Shared items box UI/UX on Client overview 2024-08-23 17:29:03 -04:00
johnnyq
b583e7f8c9 Update Text from light to dark for warning badges on client nav 2024-08-23 16:40:47 -04:00
johnnyq
e1cac4556a Rounded out the top navbar notification count badge 2024-08-23 16:33:35 -04:00
johnnyq
6d7ffdd133 Updated Admin and Account Icons in the user drop down menu 2024-08-23 16:11:47 -04:00
johnnyq
0556f0b9a4 Moved Admin Section from side nav to User Drop Down at the top 2024-08-23 16:09:34 -04:00
johnnyq
37ddf87ef0 Removed Client ID from the Side Nav as its hidden in a popover on the client name in the client header 2024-08-23 16:01:31 -04:00
johnnyq
5ef9d76a3c Removed Shared Items from the side menu and merged them inot client overview 2024-08-23 15:59:03 -04:00
johnnyq
d35b9ee161 Removed Client Audit log, now located under Recent under client Overview can click View More to see the main audit log if your an admin also added client filter to the main audit log 2024-08-23 15:43:50 -04:00
johnnyq
58ec9121a0 Moved Bulk Email from the side Menu to a contact Bulk Action, Also removed Client Statement as it did not work and payments covers that already this frees up 2 menu spaces on the client side nav 2024-08-23 15:21:15 -04:00
wrongecho
a6113dc371 WIP: Allow decrypting logins/credentials via the API 2024-08-22 18:22:20 +01:00
wrongecho
0c60ecc329 WIP: Allow decrypting logins/credentials via the API 2024-08-22 17:46:58 +01:00
wrongecho
d0ade72e6e Merge pull request #1003 from itflow-org/bulk-resolve-bugfix
Bugfix: Bulk close should actually be bulk resolve
2024-08-19 21:58:11 +01:00
wrongecho
d43cd0398e Bugfix: Bulk close should actually be bulk resolve 2024-08-19 21:45:03 +01:00
johnnyq
d803895f08 Remove the HTML line breaks in error output as the console is text only 2024-08-19 16:33:19 -04:00
johnnyq
85f2e8c244 Fix Cron Mail Ticket Parser script: It will now check if the ITFlow folder is created and subscribed before moving the mail 2024-08-19 16:24:45 -04:00
wrongecho
63feff03d2 Initial WIP: Allow decrypting logins/credentials via the API 2024-08-19 21:23:43 +01:00
Johnny
82a123a63d Merge pull request #1001 from itflow-org/cred-fix
Bugfix: credentials
2024-08-19 15:16:39 -04:00
Johnny
0e8e8416f5 Merge pull request #1000 from itflow-org/bugfix-resolved-tickets
Bugfix: Resolved ticket counts
2024-08-19 15:15:55 -04:00
wrongecho
3f772f5a2f Bugfix: credentials
Fix an edge-case bug causing the user_encryption_session_key session cookie to not be set due to error output (when display PHP errors in browser is enabled). This means login credentials are still encrypted but cannot be decrypted properly by other users.
Prevent users creating new credentials if they do not have the correct cookie set.
2024-08-19 19:56:12 +01:00
wrongecho
d17b75b7bd Bugfix: Resolved ticket counts
Prevent resolved tickets showing up in unassigned ticket / my ticket counts
2024-08-19 18:57:20 +01:00
Johnny
86e3f377ab Merge pull request #999 from itflow-org/rec-ticket-accounting-bugfix
Recurring tickets bugfix
2024-08-18 12:56:05 -04:00
Johnny
e60ca0f978 Merge pull request #998 from itflow-org/ticketing-update
Ticketing updates - guest view & resolved vs closed
2024-08-18 12:31:13 -04:00
wrongecho
f605f581cb Recurring tickets bugfix
Fix bug preventing ticket subject/content being shown when accounting module is disabled.
Think this is due to the dynamic modals - fix for now is just to hide the billable div from the user.
2024-08-18 16:11:32 +01:00
wrongecho
0025503ff8 Ticketing updates - guest view & resolved vs closed
- Swap autclose for resolved to allow temporarily re-opening resolved tickets for 72 hrs after closure
- Add guest view URL for tickets
2024-08-17 23:42:39 +01:00
wrongecho
ad9b69ae10 Remove extra php closing tag 2024-08-17 23:34:23 +01:00
wrongecho
d80334a7cf Ticketing updates - guest view & resolved vs closed
- Swap autclose for resolved to allow temporarily re-opening resolved tickets for 72 hrs after closure
- Add guest view URL for tickets
2024-08-17 23:24:15 +01:00
wrongecho
0b801b24ac Merge pull request #997 from itflow-org/wrongecho-db-update-small-fix
Correct database update logic to ensure future updates work properly
2024-08-16 13:06:20 +01:00
wrongecho
05e2b51ada Correct database update logic to ensure future updates work properly 2024-08-16 13:05:04 +01:00
Johnny
d9316233bb Merge pull request #993 from itflow-org/portal-docs-show-current
Only show most current version of a document in the client portal
2024-08-15 20:14:57 -04:00
Johnny
08f9f137c0 Merge pull request #996 from itflow-org/tickets-tasks
Tickets & Tasks
2024-08-15 20:14:34 -04:00
wrongecho
ccdfd96f56 Tickets & Tasks
- Add ability to un-complete/undo a completed task
- Require CSRF verification when deleting tickets and tasks
2024-08-15 23:52:25 +01:00
wrongecho
786fc0a369 Only show most current version of a document in the client portal 2024-08-15 21:45:20 +01:00
Johnny
26d36e6f66 Merge pull request #992 from itflow-org/tck-eml-parse-anonymous
Add unknown/anonymous email to ticket parsing
2024-08-13 17:00:31 -04:00
Johnny
f32fd01e47 Merge pull request #991 from itflow-org/asset-client-tfr
Add move/transfer assets between clients
2024-08-13 16:58:51 -04:00
wrongecho
90e95a76b7 Add anonymous email parsing
Add option to allow unknown/anonymous email parsing for unknown contacts/domains.
This will be disabled by default due to the potential for spam, but can be turned on in the settings if required.
2024-08-10 22:39:47 +01:00
wrongecho
d6f30b83f8 Add anonymous email parsing
Add option to allow unknown/anonymous email parsing for unknown contacts/domains.
This will be disabled by default due to the potential for spam, but can be turned on in the settings if required.
2024-08-10 22:35:52 +01:00
wrongecho
8fb50275ac Add move/transfer assets
Add ability to move / transfer assets between clients. Moving an asset involves the asset being archived and then re-created under the new client with most of the same information.

Information about the old & new asset is stored in the audit logs and within the asset notes. Information from the audit logs is accessible via a new History tab on the asset, subject to audit log retention.
2024-08-10 20:51:57 +01:00
wrongecho
3d3492ef27 Add move/transfer assets
Add ability to move / transfer assets between clients. Moving an asset involves the asset being archived and then re-created under the new client with most of the same information.

Information about the old & new asset is stored in the audit logs and within the asset notes. Information from the audit logs is accessible via a new History tab on the asset, subject to audit log retention.
2024-08-10 20:46:59 +01:00
wrongecho
b732e08aff Merge pull request #990 from itflow-org/wrongecho-patch-2-assets
Update ajax.php - Assets > Asset logging
2024-08-10 12:23:46 +01:00
wrongecho
9c0dfd8b48 Update php-lint.yml - bump to 9.4.1 2024-08-10 12:21:43 +01:00
wrongecho
693156c902 Update ajax.php - Assets > Asset logging
Adjust logging for asset changes so they are logged as type 'asset' not 'assets', to match existing logging
2024-08-10 12:17:31 +01:00
wrongecho
4185c2830d Merge pull request #989 from itflow-org/wrongecho-patch-1
Update client_rack_edit_modal.php
2024-08-08 05:36:23 +01:00
wrongecho
9e19943cf7 Update client_rack_edit_modal.php
Adjust rack units max on edit modal too
2024-08-08 05:35:22 +01:00
Johnny
a3ebf0845f Merge pull request #988 from itflow-org/file-delete-bugfix
Client files bugfix
2024-07-31 17:25:31 -04:00
Johnny
2e61c7e72b Merge pull request #987 from itflow-org/rem-header-js
Remove old reference to js/header_timers.js
2024-07-31 17:25:12 -04:00
Johnny
6c50722b14 Merge pull request #986 from itflow-org/wrongecho-rack-patch
Adjust max rack size to 70U
2024-07-31 17:25:02 -04:00
Marcus Hill
cfb13a0c18 Client files bugfix
- Hide delete button for techs as they do not have this permission
- Remove unused exclude_condition var
2024-07-31 22:06:17 +01:00
Marcus Hill
de5ae4bbc3 Remove old reference to js/header_timers.js as this file no longer exists 2024-07-31 21:46:15 +01:00
wrongecho
2b83fe5796 Update client_rack_add_modal.php
Adjust max rack size to 70U
2024-07-30 16:07:37 +01:00
Johnny
cc0de316ab Merge pull request #984 from ssteeltm/credentials-filter-asset_location
filter locations on credentials
2024-07-23 22:06:18 -04:00
Johnny
708dea24ef Merge pull request #985 from ssteeltm/master
fix Order by IP on assets listing
2024-07-23 22:05:46 -04:00
Hugo Sampaio
6d45e93ad9 fix Order by IP
fixes the ordering by ip, after the new change of Interfaces
2024-07-22 13:05:23 -03:00
Hugo Sampaio
79fdc979cf Update client_logins.php
Filter for Locations, based on Asset Location, if its related.
2024-07-22 09:50:41 -03:00
Johnny
f769081bf9 Merge pull request #982 from ssteeltm/client-id-tooltip
client-id-tooltip
2024-07-16 19:54:14 -04:00
Hugo Sampaio
83da33432c Update client_side_nav.php 2024-07-12 10:53:11 -03:00
Hugo Sampaio
de49c8dba1 client-id-tooltip 2024-07-12 10:42:24 -03:00
johnnyq
dcc0d77dd4 Added Client ID in the client listing and client top header 2024-07-09 15:26:07 -04:00
johnnyq
50bdeae79d Fix Invalid Var in Add License 2024-07-09 14:30:23 -04:00
johnnyq
53550e5092 Updated Client Export Fields, and added Client Import along with download client sample file 2024-07-05 15:31:01 -04:00
Johnny
cf7a900e1a Merge pull request #981 from git-kup/master
Update invoice.php
2024-07-02 23:08:50 -04:00
git-kup
eead1328ef Update invoice.php
fixed typo payed to paid
2024-07-02 17:37:34 -04:00
Johnny
afaaa5895c Merge pull request #980 from ssteeltm/uri-dropdown
uri dropdown
2024-07-02 12:50:23 -04:00
Hugo Sampaio
4e5fd048f7 uri dropdown 2024-07-02 10:34:56 -03:00
Johnny
2fa07e4e46 Merge pull request #976 from itflow-org/log-cleanup
Add audit log cleanup/retention period to cron
2024-07-01 21:54:27 -04:00
Johnny
5818a57b9f Merge pull request #977 from itflow-org/debugging-help
Debug assistance (admin_debug.php)
2024-07-01 21:53:51 -04:00
wrongecho
b6f1e0203c Merge pull request #979 from ssteeltm/Asset-URI-link-duplicate
Update client_asset_details.php
2024-07-01 18:22:47 +01:00
Hugo Sampaio
8881cd30ff Update client_asset_details.php 2024-07-01 12:01:35 -03:00
Marcus Hill
af6740d898 Debug assistance
Clarify Apache/PHP error log location in debug/setup
Include app version, cron and timezone in debug page
2024-06-30 12:31:59 +01:00
Marcus Hill
8db9822f63 Add audit log cleanup/retention period to cron
Audit logs will be automatically cleaned up after 90 days (new installs) or 7 years (existing installs). This is configurable in Settings > Security.
2024-06-30 11:51:39 +01:00
johnnyq
cc38c642c5 Added back the old cron ticket email parser as legacy_cront_ticket_email_parser.php and added back the old libraries php-mime-mail-parser in plugins note if you recently installed itflow within the last 2 weeks you will need to install and enable the php libraries php-imap and php-mailparse if you decide to use the legacy mailer 2024-06-29 13:40:47 -04:00
johnnyq
f133981b52 Remove the UTF7 to 8 Encoding as it broke Thunderbird email parsing, somehow Roundcube webmail was fine 2024-06-28 17:21:43 -04:00
johnnyq
6bdfe1b713 Add Function to convert message text from UTF7 to UTF8 possibly fix the Google Issue not sure, we need further testing 2024-06-28 13:52:50 -04:00
johnnyq
fc82dc705e Add Payment Method and Reference to Payment Receipts 2024-06-28 12:20:20 -04:00
johnnyq
c27f9fd6a9 Set Charset to UTF-8 to avoid encoding issues on some mail servers 2024-06-28 11:39:34 -04:00
johnnyq
97c2928830 Remove Duplicate Line of Code to connect to IMAP Server and find inbox 2024-06-28 11:25:58 -04:00
johnnyq
f57cf5cb91 Fix Plain Text Emails not showing in ticket replies by converting plain text emails to HTML for displaying 2024-06-27 18:50:37 -04:00
johnnyq
95fd0344c0 Fixed ticket Email processing showing array() 2024-06-27 17:23:45 -04:00
johnnyq
1c618892cc Removed WebKlex PHP-IMAP Dependency in post as it was spewing errors for people running older version of php below 8.2 - note this is still required for Mail Parser to work 2024-06-27 01:10:00 -04:00
johnnyq
5b3c6f4272 Better Handling of HTML Reply ticket emails, reduce the spacing trim out extra spaces reduce the line height etc 2024-06-26 13:14:16 -04:00
johnnyq
30bd685dea Final path fix 2024-06-25 16:02:22 -04:00
johnnyq
f7b75bb150 fix 2024-06-25 15:54:19 -04:00
johnnyq
6456dfcc67 Fix Autoloader location for WEbklex imap 2024-06-25 15:51:51 -04:00
johnnyq
b0c5d43867 Remove the reliance on php-imap extension to test imap connection in setting. Also removed the check for php-imap in the mai, parser as we use fully rely on webklex 2024-06-25 15:48:56 -04:00
johnnyq
40866e34e2 Remove the function to check if php-mailparse is installed. Its not needed and was causing breaing issues and is an unessesary check 2024-06-25 15:28:01 -04:00
johnnyq
39ff97e9dd Restore option to share a password accidentally got wiped out when adding archive unarchive functions 2024-06-25 11:44:19 -04:00
johnnyq
fbd220c5e3 Add Global Bulk Mail back to the Admin nav side bar, seemed to have gotten lost when we updated the menu 2024-06-25 09:37:49 -04:00
Johnny
897dcb179a Merge pull request #975 from ssteeltm/tickets_tasks-progress-bar
small adjustment to show 0 completed tasks
2024-06-24 10:59:14 -04:00
Hugo Sampaio
1542a89922 small adjustment to show 0 completed tasks 2024-06-24 09:54:44 -03:00
johnnyq
0c10b863b5 Use rounded badge for priority in client tickets to match 2024-06-23 00:16:41 -04:00
johnnyq
ee5e6d157d Update Cron Ticket Email Parser script to take in account of multiple variations of the word inbox 2024-06-22 13:45:39 -04:00
Johnny
1b937a0e7d Merge pull request #974 from ssteeltm/master
Update client_file_link_asset_modal.php
2024-06-18 22:30:59 -04:00
johnnyq
ea77c7567d Updated UI badge element to use yes and no for billable tickets 2024-06-17 17:38:05 -04:00
johnnyq
46ab6a696d Assure a Primary network interface gets added with the import of assets. Also check to see if a primary interface is present when editing an interface 2024-06-17 14:43:35 -04:00
johnnyq
84366cc1b9 Small UI Comment Cleanup of dashboard 2024-06-16 12:31:45 -04:00
johnnyq
55eff7ce45 Client Racks UI Cleanup Move the Rack Data to a table instead of using dd and dl 2024-06-16 12:17:05 -04:00
johnnyq
3d6d6a0e22 UI Cleanup Move the the from and to Unit to one row when adding a device 2024-06-16 12:08:59 -04:00
johnnyq
9d40ef1776 Racks: Exclude Assets in the the add device drop downlist that are already in anopther rack 2024-06-14 18:07:43 -04:00
johnnyq
aca5a1ee54 Remove Rack Photo on deletion and do not remove rack_units as the DB is set to cacade delete these 2024-06-14 17:44:29 -04:00
johnnyq
5ba0315a42 Feature: You can add and remove linked devices and customer devices to the rack units 2024-06-14 17:22:16 -04:00
Hugo Sampaio
88896d3cdf Update client_file_link_asset_modal.php
small adjustment to allow link an asset in any files. Before this it was limiting to link only one file, dont displaying it in assets listing for other files
2024-06-14 15:13:18 -03:00
johnnyq
92e594ee32 Updated Budget UI to include card header and made a view only option for budget 2024-06-14 13:41:16 -04:00
johnnyq
70dc64f05d Updated Budget to now include easy updating and creating and viewing Yearly budgets in one POST 2024-06-14 13:13:28 -04:00
johnnyq
5352416dbe Added backend archive, unarchive, delete capaiblities for racks 2024-06-13 17:12:34 -04:00
johnnyq
17feb98ec7 Added Client Network / Server Rack Documentation to the UI More to come 2024-06-13 17:06:09 -04:00
johnnyq
1efe403422 Added Asset Photo to Asset Details Side bar 2024-06-13 14:51:09 -04:00
johnnyq
6da19c3e6f Fix Physical Locatiin not showing on edit Asset 2024-06-13 14:47:48 -04:00
johnnyq
e3c39e473f Fixes on Image Uploading for assets 2024-06-13 14:31:46 -04:00
johnnyq
16c2fbf6d1 Added Asset Photo and Asset Physical Location to the UI 2024-06-13 13:54:21 -04:00
johnnyq
3288cb6dc2 DB Structure Update to make room for Rack and Patch Panel Documentation along with adding Asset Photo and Asset Physical Location DB Fields 2024-06-13 12:40:37 -04:00
johnnyq
b37cfdf677 Fix API Asset interface relationship 2024-06-12 18:06:04 -04:00
johnnyq
2edd39c16d Remove the vendor directory in .gitignore as these dependencies are needed for php-imap 2024-06-12 16:15:10 -04:00
johnnyq
779527cf6a Migrated away from PHP Mail Parser to the new WebKlex PHP IMAP Mail Parser this will open the way to support OAUTH2 for Mail servers such as Microsoft 365 and Google Workspaces 2024-06-12 15:39:52 -04:00
johnnyq
d64a7ce31e Fix Client Services to include interfaces 2024-06-11 23:32:09 -04:00
johnnyq
836e1a3199 Updated Asset API to include its assets 2024-06-11 23:00:57 -04:00
johnnyq
b25d21b8bf Delete Asset Interfaces related to client assets when deleting a client 2024-06-11 22:39:03 -04:00
johnnyq
3eb81e5954 Fix Network Select under client assets 2024-06-11 21:51:54 -04:00
johnnyq
1e241a9232 Quick Fix 2024-06-11 21:46:45 -04:00
johnnyq
41ac390173 MAJOR Feature Update - Backup before updating Migrated Asset Network info to a seperate table to allow for multiple interfaces per asset 2024-06-11 21:36:03 -04:00
johnnyq
a1613ddceb Up Max Client Abbreviation length from 5 to 6 2024-06-11 13:45:19 -04:00
johnnyq
0a7fd1471a Move All Domains from main side nav to Reports under Overview header 2024-06-11 12:09:00 -04:00
johnnyq
32df0369e2 Added IPv6 Field to Contact Details 2024-06-10 23:57:03 -04:00
johnnyq
fc6ec8dd03 Added IPv6 field for Assets 2024-06-10 22:10:18 -04:00
johnnyq
2ce36cb14f Added Bulk Edit Category, Archive, Unarchive and Delete to Products 2024-06-10 17:26:43 -04:00
johnnyq
655f1230c2 Added Export Products CSV 2024-06-10 15:53:26 -04:00
Johnny
ff1ec30775 Merge pull request #973 from wrongecho/ticket-parse-save-original-mail
Email to ticket parsing - Save the original email
2024-06-10 11:28:33 -04:00
Johnny
7135747b7d Merge pull request #972 from wrongecho/2fa-6char
2FA tweaks
2024-06-10 11:28:11 -04:00
Marcus Hill
041cbe15fa Email to ticket parsing - Save the original email
When creating a new ticket, save the original email in a .eml format and attach it to the ticket.

This will be useful for situations when you want to reply to the original thread but don't have access to the inbox. We could add this to all received emails if there is interest?
2024-06-09 21:34:54 +01:00
Marcus Hill
3dcd04a724 2FA
- Set the 2FA number input field to only accept 6 characters max
- Revoke existing remember-me tokens when 2FA is re-enabled
2024-06-09 12:57:42 +01:00
johnnyq
51710f886c Added Category Drop Down Select and Archive Query to Products 2024-06-08 21:00:14 -04:00
johnnyq
674f4cd6db Fix Padding for Client Documents 2024-06-08 19:31:24 -04:00
johnnyq
fb16ecd0c6 Added Bulk Archive, unarchive support to domains 2024-06-08 19:17:06 -04:00
johnnyq
64c5cbda52 Added Bulk Archive, UnArchive and Delete support to client vendors 2024-06-08 18:49:18 -04:00
johnnyq
e8715979d5 Optimized Show/Unshow Archive Button Logic 2024-06-08 17:14:08 -04:00
johnnyq
2032fe43d4 Added Bulk Delete to Archived Contacts 2024-06-08 16:20:28 -04:00
johnnyq
ee30b0b197 Added Bulk Archive, Unarchive, Delete actions to to logins 2024-06-08 16:00:29 -04:00
johnnyq
0d8333c7ab Add Bulk Actions to Locations 2024-06-08 14:49:26 -04:00
johnnyq
eb7fe5708a Fix Bulk actions in client recurring tickets 2024-06-08 13:38:08 -04:00
Johnny
0af4a7ac1e Merge pull request #971 from wrongecho/ticket-report-fix
Bugfix: Ticket report - average time to close
2024-06-08 12:46:58 -04:00
Marcus Hill
c06c240e2a Bugfix: Ticket report - average time to close 2024-06-08 07:32:41 +01:00
johnnyq
551146d3e2 btn-lg 2024-06-07 20:46:36 -04:00
johnnyq
a17fbcfc1d Fix Update 2024-06-07 20:45:33 -04:00
johnnyq
02445811fa Added locaiton drop down filter to contacts 2024-06-07 20:40:35 -04:00
johnnyq
86cd618b03 Add Force Update Button 2024-06-07 20:36:18 -04:00
johnnyq
f1b28a6f14 Fix Archive var check for contacts and assets 2024-06-07 18:52:54 -04:00
johnnyq
a44a76db28 Added the option to bulk remove contact tags 2024-06-07 18:44:21 -04:00
johnnyq
e920ccc5e4 Force upper case on client abbreviations 2024-06-07 18:31:53 -04:00
johnnyq
24022eca55 Added Definable Client Abbreviation 2024-06-07 18:18:42 -04:00
johnnyq
b229349d8c Added / ID to Username field under credentials 2024-06-07 18:01:25 -04:00
johnnyq
fb4c1e828f Fix Some Undefined Vars PHP Errors 2024-06-07 17:57:02 -04:00
johnnyq
c2b7d03c22 Added Payment Method and Account Dropdown Filters to Payments 2024-06-07 16:48:57 -04:00
johnnyq
1070449450 Added User, log type, and log action Dropdown Filter to audit logs 2024-06-07 16:32:45 -04:00
johnnyq
a742c9596e Moved Exports into the the new drop downs to match consistency 2024-06-07 15:59:22 -04:00
johnnyq
01b3d53683 Feature: Ability to Bulk Assign Additional tags to Many Contacts 2024-06-06 20:19:58 -04:00
johnnyq
474e9525c4 Add Bulk Archive and Unarchive to contacts 2024-06-06 17:54:12 -04:00
johnnyq
a35a28cf7d Added Bulk Archive and Unarchive to Assets 2024-06-06 17:25:25 -04:00
johnnyq
1522f5414a Ability to Unarchive contacts and assets 2024-06-06 16:51:08 -04:00
johnnyq
94ba05271f Allow Invoices to be exportable, move export expense modal out of the record loop 2024-06-06 13:49:50 -04:00
johnnyq
10f1d39b2a Fix In Comntat Details Contact must belong to the client 2024-06-06 13:18:50 -04:00
johnnyq
71bad025cc Fix Ticket Subject under client contact details showing 0 2024-06-06 13:01:51 -04:00
johnnyq
5e6b79fce5 Added DataTables JS Plugin tested functionality for client contact details 2024-06-06 13:00:14 -04:00
johnnyq
965c16c19d Fix broken Clients when restricting user client access 2024-06-06 12:06:26 -04:00
johnnyq
40ccbb5627 Update GetDomainExpiry Function to return proper null if Expire is not found, updated the logic 2024-06-06 02:30:12 -04:00
Johnny
dfda4d1101 Merge pull request #969 from ssteeltm/asset-view-files
show related Files on Asset View
2024-06-04 21:23:00 -04:00
Johnny
61a95dbd59 Merge pull request #968 from ssteeltm/file-link-assets
link file to assets
2024-06-04 18:30:47 -04:00
johnnyq
d20e462652 Mimicked UI for Client Perms to USer and Device Licneses under Licenses 2024-06-04 16:36:39 -04:00
johnnyq
21019ba471 Add Checkbox that will select all / de-select all Client Restriction permissions in add/edit user 2024-06-04 16:05:49 -04:00
Hugo Sampaio
49436fae3b rename description
hability to also rename description
2024-06-04 16:40:33 -03:00
johnnyq
0aea143049 Update wording for Restrict Client Access 2024-06-04 15:18:44 -04:00
johnnyq
e5cab12633 Updated UI for Restrict Client Access 2024-06-04 15:11:13 -04:00
Hugo Sampaio
87069b7ebb forgoten modal identifier 2024-06-04 15:55:57 -03:00
johnnyq
254715ddc6 Rework User client Access Restriction UI for add and edit user. Moved from multi Select Box to Individual checkboxs 2024-06-04 14:52:20 -04:00
Hugo Sampaio
3b07caadb7 show related Files on Asset View
initial work on showing related files when in asset view
2024-06-04 15:45:57 -03:00
Hugo Sampaio
3023c48771 link file to assets
provides hability to add link on Files to Assets, so later we can show this related files on Asset View
2024-06-04 15:03:53 -03:00
johnnyq
8bc7c849ef Feature: Added the ability to edit the order of the tasks this is not the best solution but works we recommend setting them in orders of 5 or 10 so there is wiggle room to add tasks in between 2024-06-03 19:36:16 -04:00
johnnyq
1076ffb5f7 Feature Ability to Edit Task names under Ticket Templates 2024-06-03 19:15:59 -04:00
johnnyq
9f73b13dcf Dont show Template or Client Vendors under Vendor Select in Expenses Filter 2024-06-03 18:12:57 -04:00
johnnyq
5b594813c4 Feature: Add Advanced Filter Vendor and Category under Expenses 2024-06-03 16:28:45 -04:00
johnnyq
20795c2816 Feature: Add Advanced Filter for Account From and Account To under transfers 2024-06-03 16:13:01 -04:00
johnnyq
acfd5e8d54 Was missing a few more regexes in get domain expiry 2024-06-02 17:05:53 -04:00
johnnyq
738c83378c Forgot to add a pattern for expires on 2024-06-02 16:41:20 -04:00
johnnyq
56b0eafe2b re-push out new domain expiry lookup 2024-06-02 16:32:42 -04:00
johnnyq
e2b700cdcd Revert new Domain lookup 2024-06-02 13:15:41 -04:00
johnnyq
13764da199 Updated domain lookup function to include TLDs of and time formats to match the python script 2024-06-02 13:07:33 -04:00
johnnyq
84653cb57a Created new PHP function to use the local whois binary to get the expire date of a domain 2024-06-02 12:38:47 -04:00
johnnyq
b47f543534 Ticket Events now shows everything logged in the ticket by auditing logs 2024-06-01 20:04:37 -04:00
johnnyq
6107e0436f Added Eye ball Icon to System Calendar to toggle system calendars 2024-06-01 18:55:24 -04:00
johnnyq
c573687fa1 Feature: Calendar Names and Colors can now be edited 2024-06-01 18:48:06 -04:00
johnnyq
851542bcc1 Added Side nav for calendars, pending more updates 2024-06-01 18:09:59 -04:00
johnnyq
e04a9d1f09 Added All Domain view to main side nav 2024-06-01 17:12:15 -04:00
johnnyq
c0207aa9ec Remove the Arrow Icon Next to the client in client listing 2024-06-01 16:54:44 -04:00
johnnyq
1fa043b1d7 Bumped TinyMCE Editor from 7.0 to 7.1.1 2024-06-01 16:21:46 -04:00
johnnyq
307cc709d4 Fix Merging Ticket where the merging ticket HTML would be lost during the merge to the another ticket 2024-06-01 16:15:38 -04:00
johnnyq
18d94cb33d Add Revision history to the bottom of each document 2024-06-01 15:54:53 -04:00
johnnyq
5edec23234 Convert document details to 4 Space indent instead of 2 2024-06-01 15:32:14 -04:00
johnnyq
a064d26c10 Fix Creating Document from a template where is would not set the document_parent causing new documents to display revisions that dont exist 2024-06-01 15:24:30 -04:00
johnnyq
3621912398 Keep Admin Menu Nav Highlighted when going deeper into an item 2024-06-01 15:07:47 -04:00
johnnyq
64499fa734 Also Delete Location Tags when a Client is deleted 2024-06-01 14:39:14 -04:00
johnnyq
ba23142843 Remove repeated delete client tags query when client is deleted 2024-06-01 14:35:35 -04:00
johnnyq
dfe61fb426 Delete Contact Tags when a Client is deleted 2024-06-01 14:34:28 -04:00
johnnyq
2ab7a44f6e Feature: Add Contact Tags Support 2024-06-01 14:25:51 -04:00
johnnyq
565f8162a4 Feature: Clients and Locations can now be searchable with multiple tags selected 2024-05-31 18:18:41 -04:00
johnnyq
8d87672b49 Tidy Tickets Collapse 2024-05-31 17:39:09 -04:00
johnnyq
0770c701b5 Continue to Show Advanced Search in Tickets Filter if assigned to is selected 2024-05-31 17:36:19 -04:00
johnnyq
ecbeb12990 Fix broken page over the shortened tag query in client details and ticket details.php 2024-05-31 16:51:52 -04:00
johnnyq
a7376fe08d DB Update Shorten Client Tag Fields and add Delete Client Tags to Delete Client and cleanup clients query 2024-05-31 16:46:50 -04:00
johnnyq
5347429d58 Remove Unessesary Syntax from locaiton tag Query 2024-05-31 16:27:04 -04:00
johnnyq
89d9ec73ad Feature Added Location Tags 2024-05-31 16:13:55 -04:00
johnnyq
63f740e22f Move total time worked to 3rd column in ticket details 2024-05-30 19:42:08 -04:00
johnnyq
eab3bf226c Add Company Name to the Browser title in guest viewing sessions such as guest_invoice, guest_quote etc 2024-05-30 19:29:33 -04:00
johnnyq
7db9a7de73 Fix Telemetry check 2024-05-30 18:57:33 -04:00
johnnyq
14c814c5b8 Made Public Comment and Email Default Selected option 2024-05-30 16:45:20 -04:00
johnnyq
2149a33bd5 Added Email Client to ticket details, Public Comment does not email the client or watchers anything, but can view it in the ticker portal 2024-05-30 16:36:38 -04:00
johnnyq
237ba1dd20 Removed Custom CSS for ticket was able to make work with CSS Library bootstrap, asjusted spacing and layout of ticket response controls, 2024-05-30 15:35:02 -04:00
johnnyq
8c007ea7b1 Calculate more ticket response counts 2024-05-30 15:05:13 -04:00
johnnyq
f091d94282 Ticket Response UI Update Public Comment and Internal Note work now, added Events and Tasks to the Responses stil WIP there 2024-05-30 14:53:49 -04:00
johnnyq
db5ec8912a More UI Updates to ticket comments 2024-05-30 13:56:30 -04:00
johnnyq
7eb6c2ac7f Initial rework on UI for public comments, private notes and ticket events 2024-05-30 13:49:52 -04:00
johnnyq
dfca3a04a1 DB Structure Dumnp for billable options 2024-05-29 17:56:59 -04:00
johnnyq
1d19b72229 Added Billable Recurring Tickets, UI: changed the Billable option to switch. Added ticket settings option to automatically mark new tickets as billable 2024-05-29 17:55:39 -04:00
johnnyq
c389c68883 Default Tickets to not billable and add Billable option to Create Ticket 2024-05-27 13:46:17 -04:00
Johnny
1c5cb0123c Merge pull request #965 from wrongecho/ticket-categories
Ticket categories
2024-05-27 12:58:50 -04:00
Johnny
a3f72b7d93 Merge pull request #966 from wrongecho/calendar-start-day
Calendar start day
2024-05-27 12:58:14 -04:00
Marcus Hill
fbc87572e9 Calendar start day
Allow customising the calendar to start on a Monday instead of Sunday
2024-05-26 23:38:50 +01:00
Marcus Hill
159c1d78a0 Ticket categories
Add basic support for categorising tickets (e.g. Software/Network)
2024-05-26 22:49:57 +01:00
johnnyq
5210fae3ec Fix 2024-05-26 15:55:46 -04:00
Johnny
f177045432 Merge pull request #964 from wrongecho/user-roles-initial
User roles - Initial
2024-05-26 15:42:24 -04:00
Marcus Hill
e820ffec6b User roles
Move the default user roles into the database to make way for custom roles & permissions
2024-05-26 18:37:37 +01:00
wrongecho
c4fd3f7422 Merge pull request #962 from wrongecho/bugfix-ticker-timer-since-removal-open-tickets
Bugfix - Ticket time tracking
2024-05-26 17:09:24 +01:00
Marcus Hill
c969897389 Ticket time tracking
Bugfix for ticket time tracking as this was broken since the open ticket timer was removed
2024-05-26 17:09:04 +01:00
Marcus Hill
059a5516fc Ticket time tracking
Bugfix for ticket time tracking as this was broken since the open ticket timer was removed
2024-05-26 17:05:42 +01:00
wrongecho
f1037975a7 Merge pull request #961 from wrongecho/qr-code-fix
2FA QR Codes
2024-05-26 16:36:36 +01:00
Marcus Hill
2b006af52d 2FA QR Codes
Move away from the Google Charts API for generating QR codes as this is currently broken and not a security best practice.
2024-05-26 16:29:35 +01:00
Marcus Hill
8b1ba7028e 2FA QR Codes
Move away from the Google Charts API for generating QR codes as this is currently broken and not a security best practice.
2024-05-26 16:08:06 +01:00
johnnyq
c02d6d4cf0 Add Recurring Tickets NextDate to the Calendars 2024-05-21 13:33:53 -04:00
Johnny
85a1c5e795 Merge pull request #960 from wrongecho/2fa-token-cookie-time
Set 2FA Remember-me cookie expiry
2024-05-20 23:49:13 -04:00
Marcus Hill
cabc7e8c8b Set 2FA Remember-me cookie expiry to number of days the token should be valid for
Currently, the token is only valid for 2 days (86400 seconds = 24 hrs, multiplied by 2). This PR adjusts the cookie expiry date to the number of days configured that tokens are cleared after. This should help ensure users are not prompted for 2FA every few days, even if they've set a longer interval.
2024-05-17 23:26:22 +01:00
Johnny
579482c780 Merge pull request #958 from ssteeltm/client_logins-uri-ellipsis
client_logins uri limit with ellipsis
2024-05-17 16:26:49 -04:00
Hugo Sampaio
a96b3a30bd Update client_logins.php 2024-05-17 16:14:46 -03:00
Hugo Sampaio
4782892c8a using truncate function 2024-05-17 15:55:13 -03:00
Johnny
b78b62081c Merge pull request #959 from ssteeltm/tickets_tasks-progress-bar
Tickets tasks progress bar
2024-05-17 14:31:55 -04:00
Hugo Sampaio
aef2cde9d2 Update client_logins.php 2024-05-16 11:14:20 -03:00
Hugo Sampaio
d1aab02721 tasks table header 2024-05-16 11:04:25 -03:00
Hugo Sampaio
d4da95a6f1 show bar on html 2024-05-16 11:01:34 -03:00
Hugo Sampaio
edf9371ffa show tasks progress bar on tickets view 2024-05-16 11:00:04 -03:00
Hugo Sampaio
067d674c16 client_logins uri limit with ellipsis
limits long uri that may break lines in table
2024-05-16 10:48:41 -03:00
johnnyq
abc936d753 Update the AI prompt to style with html formatting 2024-05-15 10:47:27 -04:00
johnnyq
5b38a562bb Update the AI prompt to reword 2024-05-15 10:44:04 -04:00
johnnyq
cddd9b4977 Removed the AI Prompt as it did not always work correctly 2024-05-15 10:40:15 -04:00
Johnny
b2d529e783 Merge pull request #956 from ssteeltm/notification-updates
Display notification when update is available
2024-05-14 21:23:13 -04:00
Johnny
b8a4f0f10f Merge pull request #957 from ssteeltm/docs-files-search-recursive
search in all folders when in root (docs/files)
2024-05-14 21:20:59 -04:00
Hugo Sampaio
1242bd31c9 wrong folder id names 2024-05-13 17:28:53 -03:00
Hugo Sampaio
9e758b1edd only when search 2024-05-13 17:26:23 -03:00
Hugo Sampaio
cdf4767590 search in all folders when in root
Enable search recursive/all folders when in / (root).

In the future will be nice to have this as an advanced search.

reference:
https://forum.itflow.org/d/850-search-documents-recursive
2024-05-13 12:19:11 -03:00
Hugo Sampaio
352fbd852e typos 2024-05-13 11:22:57 -03:00
Hugo Sampaio
13a45c81a0 Display notification when update is available 2024-05-13 11:12:52 -03:00
johnnyq
bd12319422 Limit User access to restricted clients under global search 2024-05-12 13:54:34 -04:00
johnnyq
ff4628465c Quote Copy, Make Client a required field 2024-05-10 21:57:22 -04:00
johnnyq
d202c7684a Feature: Allow copying a quote from one client to another 2024-05-10 21:56:13 -04:00
johnnyq
3e7f57f64a Add contact primary to the API edit ^Cd create 2024-05-10 14:27:04 -04:00
johnnyq
9876c33d2e Client Access: Allow to select Client Access Restrictions for existing users 2024-05-10 14:01:20 -04:00
johnnyq
85bf412f53 Client Access: Allow to select Client Access Restrictions for new users 2024-05-10 13:42:42 -04:00
johnnyq
fa064962a9 Update logic denyed access to log it and redirect back with a toast indicating no access to client 2024-05-10 13:16:42 -04:00
johnnyq
e16dce190f Added logic to the inc_all_client.php file to deny access to users with client access permissions set 2024-05-10 13:05:32 -04:00
johnnyq
5f7ca75d1f Use try instead so script doesnt break if user_permissions table doesnt exist 2024-05-10 12:32:46 -04:00
johnnyq
2832f0eb33 Fix if Tables doesnt exist dont break script 2024-05-10 12:28:31 -04:00
johnnyq
ce0c394d3f Feature: User Client Access Permissions logic has been added, next up is the defining access via user managment 2024-05-10 12:25:38 -04:00
johnnyq
a41eede52f DB update for the upcoming user client restricted access permissions 2024-05-10 11:34:25 -04:00
Johnny
3b8f36e8f3 Merge pull request #954 from ssteeltm/phone-mask-option
Phone mask option
2024-05-10 11:06:24 -04:00
Johnny
2f3263cc64 Merge pull request #955 from ssteeltm/master
num active clients on menu
2024-05-10 11:03:19 -04:00
Hugo Sampaio
4779e8f923 add file ext .unf
https://forum.itflow.org/d/835-allow-file-type

added .unf for unifi backup file
2024-05-06 13:42:11 -03:00
Hugo Sampaio
ec94071167 num active clients on menu
show number of active clients um side menu
2024-05-06 13:25:30 -03:00
Hugo Sampaio
b1efb76b3b Update functions.php
handle phone_mask option
2024-05-06 11:31:38 -03:00
Hugo Sampaio
e677292875 update db
update db to store phone mask option
2024-05-06 10:44:52 -03:00
Hugo Sampaio
6c4235bdeb phone mask config
prepare phone mask config
2024-05-06 10:27:47 -03:00
Johnny
de7d68b659 Merge pull request #953 from wrongecho/hide-open-tickets-timer
Hide the running open ticket tracker as this feature is being removed
2024-05-05 14:30:21 -04:00
Johnny
c471228e6a Merge pull request #952 from wrongecho/report-tickets-time
Add total time worked to 'Tickets by client' report
2024-05-05 14:30:11 -04:00
Johnny
4069dc9cdc Merge pull request #951 from wrongecho/debug-assistance
Debugging help
2024-05-05 14:30:00 -04:00
Johnny
0f6a781638 Merge pull request #950 from wrongecho/cert-checks-custom-ports
Certificate checks - Allow custom ports
2024-05-05 14:29:51 -04:00
Johnny
aca1a13104 Merge pull request #948 from ssteeltm/master
Enable URL Recovery from logout
2024-05-05 14:29:40 -04:00
Hugo Sampaio
76a34dea8f Merge branch 'itflow-org:master' into master 2024-05-04 19:25:50 -03:00
Hugo Sampaio
5280620c6d Update login.php If standard 2024-05-04 19:25:10 -03:00
Hugo Sampaio
17eb51bd54 Update check_login.php If standard 2024-05-04 19:23:39 -03:00
Marcus Hill
df66a9625b Hide the running open ticket tracker as this feature is being removed 2024-05-04 21:36:59 +01:00
Marcus Hill
8d5c71f043 Add total time worked to 'Tickets by client' report 2024-05-04 21:32:03 +01:00
Marcus Hill
cd668241a6 Debugging help
- Mention the PHP error log on the setup & debug pages.
- Restructure the debug page to include the server info before the db structure table
2024-05-04 21:02:33 +01:00
Marcus Hill
43abd177ea Certificate checks - Allow custom ports 2024-05-04 18:04:24 +01:00
Hugo Sampaio
bab66bf769 updated
fixed domain url from config to prevent open redirect issue and encoded uri
2024-05-03 09:34:50 -03:00
wrongecho
c0fc957617 Merge pull request #949 from itflow-org/wrongecho-fileexts
Update file.php - Allow .pages and .numbers files
2024-04-28 20:06:52 +01:00
wrongecho
5f0c363503 Update file.php - Allow .pages and .numbers files 2024-04-28 20:06:08 +01:00
Hugo Sampaio
b8c529c2ec Enable URL Recovery from logout 2024-04-27 09:30:41 -03:00
johnnyq
5f0068a64f Added Advanced Filter by Referral under clients 2024-04-18 21:33:15 -04:00
johnnyq
c1f9ad6ea8 Allow to filter by industry under clients 2024-04-18 21:21:30 -04:00
johnnyq
c5876d2715 Move account selection in advanced Filter 2024-04-18 19:37:06 -04:00
johnnyq
d93caf1eac Cleanup up the side menu of admin / settings to be collapsible headers 2024-04-18 19:05:02 -04:00
johnnyq
7d6b578027 Remove indent for recurrings under client nav 2024-04-18 18:39:13 -04:00
johnnyq
0a5de911e9 Combine Settings and with Admin Side Nav 2024-04-18 18:37:43 -04:00
Johnny
d54780c913 Merge pull request #947 from git-kup/master
Update side_nav.php
2024-04-18 18:29:56 -04:00
git-kup
eb2cc7720e Update side_nav.php
Fix all 3 "Recurring" buttons where not inline with the rest of the buttons in the main side nav. it was slightly indent to the right.
2024-04-18 14:54:43 -04:00
johnnyq
894a4369b3 Fix Timezone always being UTC when sent to the mail queue when scheduling / cancelling tickets 2024-04-17 16:47:10 -04:00
johnnyq
7a2e063bde Fix Broken Reset Password due to incorrect timezone path 2024-04-17 14:05:43 -04:00
johnnyq
888552724a Set Timezone in all places and it needs to be set in and sperated it into a seperate include 2024-04-17 12:53:11 -04:00
johnnyq
7c10bbacd7 Fix not being able to filter tickets by using the search filter 2024-04-16 14:35:08 -04:00
johnnyq
2fd609bb2b Remove Piggy bank icon 2024-04-13 13:59:56 -04:00
johnnyq
7912c99b30 Add Account Selection filter in Expenses 2024-04-13 13:57:14 -04:00
Johnny
59b60e35c2 Merge pull request #945 from wrongecho/addnotice-stripefees-opentickettimer
Add removal notices for Stripe Fees & 'open ticket' time tracker
2024-04-13 13:37:53 -04:00
Johnny
4c02f3dc90 Merge pull request #944 from wrongecho/rec-inv-eml
Per-invoice notifications
2024-04-13 13:37:34 -04:00
Marcus Hill
cfa804b468 Add removal notices for Stripe Fees & 'open ticket' time tracker - these features are to be removed 2024-04-13 17:21:19 +01:00
Marcus Hill
0def06cf40 Add removal notices for Stripe Fees & 'open ticket' time tracker - these features are to be removed 2024-04-13 17:18:49 +01:00
Marcus Hill
a87a79b257 Per-invoice notifications
Hide per-invoice notif setting if invoice notifications are globally disabled
2024-04-13 17:10:10 +01:00
Johnny
a33a91cd95 Merge pull request #943 from wrongecho/ticket-notify-contact-manual-button
Ticket - Notifications
2024-04-13 11:50:04 -04:00
Marcus Hill
1c8b9a3319 Ticket - Notifications
Allow notifying contacts & watchers of a ticket when they are added/updated (#937)
2024-04-13 15:35:06 +01:00
Marcus Hill
2dc8e50ef8 Ticket - Notifications
Allow notifying contacts & watchers of a ticket when they are added/updated (#937)
2024-04-13 15:33:46 +01:00
wrongecho
034c12d6c3 Update README.md
Github readme - Updated bug report and forum roadmap links
2024-04-13 14:06:46 +01:00
johnnyq
c46d35247b Added recurring notification on off to cron 2024-04-12 20:25:05 -04:00
johnnyq
29a83b1e8e Added button to turn Email Notifications off or on on Recurring Invoices 2024-04-12 20:16:54 -04:00
johnnyq
ba66dbf887 Update DB Structure for the addition Email Notify to Recurring Invoices 2024-04-12 19:38:13 -04:00
Johnny
cc9abe5a09 Merge pull request #940 from wrongecho/tck-merge
Tickets - Merging
2024-04-12 19:30:04 -04:00
Johnny
65a3a03801 Merge pull request #939 from wrongecho/rec-invoice-var-name-fix
Client recurring invoice num fix
2024-04-12 19:29:55 -04:00
Marcus Hill
43bd028298 Tickets - Merging
- Fix merging UI not showing ticket status name correctly
- Add ability to move ticket notes and replies to the new parent ticket if desired (sometimes helpful, sometimes not)
2024-04-12 22:26:27 +01:00
Marcus Hill
bdd75f9f95 Client side nav pulls recurring invoice count from num_recurring, not num_recurring_invoices (this is instead used on the main page via inc_all) 2024-04-12 21:39:36 +01:00
wrongecho
453453cf9a Merge pull request #938 from git-kup/patch-1
Update client_overview.php
2024-04-12 21:29:33 +01:00
git-kup
60e067cc9e Update client_overview.php
Remove unpleasant looking elevation of note card in client overview
2024-04-12 15:51:01 -04:00
johnnyq
4ad897d85d Fix Closed Tickets showing up under stale tickets in client Overview 2024-04-12 14:43:53 -04:00
johnnyq
237cc38c60 Remove the recurring link on main tickets as this is on the side nav 2024-04-11 11:18:48 -04:00
johnnyq
f2125dd6d0 Changed the Tickets and Tasks Progress bar colors which have better contrast now 2024-04-10 17:24:34 -04:00
johnnyq
d0ed9fa817 Fix title to only show the session company name no need to nullify_html_entities the title this cause issues with umlaughts if you do 2024-04-10 15:11:09 -04:00
johnnyq
ccab5f9a00 Fix umlauts in settings browser title 2024-04-10 15:05:37 -04:00
johnnyq
b9342c8397 Update Browsers window title to the clients name when in the client section 2024-04-10 14:58:11 -04:00
johnnyq
51e80df71c Moved back Recurring Ticket, Invoices back in client side nav 2024-04-10 14:38:12 -04:00
johnnyq
d8bb6dd4c1 Moved back Recurring Ticket, Invoices and Expense back to the main side nav and added bagdge counters for them. They were just to buried and were used often 2024-04-10 14:06:25 -04:00
johnnyq
610ad04acf Tidy Side Nav 2024-04-10 13:40:38 -04:00
johnnyq
7dff524a19 Client domains: Do not show archived vendors and sort vendor names by name in the select boxes 2024-04-10 13:27:18 -04:00
johnnyq
88a96e3044 Reworked Client Domains, added mail host and dns host, made all the host columns sortable by reworking the logic and optimized the code further 2024-04-10 13:21:45 -04:00
johnnyq
7ca4163552 Ticket Details Update Do not show Invoice Button when Invoiced, do not show billable show Invoiced and the Invoice Number, fixed some padding 2024-04-10 11:27:58 -04:00
johnnyq
f526e908c3 Fix Bug where it doesnt add the tasks from a ticket template, this was due to the removal of task_description 2024-04-08 20:23:23 -04:00
johnnyq
199185a279 Fix Rounding Percents for tasks and tickets 2024-04-08 20:11:40 -04:00
johnnyq
3e14938a53 Add Open Quotes to the Side Nav 2024-04-08 17:35:21 -04:00
johnnyq
a9e5c1ff9c Add Open Invoices, Tickets and Projects Badges to Main Side Nav Bar 2024-04-08 17:22:08 -04:00
johnnyq
e849832f01 Make project number clickable and to view project details 2024-04-08 17:00:50 -04:00
johnnyq
0acd737135 Hide Ticket Close button until all tasks are complete 2024-04-08 16:58:43 -04:00
johnnyq
16fb1467a2 Added Project Prefix and Project Numbering System 2024-04-08 16:48:06 -04:00
johnnyq
f4051fe718 Updated Ticket details to include Tasks Completion Status and Collaborators 2024-04-08 15:58:59 -04:00
johnnyq
ae5f81d9b5 List all the ticket Callaborators in project details currenly it just gets the users that replied to tickets 2024-04-08 15:43:04 -04:00
johnnyq
6435ffde67 Added total time worked for all tickets in project details 2024-04-08 15:19:35 -04:00
johnnyq
ea85094be8 Fixed Bulk Assign Ticket, UI Update on Ticket Details, added Project details to the right pane, moved Client and ticket details along with Assign Ticket to the top Ticket Header 2024-04-08 14:44:35 -04:00
johnnyq
2aefbd9fba DB Dump from last commit 2024-04-08 12:23:05 -04:00
johnnyq
72f96e0ebf Added Project Manager field to projects 2024-04-08 12:22:16 -04:00
johnnyq
d2e11fca61 Remove the Add Contact to a ticket as this can be done at the top 2024-04-07 16:17:27 -04:00
johnnyq
dfb1304bfa When completeing task add a private note to the ticket along with a 5 Min time worked soon will be configurable based off the task 2024-04-07 14:26:37 -04:00
johnnyq
1e85b56d2a Use Plus icon for Adding tickets to Projects 2024-04-07 13:28:28 -04:00
johnnyq
e1312b29e5 Generating a Project with Tickets is now possible by selecting a project template when creating a new project 2024-04-07 13:17:52 -04:00
Johnny
d54bcf9a14 Merge pull request #936 from wrongecho/portal-pw-reset-delay
Client Portal
2024-04-07 11:40:24 -04:00
Johnny
3191ef120e Merge pull request #935 from wrongecho/client-show-archived
Client archiving
2024-04-07 11:39:31 -04:00
Johnny
acc7a7bc97 Merge pull request #934 from wrongecho/portal-sql-tidy
Client Portal - Ticket SQL Tidy
2024-04-07 11:38:19 -04:00
Marcus Hill
7171289f26 Client Portal
- Remove old fake send delay as reset links now go via mail queue
- Small tidy
2024-04-07 10:14:37 +01:00
Marcus Hill
abf01384ca Client archiving
Relates to #510

- Ability to see archived clients
- Ability to un-archive a client
- To help prevent accidents, client deletion button now only shows once the client is archived
2024-04-07 09:52:23 +01:00
Marcus Hill
da3201dbe0 Client Portal - Ticket SQL Tidy
Tidy up the client portal sql for viewing tickets to only grab required fields - #933
2024-04-07 09:15:55 +01:00
johnnyq
d762efd1a6 Try to differentiate Project Template and Project Details 2024-04-06 22:21:15 -04:00
johnnyq
004e2eb69c Make Add Ticket More Prominent in Projects and move it out of the 3 dots 2024-04-06 22:16:40 -04:00
johnnyq
e3ff8854f9 Removed Task Descriptions as the name says it all 2024-04-06 22:07:29 -04:00
johnnyq
e6e6c38db2 UI: Changed Reword to AI Reword and changed color from Primary blue to Secondary Gray so it doesnt get confuged with reply in ticket details 2024-04-06 21:54:59 -04:00
johnnyq
8473ee018f Removed Add Task Modal as this can be added inside the ticket 2024-04-06 21:44:42 -04:00
johnnyq
48ecde6e9b Allow Overriding a ticket templates subject when creating a ticket from template 2024-04-06 20:54:22 -04:00
johnnyq
8d571682cc Cleaned up Contact Add/Edit Relabeled Secure tab to Access and moved Roles to Access Tab ss this is much more suitable 2024-04-06 20:05:53 -04:00
johnnyq
6da826e418 Tidy Update Project and Ticket Templates Deleting functions 2024-04-06 19:05:36 -04:00
johnnyq
f6b87553ac Created new table to allow many to many relationship for Ticket and Project Templates 2024-04-06 18:37:37 -04:00
johnnyq
c17957fe0a Order by the order number then by ticket template name 2024-04-05 18:22:50 -04:00
johnnyq
b22781d2ea Add Ticket Template order under project templates, this will state the execution order when deployed 2024-04-05 18:20:09 -04:00
Johnny
60212b380c Merge pull request #932 from wrongecho/ticket-email-status-fix
Ticket status in emails
2024-04-05 17:01:48 -04:00
Johnny
97cc36e93a Merge pull request #931 from itflow-org/wrongecho-patch-1
Clarify remember me token is for 2fa
2024-04-05 16:52:07 -04:00
johnnyq
dbe5525046 Added the ability to Add ticket templates to project templates and also to remove ticket templates from project templates 2024-04-05 16:50:22 -04:00
Marcus Hill
be01525136 Ticket status in emails
- Fix tickets showing an "unknown" status in client update emails
- Remove old code related to closing tickets, as close is now it's own button
2024-04-05 21:48:57 +01:00
wrongecho
d7a466bde6 Clarify remember me token is for 2fa 2024-04-05 21:27:33 +01:00
johnnyq
5370a70ab8 Renamed Login In the Frontend UI to Credentials to better fit other types of creds like API Keys, WiFi etc, also renamed the password field to password / key 2024-04-05 15:06:42 -04:00
johnnyq
05d979b3d8 Do not allow editing a closed project 2024-04-05 14:19:34 -04:00
johnnyq
048b890465 Added Open and Closed Project button to projects list, renamed complete to close for projects 2024-04-05 14:06:57 -04:00
johnnyq
43c06b8151 Now you can mark a project complete when all Tickets for the project are closed and we now show an open or closed status by the project name 2024-04-05 13:48:50 -04:00
johnnyq
064b37f87e Quick Fix 2024-04-04 19:54:33 -04:00
johnnyq
4824ae8ef8 Make Remmeber Me Token Configurable and default to 3 2024-04-04 19:52:44 -04:00
johnnyq
e1f1122b3e Added more global search parameters to assets like serial, mac, ip, make, model, os, status, type 2024-04-04 14:58:14 -04:00
johnnyq
8ca8f3ef46 Added Files and Recurring Tickets to the Global Search 2024-04-04 14:48:59 -04:00
johnnyq
730c1f4df3 Feature: You can now create a ticket from a ticket template 2024-04-03 15:41:20 -04:00
johnnyq
c8bac996bf Bump TinyMCE from 6.8.2 to 7.0.0 2024-04-02 12:10:33 -04:00
wrongecho
ed87ddc2dd Merge pull request #929 from wrongecho/portal-ticket-list-fix
Client Portal Tickets - Adjust bad SQL query that shows ticket subjects for other contacts
2024-04-02 00:38:48 +01:00
Marcus Hill
bc8f79cdf9 Adjust bad SQL query that allowed contacts to see ticket subjects (but not content) for other contacts 2024-04-02 00:36:55 +01:00
Marcus Hill
2f473c6a03 Adjust bad SQL query that allowed contacts to see ticket subjects (but not content) for other contacts 2024-04-02 00:30:25 +01:00
johnnyq
da2fee7fc6 Fix add project ticket to show all tickets but closed one instead of showing just closed tickets 2024-04-01 17:37:47 -04:00
johnnyq
6d8ab569c9 Add Ticket subject to Add ticket to Project notification and logging 2024-04-01 17:33:36 -04:00
johnnyq
e5e17c669f Made Add Ticket to Project Functionable 2024-04-01 17:21:59 -04:00
johnnyq
365cd79999 No Need for if conditions on a blank due date as it is required 2024-04-01 16:49:08 -04:00
johnnyq
cf71a58526 Make Project Due Date Required Field, Do not require a project Template 2024-04-01 16:45:13 -04:00
johnnyq
f1833e1083 Updated ticket status color capabilities to use multiple color instead of a select few, added activate disable ticket statuses, fixed ticket status Left joins in a few more areas 2024-04-01 16:27:05 -04:00
johnnyq
912e2774f8 Dont display tasks if none are set 2024-03-31 14:19:06 -04:00
johnnyq
9243964242 Tidy Projects UI 2024-03-31 14:17:35 -04:00
johnnyq
b04c2e1232 Added Project due to the UI: 2024-03-31 14:02:48 -04:00
johnnyq
2fa86d9ae7 Update DB Structure to include task order and project due date 2024-03-31 13:55:38 -04:00
johnnyq
3b46f1e6bd Added the ability to Add Ticket and Edit Ticket statuses, disallowed deleting editing system tickets, this is still work in progress 2024-03-31 13:40:31 -04:00
Johnny
dac5fb1284 Merge pull request #928 from wrongecho/login-tidy
Login related tidying
2024-03-30 20:33:36 -04:00
Marcus Hill
d94b9ce7bb Login related tidying
- Feature: Show users their remember-me tokens and allow them to be revoked
- Log when a user generates a remember-me token during sign in
- General refactoring and tidying up
2024-03-30 23:19:50 +00:00
johnnyq
2c22c732e4 Comment out updating undefined statuses 2024-03-30 17:53:30 -04:00
johnnyq
d74c2c6898 New Tciket Status: Update Projects 2024-03-30 17:39:45 -04:00
johnnyq
3fb3f647cf New Tciket Status: Fix Unbilled Ticket Report to use ticket closed at IS NOT NULL 2024-03-30 17:29:38 -04:00
johnnyq
770356ba10 No Need for ticket status name or status id when bulk closing tickets 2024-03-30 17:16:01 -04:00
johnnyq
07892afe24 Fix missing ) in calendar events 2024-03-30 17:02:41 -04:00
johnnyq
5b9cc50bae Allow to search by ticket status name 2024-03-30 16:59:49 -04:00
johnnyq
0a52e3a33d Update Calendar Events use the ticket_scheule field to determine if a ticket is scheduled or not instead of status as scheduled is not a core status 2024-03-30 16:55:11 -04:00
johnnyq
afcb0cffdc Remove Ticket Status display and priority and assigned to from invoice also updated the new ticket status int format 2024-03-30 16:34:14 -04:00
johnnyq
67a045a2b5 New Ticket Status Fix Gobal search 2024-03-30 16:18:39 -04:00
johnnyq
13a1d9d394 New Ticket Status Fix Ticket Listing is asset_Details 2024-03-30 16:08:18 -04:00
johnnyq
f39c380c47 New Ticket Status Correct Ticket Side nav Badges 2024-03-30 15:58:03 -04:00
johnnyq
f99be168cf New Ticket Status Fix dashboard Tickets 2024-03-30 15:55:04 -04:00
johnnyq
b63eddb300 Fix Ticket Close to use the new ticket status INT instead of string 2024-03-30 15:46:02 -04:00
johnnyq
4aad95d380 Add Ticket Closed at time to tickets that were Bulk Closed 2024-03-30 15:28:22 -04:00
johnnyq
b4db5013a3 Fix Bulk Close Ticket not updating the ticket_closed_at field and not using the new status id 2024-03-30 15:20:01 -04:00
johnnyq
387d2733fa Fixes ticket status that did not conform to the current ticket statuses to Open 2024-03-30 15:06:52 -04:00
johnnyq
349a276de2 Merge branch 'master' of github.com:itflow-org/itflow 2024-03-30 14:59:08 -04:00
johnnyq
e177dae237 Created Project template details page and updates Tasks in project details 2024-03-30 14:58:48 -04:00
Johnny
e2f825e5c1 Merge pull request #926 from wrongecho/ticket-statuses
Ticket Statuses from DB
2024-03-30 14:57:46 -04:00
wrongecho
fa777eaf9c Merge pull request #927 from itflow-org/we-template-nav
Update admin_side_nav.php
2024-03-30 09:10:20 +00:00
wrongecho
084dcb782e Update admin_side_nav.php
https://forum.itflow.org/d/785-new-templates-ui-bug-admin
2024-03-30 09:07:32 +00:00
wrongecho
dfa952ab73 Update README.md
Bugs should also go to the forum
2024-03-30 08:27:39 +00:00
Marcus Hill
7df1d419fa Ticket Statuses from DB / use left join instead of a function, hard-code system statuses 2024-03-29 23:20:52 +00:00
Marcus Hill
a961b8aa72 Ticket Statuses from DB / touchups 2024-03-29 12:08:02 +00:00
wrongecho
2e95b7cb6e Merge branch 'master' into ticket-statuses 2024-03-29 11:58:53 +00:00
Marcus Hill
8607198c3e Ticket Statuses from DB / add project id 2024-03-29 11:32:46 +00:00
Marcus Hill
667a93210c Ticket Statuses from DB 2024-03-29 11:22:32 +00:00
johnnyq
78e92ea8d6 Add Project Templates Listing, edit and add, more to come 2024-03-28 22:03:57 -04:00
johnnyq
89a1c5d2d8 Added Ticket Templates and the ability to add Tasks to the template, reworked the ticket details tasks and adding tasks 2024-03-28 21:09:32 -04:00
johnnyq
08fc72ded7 Fix Last Reponse Column under tickets and client tickets use the ticket_reply_created_at instead of ticket_updated_at 2024-03-27 23:12:17 -04:00
johnnyq
ee308453db Dont break when division of 0 occurs 2024-03-27 22:51:20 -04:00
johnnyq
e42c5bc2f5 Major UI Updates to projects, created project details which display project stats tickets and tasks, tickets can be linked to a project, soon will add all users who contributed to a project and some more stats along with a nice timeline from created to deadline 2024-03-27 22:27:56 -04:00
johnnyq
c9724bea0d DB Update task, ticket and project templates added 2024-03-27 19:16:44 -04:00
johnnyq
76cce6ac23 Updated Edit Domain and Certificates to match the tabing in the add modal 2024-03-27 14:53:15 -04:00
johnnyq
2012a80fe5 DB Duimp for the new network fields 2024-03-27 14:21:18 -04:00
johnnyq
8addc4f55c Feature: Added Subnet Mask and primary and secondary DNS change the wording for network to IP / Network in case a single IP needs to be used for example an Internet Connection, Added more newe tabs to the Add/Edit Network so everything fits and is organized 2024-03-27 14:19:32 -04:00
johnnyq
720a4af44e Fixed Missing Invoice Button when ticket is closed 2024-03-27 11:02:45 -04:00
johnnyq
26dc3172e7 Initial Project work on the UI started 2024-03-27 00:26:53 -04:00
johnnyq
6ff740e619 Fix Missing Asset Buttons when selected 2024-03-26 16:31:24 -04:00
johnnyq
0931f60764 Ticket Details Tidy Buttons and Ticket Details 2024-03-26 16:08:32 -04:00
johnnyq
c052850465 Automatic submit when Assign Tech is selected 2024-03-26 15:41:16 -04:00
johnnyq
cdc87562c9 Ticket Details UI Enhancements, Dont display entity cards if no data, Moved Add Entities to the Top Bar along with Invoice and Close Ticket. Combine the Client Details and Assign Card into one card, and Tidy Work 2024-03-26 15:11:57 -04:00
johnnyq
038e7e4a52 Add Task Completion Date and Time Stamp 2024-03-26 14:10:14 -04:00
johnnyq
31184dab62 Moved Tasks Card under Details, Added tje ability to Edit and mark a task complete 2024-03-26 14:06:32 -04:00
johnnyq
c40c204ce1 Use full name in vars 2024-03-25 16:45:34 -04:00
johnnyq
e2733fecb7 Some initial beginnings of task management in tickets, currently you can create and delete them more to come 2024-03-25 16:43:56 -04:00
Marcus Hill
63f35d5760 Ticket Statuses from DB
First swing at this to share my progress, isn't ready to merge yet but would appreciate thoughts
2024-03-24 22:57:21 +00:00
Marcus Hill
9c68a315db Ticket Statuses from DB
First swing at this to share my progress, isn't ready to merge yet but would appreciate thoughts
2024-03-24 22:54:38 +00:00
Marcus Hill
5e63ef9a2a Ticket Statuses from DB
First swing at this to share my progress, isn't ready to merge yet but would appreciate thoughts
2024-03-24 22:36:21 +00:00
Johnny
7702d8c5bf Merge pull request #920 from wrongecho/ticket-cleanup
General ticket updates/cleanup
2024-03-24 10:56:51 -04:00
Johnny
fe644317b6 Merge branch 'master' into ticket-cleanup 2024-03-24 10:56:43 -04:00
Johnny
865c2dcb84 Merge pull request #919 from wrongecho/ticket-status-color
Ticket status colours
2024-03-24 10:54:27 -04:00
Marcus Hill
ccb1bf9b0d General ticket updates/cleanup
- Tickets & Client Tickets: General tidy up, fix broken vars, remove unneeded vars, add comments
- Client Portal: Show assigned agent for open tickets
2024-03-24 11:31:46 +00:00
Marcus Hill
796ba6633e Ticket status colours
Standardize ticket statuses via function
2024-03-24 10:12:02 +00:00
johnnyq
b47aba1d5a Feature: Submit form when drop down are selected everywhere 2024-03-23 17:31:42 -04:00
johnnyq
2afb467503 Feature: Submit form when drop down are selected 2024-03-23 17:16:06 -04:00
johnnyq
1792aaee64 Feature added location to calendar events and created new tab called details in calendar events for description and location 2024-03-23 16:43:42 -04:00
johnnyq
5ebc6ffde8 Feature Added ability to select a ticket location for location based, still need to add more to this functionality 2024-03-23 16:24:40 -04:00
johnnyq
534e02e2c7 Feature: Color ticket rows yellow if Last Response was from a client This will let you know you need to be the next responder 2024-03-23 16:03:52 -04:00
johnnyq
79ea97410e Feature Show who last replied in ticket listings 2024-03-23 15:59:02 -04:00
johnnyq
4d773e895a Tid 2024-03-23 15:24:14 -04:00
johnnyq
df313e5bd6 Tidy removed Help on the Top Nav Bar too much clutter and unnessesary 2024-03-23 15:23:12 -04:00
johnnyq
9e7f50b9eb Feature Add Bulk Cancel and Delete to Mail Queue for mail that are any status other than sent 2024-03-23 15:01:01 -04:00
johnnyq
3cf1b8427c Fix Asset Counts into a better defined count query 2024-03-22 19:01:10 -04:00
johnnyq
ca7cf62098 Do not show all asset button if no assets are found, also get correct count of assets types if location is selected 2024-03-22 18:38:29 -04:00
johnnyq
1d9d9a89ed Feature Added Location filter to assets 2024-03-22 18:09:15 -04:00
johnnyq
8270c8fcc4 Cannot edit driver Fix 2024-03-22 17:16:06 -04:00
johnnyq
cf8b2aa7ad Add eye icon for people viewing tickets 2024-03-22 15:58:25 -04:00
johnnyq
eda78f0927 Moved Ticket Viewing to the top if someone is viwing the ticket the same time you are 2024-03-22 15:44:24 -04:00
johnnyq
3974055bff Missing Div 2024-03-22 15:33:52 -04:00
johnnyq
900df014b7 Do not show Responses if the count is 0 2024-03-22 13:35:48 -04:00
johnnyq
4cfbfb1a73 Improved spae utiliztion in ticket details by Removing the Extra Card on the left and right panes 2024-03-22 13:25:13 -04:00
johnnyq
90156f4f1b Enhanced the UI for document details removed the lists in replacement of divs, remove items to the far right, removed the span buttons and used normal button as it took up too much space 2024-03-22 13:17:47 -04:00
johnnyq
a6a763c24c Move View Queue Message away from a modal as tables tend to break the modal causing distorted view, more ui work for this to come 2024-03-21 18:01:41 -04:00
johnnyq
0c62ce169f Add Pretty content JS function to global search so HTML ticket replies look nicer and fit to width 2024-03-21 17:19:06 -04:00
johnnyq
e34f66f00a Updated Services to use the media css function 2024-03-21 17:12:13 -04:00
johnnyq
1f1197be50 Missing var 2024-03-21 16:16:32 -04:00
johnnyq
7d22f208b8 Enhancement moved to media css for domain listing and added description field 2024-03-21 16:07:54 -04:00
johnnyq
ed20681790 Update Client Vendors to use the new media css function 2024-03-21 15:56:09 -04:00
johnnyq
51dba5ac1a Certificates Enhancement, Use Media CSS, add description create a new tab for notes 2024-03-21 15:46:14 -04:00
johnnyq
5266f126cb Set Timezone in the CRON files as well as the command line PHP doesn't always respect the system timezone 2024-03-21 14:55:54 -04:00
johnnyq
2f4ddd85ca Fix PHP UTC issue, new PHP updates did not not respect System TimeZone 2024-03-21 14:23:16 -04:00
johnnyq
bdf868588e Ability to search by network description 2024-03-20 18:46:34 -04:00
johnnyq
16cfc3e032 Add Description to Networks 2024-03-20 18:44:32 -04:00
johnnyq
ca0eb4f261 Adjust media css listing to use divs instead of <p> tags 2024-03-20 18:11:37 -04:00
johnnyq
5d3e6da38d Removed Extra location name under edit location 2024-03-20 17:46:32 -04:00
johnnyq
bfe7c3098d Fix broken open uri 2024-03-20 17:31:04 -04:00
johnnyq
71c4537263 Client Logins Enhancement: Moved to the new media CSS Class, fixed password reveal would take you to the top of the page, moved open URI to the action bar as a button, fixed password alignment for copy to clipboard, description is now below the login name, made set button to type=button to prevent submits if wrapped in a form 2024-03-20 17:28:09 -04:00
johnnyq
534096f182 Software Licenese / Template Enhancements: Fixed create Software from template, added description, user media css for licenses and templates, reworked the add edit modal, Removed Software Login 2024-03-20 16:54:38 -04:00
johnnyq
845e168942 Updated the rest of wording regarding email being sent to email been queued with a link to the Mail Queuer 2024-03-20 14:22:57 -04:00
johnnyq
c0115a26c5 Group Ticket Replies and only search in ticket reply not ticket subject or ticket details In global search 2024-03-20 13:36:04 -04:00
johnnyq
6790464e90 Do not show DHCP if IP is null under assets 2024-03-20 13:05:10 -04:00
johnnyq
dafdc7a63b Include Client Name in Ticket Replies Global Search 2024-03-20 13:00:50 -04:00
johnnyq
6a3d53fc4b Feature: Added Ticket Replies to Global Search 2024-03-20 12:53:25 -04:00
johnnyq
643144bc5e Name Margin enhancement 2024-03-19 18:14:36 -04:00
johnnyq
1ff614381f UI Enhancement to contact listing now use the media class 2024-03-19 18:10:40 -04:00
johnnyq
a8bacd5acb Give notes a little more space 2024-03-19 17:52:27 -04:00
johnnyq
4c01c472b8 Add UI and logic for location Description, Tweak Location Listing UI to use the media class 2024-03-19 17:48:54 -04:00
johnnyq
b800d52ea9 No Null for Invitation status 2024-03-19 17:12:22 -04:00
johnnyq
4fec8efecd DB Structure Update, added missing Short description fields to several entities, Added Event Attendees Table, Added event location, added db support support to link files with an asset, added db support to allow multiple contacts for a vendors 2024-03-19 17:08:37 -04:00
johnnyq
1a74acfbff Adjust margins in assets 2024-03-19 15:27:39 -04:00
johnnyq
904b87fff6 reduced serial number to just serial 2024-03-19 15:13:42 -04:00
johnnyq
df4f8a518c Add DHCP next to IP if none is given 2024-03-19 15:11:06 -04:00
johnnyq
e426778ac2 Remove Copy IP Button from assets as its not nessessary and was taking up precious space 2024-03-19 15:09:39 -04:00
johnnyq
2320a93f82 Renamed Column headers to increase margin space 2024-03-19 15:03:57 -04:00
johnnyq
76eae92954 UI Use media Class for assets to seperate the icon from the name / description text, moved logins and and remote links to the action column instead of by the asset name also increased right margin of the device icons for top search bar 2024-03-19 15:00:59 -04:00
johnnyq
2c8c275a7e Use bootstrap css media function to properly seperate icon on the left and text on the right for files, Fix Search for files within a folder. 2024-03-19 14:33:21 -04:00
Johnny
294760b50c Merge pull request #917 from wrongecho/guest-sharing-otp
Guest login sharing - OTP
2024-03-17 22:52:54 -04:00
Johnny
0dfca605a8 Merge pull request #916 from wrongecho/assets-and-logins
Assets and Logins
2024-03-17 22:52:29 -04:00
Johnny
aed46a3b21 Merge pull request #915 from wrongecho/contact-pw-generator-bugfix
Bugfix: Contact generated passwords are in quotes
2024-03-17 22:50:19 -04:00
Marcus Hill
f1528b9e95 Guest login sharing - OTP
Bugfix: Fix guests not being able to see the 2FA/TOTP token via the sharing link
https://forum.itflow.org/d/646-shared-login-with-otp
2024-03-17 19:32:49 +00:00
Marcus Hill
6788781ee6 Assets and Logins
- Show asset location when relating it to a login
- Bugfix: Swap login_id for asset_id on client_assets.php, as login_id won't yet be defined
- Bugfix: Don't show archived assets in the login relation modal
2024-03-17 19:19:59 +00:00
Marcus Hill
d29726f63e Bugfix: Contact generated passwords are in quotes
Fixing as per https://forum.itflow.org/d/760-password-generator-include-at-start-and-end
2024-03-17 18:51:56 +00:00
Johnny
064629d499 Merge pull request #914 from wrongecho/smtp-test-wording
Reword SMTP test message to make it clear that messages are queued
2024-03-17 13:42:31 -04:00
Johnny
ba68fe54ab Merge pull request #911 from wrongecho/rec-tck-agent-assign
Ticketing updates
2024-03-17 13:42:18 -04:00
Marcus Hill
678c53a8fb Reword SMTP test message to make it clear that messages are queued 2024-03-17 16:39:03 +00:00
wrongecho
0fd50a33ea Update db.sql
Recurring ticket agent assignment, retrigger checks
2024-03-17 16:26:59 +00:00
wrongecho
43ebb867b2 Merge pull request #912 from itflow-org/wrongecho-db-sql-lint
Create dbsql-lint.yml
2024-03-17 16:24:53 +00:00
wrongecho
73b5a6b0a5 Create dbsql-lint.yml 2024-03-17 16:23:55 +00:00
Marcus Hill
dfce95a67b Recurring tickets bugfixes 2024-03-17 11:57:58 +00:00
Marcus Hill
f9a5ca1ef8 Ticketing updates
- Bugfix: Prevent tickets from being assigned to disabled techs
- Bugfix: Un-assign all open tickets when a tech account is disabled
- Allow auto-assignment of recurring/scheduled tickets to an agent/tech (#901)
- Rework layout of recurring/scheduled ticket modal
2024-03-17 11:09:53 +00:00
johnnyq
cdd16bd460 Add file Description below filename, still need to work on the UI a bit 2024-03-15 18:44:16 -04:00
johnnyq
27a96c2293 Add Important asset, document, file, add file Description to DB Structure 2024-03-15 18:32:42 -04:00
johnnyq
d32925eefc Tidy 2024-03-13 14:03:07 -04:00
johnnyq
07c27eb2f9 Merge branch 'master' of github.com:itflow-org/itflow 2024-03-11 17:51:27 -04:00
johnnyq
79011763db Fix issue where certrain password characters would break writing config.php file which would break the setup also check for valid host 2024-03-11 17:50:48 -04:00
Johnny
a1ccecea9e Merge pull request #908 from wrongecho/guest-sharing-downloads
Guest Sharing - File downloads
2024-03-11 16:49:11 -04:00
Marcus Hill
52685e424b Guest Sharing - File downloads
- Fix a bug where the file name wouldn't be shown to guests in certain situations
- General refactor and tidy of the file download code
2024-03-10 19:06:40 +00:00
Johnny
4b839c8b23 Merge pull request #907 from wrongecho/file-upload-pfx
Allow pfx file uploads
2024-03-10 13:38:04 -04:00
Marcus Hill
c251cc1faf Allow pfx file uploads 2024-03-10 10:48:17 +00:00
johnnyq
a40ec71b0a Fix Broken Test Input Text Reword under AI Settings 2024-03-08 16:11:25 -05:00
johnnyq
5d40f7480b Add Type Button to prevent submit for copy Email in contacts 2024-03-08 12:23:44 -05:00
johnnyq
82012ced62 Use margin instead of br to seperate Last Login Info on users list 2024-03-06 12:06:32 -05:00
johnnyq
a86523bd1b Removed the requirment visual for transer method as its not required 2024-03-05 19:26:16 -05:00
johnnyq
37a4f5cee0 Added Method of Transfer to Transfers frontend, currently uses payment type category and is optional useful to see how the money got transferred 2024-03-05 19:22:05 -05:00
johnnyq
1dfc819660 Add Transfer Method to the Database this will in the method to transfer money from 1 account to another 2024-03-05 18:48:34 -05:00
johnnyq
120348df4d Add _amount 2024-03-05 17:07:51 -05:00
johnnyq
efdef7f6aa Better Descriptive Vars to seperate amounts vs counts in Invoices 2024-03-05 17:05:43 -05:00
johnnyq
5e88664558 Exclude Cancelled 2024-03-05 16:59:21 -05:00
johnnyq
e6192ab5eb Invoice Top Bar Statuses, Get the Real Overdue amout which is to subtract from the partial payments 2024-03-05 16:41:24 -05:00
johnnyq
2d447369b6 UI: Icon updates for income and profit 2024-03-05 16:37:20 -05:00
johnnyq
8719919639 UI: Update Invoices Listing Top Header to include Drafts, Unpaid and Overdue instead of Drafts, Sent, Viewed and Partial 2024-03-05 16:23:05 -05:00
johnnyq
a91352229e Drop asset_login_id as we have login_asset_id to allow 1 asset many logins, also drop the unused many to many asset login table 2024-03-03 13:40:50 -05:00
johnnyq
51248ed841 You can now view all login / passwords for an asset under asset lists and under asset details now 2024-03-03 13:23:52 -05:00
johnnyq
eeb5cece7c Remove SQL Left Join logins for assets as this is causing duplicate assets to appear if more than 1 related login exists, this break viewing login password for each asset, we will handle this a little differently 2024-03-03 13:03:49 -05:00
Johnny
8c51754c6b Merge pull request #900 from wrongecho/ticketing-hide-functions-closed
Ticketing (and Invoicing)
2024-03-02 19:48:55 -05:00
Johnny
cb57a1e86b Merge branch 'master' into ticketing-hide-functions-closed 2024-03-02 19:48:44 -05:00
Johnny
ef14e95adf Merge pull request #902 from wrongecho/ticket-statuses
Ticket States
2024-03-02 19:44:39 -05:00
Marcus Hill
81301388cd Ticket Statuses
Standardize on 5 consistent ticket states:-
- New (Red/Danger)
- Open (Blue/Primary)
- On Hold (Green/Success)
- Auto Close (Dark/black)
- Closed (Dark/black)

Update parts of the app where these have deviated from, as they have not been updated everywhere.
Other states may be configurable in future via custom fields.
2024-03-03 00:22:20 +00:00
Marcus Hill
b9431645d3 Ticket Statuses
Standardize on 5 consistent ticket states:-
- New (Red/Danger)
- Open (Blue/Primary)
- On Hold (Green/Success)
- Auto Close (Dark/black)
- Closed (Dark/black)

Update parts of the app where these have deviated from, as they have not been updated everywhere.
Other states may be configurable in future via custom fields.
2024-03-03 00:13:29 +00:00
Marcus Hill
66e07b0c47 Ticket closure email wording 2024-03-02 18:35:10 +00:00
Marcus Hill
3084e9e0d3 Ticketing (and Invoicing)
- Hide the ability to add/delete watchers when a ticket is closed
- Hide watchers card entirely when tickets are closed, if the ticket had no watchers
- Hide the ability to schedule a ticket when a ticket is closed
- Don't include tickets in an auto-close state in the sidebar ticket counts
- Small edit to the ticket closure wording to account for requests and issues
- Small edits to invoice emails text
2024-03-02 18:31:01 +00:00
wrongecho
f5a6dc2b0a Update FUNDING.yml
Adjust sponsor/donate link on Github
2024-03-02 09:38:49 +00:00
johnnyq
f860d36334 Fix Ticket Notifications via Client Portal 2024-03-01 14:43:50 -05:00
johnnyq
15e729e65a Removed old Remember me token, update revoke remember me function 2024-02-29 15:51:26 -05:00
johnnyq
6641c5c338 Added removed old remmeber me tokens after 48 hours to the cron.php cleanup section 2024-02-29 14:46:02 -05:00
johnnyq
9955ff56f5 Carry over discount amounts when copying a quote or invoice 2024-02-29 14:28:48 -05:00
johnnyq
85cc8c163b Carry over discount amounts from recurring and quotes to invoice, fix force recurring 2024-02-29 14:15:57 -05:00
johnnyq
998a701634 UI: Show assigned contact in asset dropdown select menu in tickets 2024-02-26 16:50:12 -05:00
johnnyq
be5bf1853e Sanitize From Name and From Email Output in bulk mail as its not sanitized when the vars are grabbed from get_settings.php 2024-02-26 15:58:28 -05:00
johnnyq
015ef13c55 Show the From name from System, Billing, Sales and Support Email in Bulk Email from section 2024-02-26 15:51:44 -05:00
johnnyq
18bc7c909e Sort client names ASC not desc for bulk mail 2024-02-26 15:45:11 -05:00
johnnyq
0a088a43c5 UI: Add some bottom margin so when the button is reveals rows dont shift down a few lines 2024-02-26 15:43:20 -05:00
johnnyq
4369b3bd12 Include and sort by client name first in global bulk email 2024-02-26 15:42:03 -05:00
johnnyq
c3c9da0c71 Use the bulk mail function in bulk mailers for standardization, also fix unused vars in smtp settings form 2024-02-26 15:38:00 -05:00
johnnyq
1c50a0e314 UI: Center Aligned Billable under client tickets 2024-02-26 13:08:20 -05:00
johnnyq
0997282077 Fix broken link logs.php to admin_logs.php 2024-02-26 12:28:21 -05:00
Johnny
fe5376c52e Merge pull request #893 from wrongecho/ticket-billable-column
Hide billable tickets when accounting is disabled
2024-02-24 11:19:48 -05:00
Johnny
e1b29df0ee Merge pull request #894 from wrongecho/locations-api
Add locations read api endpoint
2024-02-24 11:19:40 -05:00
Johnny
d318fffc8c Merge pull request #892 from wrongecho/mail-queue
Mail queue & tickets
2024-02-24 11:19:34 -05:00
Johnny
2016275db3 Merge pull request #890 from wrongecho/categories-shortcut-fix
Fix error 404 on categories.php as it is now admin_categories.php
2024-02-24 11:18:54 -05:00
Marcus Hill
54e015b5a5 Add locations read api endpoint 2024-02-24 11:56:18 +00:00
Marcus Hill
78db33c5d5 Hide billable tickets when accounting is disabled 2024-02-24 11:50:13 +00:00
Marcus Hill
1e8fbddcbd Mail queue & tickets
- Allow cancelling emails
- Adjust wording of ticket scheduling emails
2024-02-24 11:06:55 +00:00
johnnyq
da54b125c3 Merge branch 'master' of github.com:itflow-org/itflow 2024-02-23 23:45:06 -05:00
johnnyq
6019a4d1be DB Structure fix 2024-02-23 23:44:49 -05:00
wrongecho
c510eac613 Merge pull request #891 from wrongecho/login-encryption-fix
BUGFIX: Login with and actually decrypt the master encryption key
2024-02-23 21:29:07 +00:00
Marcus Hill
6432ee0486 BUGFIX: Login with and actually decrypt the master encryption key 2024-02-23 21:20:03 +00:00
Marcus Hill
4b730147c0 Fix error 404 on categories.php as it is now admin_categories.php 2024-02-23 20:52:34 +00:00
Johnny
603d677dfd Merge pull request #888 from wrongecho/dns-expiry-null-fix
Domain expiration dates
2024-02-23 12:23:20 -05:00
johnnyq
31184f0db1 Fix Broken DB Update was missing Primary Key declaration 2024-02-22 17:43:08 -05:00
Johnny
46344c962b Merge pull request #886 from twetech/0.1.8.4
Remember Me Tokens, and AI Enhancements
2024-02-22 17:34:10 -05:00
Johnny
f363e7e6fc Merge pull request #887 from Viborg-IT/vendor-link
Update client_vendors.php
2024-02-22 17:29:27 -05:00
Marcus Hill
dae51c9b8b Domain expiration dates - remove debug 2024-02-22 21:52:57 +00:00
Marcus Hill
66dc7e799b Domain expiration dates
- Update logic in post when adding/editing a domain to better account for null values
- Update logic in cron domain refresher to account for null values
- Prevent cron domain refresher getting stuck on a single domain
- Exclude domains with no expiration date from the cron nightly renewal alerts
2024-02-22 21:51:12 +00:00
Nicky Mogensen
30b6f9b6a7 Update client_vendors.php
Added column to quick access a vendors support url
2024-02-22 21:12:10 +01:00
o-psi
5d620d041a Fix user role and other definitions 2024-02-22 12:15:15 -06:00
o-psi
1d4271de36 Merge branch '0.1.8.4' of https://github.com/twetech/itflow into 0.1.8.4 2024-02-22 17:49:11 +00:00
o-psi
3947c3a329 Remove comment 2024-02-22 17:49:08 +00:00
o-psi
28ab569dfc Update Prompt 2024-02-22 17:48:53 +00:00
Andrew Malsbury
d2c33c28a0 Merge pull request #5 from twetech:remember-me-tokens-table
Change remember me tokens to many:many table
2024-02-22 11:46:42 -06:00
o-psi
c2cf0bb448 Change remember me tokens to a many:many table to allow for multiple devices to be remembered. 2024-02-22 17:45:09 +00:00
Andrew Malsbury
e656837d3c Merge branch 'itflow-org:master' into 0.1.8.4 2024-02-22 11:06:49 -06:00
o-psi
06ce12ba47 Update AI prompting 2024-02-21 18:13:10 +00:00
o-psi
b31f1b4c49 add ticket description to AI Query 2024-02-21 11:16:40 -06:00
johnnyq
4fddeb88b7 Fix issue with password managers asking for passwords when migrating away from the assets page 2024-02-20 14:53:32 -05:00
johnnyq
14cb4bb09a set the remember me token from 14 Days to 2 Days or 48 Hours 2024-02-19 15:00:32 -05:00
johnnyq
03bd7f837c Merge branch 'master' of github.com:itflow-org/itflow 2024-02-16 14:53:30 -05:00
johnnyq
703e0f6bb2 Remove Axios as we are not using it 2024-02-16 14:52:57 -05:00
wrongecho
ae80bba5ce Deleting recurring tickets - correctly pull subject/frequency 2024-02-16 12:20:49 +00:00
wrongecho
793a4f9c8e Recurring ticket deletion wording 2024-02-16 12:18:36 +00:00
wrongecho
e6418046aa Fix deleting recurring tickets 2024-02-16 12:15:55 +00:00
johnnyq
2a4efe629f Move Repky buttons and Control on one row removed the Timer Icon just use boxes for time as this is assumed 2024-02-15 18:24:07 -05:00
johnnyq
16a8e3d828 UI: Wrap tickert detail UI into 3 card sections for ease of seperation 2024-02-15 18:19:18 -05:00
johnnyq
66d118c1f2 UI: Wrap Dashboard and Top Controls in seperate cards 2024-02-15 18:05:37 -05:00
johnnyq
b4c50a9cd8 UI: Wrap the Calendar in a card similar to client calendar 2024-02-15 17:59:07 -05:00
Johnny
8e3c490092 Merge pull request #884 from twetech/0.1.8.4
0.1.8.4
2024-02-15 17:56:04 -05:00
o-psi
671cdd9832 Fix filtering to admin bulk mail 2024-02-15 22:16:01 +00:00
o-psi
466fbc03ca Merge branch '0.1.8.4' of https://github.com/twetech/itflow into 0.1.8.4 2024-02-15 22:12:43 +00:00
o-psi
958e808c88 fix links to contacts 2024-02-15 22:12:41 +00:00
o-psi
1ffa918d8e Merge branch '0.1.8.4' of https://github.com/twetech/itflow into 0.1.8.4 2024-02-15 16:09:25 -06:00
o-psi
79157c88ea Fix collections report 2024-02-15 16:09:10 -06:00
o-psi
570b3479a9 Only Special Contacts 2024-02-15 22:08:40 +00:00
o-psi
5d15a7ded9 Merge branch '0.1.8.4' of https://github.com/twetech/itflow into 0.1.8.4 2024-02-15 22:04:57 +00:00
o-psi
633c2f785c Add mass bulk mail 2024-02-15 22:04:54 +00:00
o-psi
9e2f92a92f Fix client statement payments 2024-02-15 15:41:34 -06:00
o-psi
277e91b07e Update Password Gen Function 2024-02-15 21:35:21 +00:00
Johnny
e358230a44 Merge pull request #883 from o-psi/patch-1
Add Zapcal to the readme
2024-02-15 12:19:47 -05:00
Johnny
b8f8cca54c Merge pull request #881 from twetech/0.1.8.3
0.1.8.3 (Calendar Update)
2024-02-15 12:16:51 -05:00
Andrew Malsbury
4db0a68488 Update README.md 2024-02-15 11:00:25 -06:00
Andrew Malsbury
00d4284e7c Merge pull request #4 from twetech/0.1.8.3
Allow canceling scheduled tickets
2024-02-15 10:36:25 -06:00
o-psi
cdf4118b09 Allow canceling scheduled tickets 2024-02-15 16:31:35 +00:00
Andrew Malsbury
f34818425b Merge pull request #3 from twetech/client-recurrings
Make same changes to client pages as main recuring invoices and tickets
2024-02-15 09:53:05 -06:00
o-psi
724540da33 Make same changes to client pages as main recuring invoices and tickets 2024-02-15 15:51:11 +00:00
o-psi
a2f8f8f731 Make script source local, and fix client_events.php 2024-02-15 15:07:12 +00:00
o-psi
767e0ecfd7 Remove old FullCalendar 2024-02-14 22:31:45 +00:00
o-psi
5a926ba205 Remove readme 2024-02-14 22:30:46 +00:00
o-psi
31171405ef Remove excess from FullCalendar 2024-02-14 22:27:25 +00:00
o-psi
09f7f8b1cd Adjust Calendar Spacing 2024-02-14 16:05:40 -06:00
o-psi
f573f0401b More calendar tweaks 2024-02-14 21:55:46 +00:00
o-psi
1f3799ebe3 Update Calendar to Full Calendar 6.1.10 2024-02-14 20:21:19 +00:00
Johnny
20845d72da Merge pull request #880 from wrongecho/logs
Update URL from logs.php to admin_logs.php
2024-02-12 17:55:31 -05:00
Johnny
e2acf07d6c Merge pull request #879 from wrongecho/recurring-tickets-wording
Recurring tickets
2024-02-12 17:55:08 -05:00
Marcus Hill
aee47adf12 Update URL from logs.php to admin_logs.php 2024-02-12 22:25:35 +00:00
Marcus Hill
2c7b65dad2 Recurring tickets
- Reword some areas to better separate recurring and scheduled tickets.
- Fix bulk actions not doing anything due to form name mismatch
2024-02-12 22:17:05 +00:00
Johnny
85f55a629b Merge pull request #878 from wrongecho/scheduling
Ticket scheduling enhancements
2024-02-12 15:00:30 -05:00
Marcus Hill
b64df190ed Ticket scheduling
- Prevent scheduling dates in the past (also for API keys expiry date)
- Correct the ticket URL in the agent email
- Update the onsite value in the database when scheduling a ticket
- Reword the internal note to include a user friendly time and whether the ticket is onsite/remote
2024-02-12 19:52:12 +00:00
Johnny
c207fdd1f5 Merge pull request #877 from wrongecho/ticket-respond-behaviour
Enhance ticket reply button
2024-02-12 13:43:35 -05:00
Marcus Hill
25d242dc86 Enhance ticket reply button
- Better logic on when the button should default to private/public
- Fix the new plane icon not showing when the button was checked/unchecked
2024-02-12 18:10:37 +00:00
johnnyq
ddb8061404 [FEATURE] Added AI Rewording Functionality to Create Ticket, Ticket Reply, Create Document and Edit Document, more to come 2024-02-11 00:13:10 -05:00
johnnyq
48ba4445bf Added LocalAI 2024-02-10 21:25:18 -05:00
johnnyq
a1d642c54b You can now Test AI Rewording Functionality right from the AI Settings Screen 2024-02-10 21:15:05 -05:00
johnnyq
726b023592 Renamed Scheduled Ticket Files to Recurring Ticket and made some more changes inside the files 2024-02-10 17:31:32 -05:00
johnnyq
310e3f0a42 Split Admin Menu and Settings Menu 2024-02-10 17:10:14 -05:00
johnnyq
30d41c523e Add Seperate Menu for Settings will be splitting Admin and Settings 2024-02-10 16:09:05 -05:00
johnnyq
e177fa193a Change more wording from the old scheduled tickets to recurring tickets 2024-02-10 15:48:00 -05:00
johnnyq
3b0b0c37e1 Do a DB Structure Dump 2024-02-10 15:26:40 -05:00
johnnyq
cb26d40090 Added AI Model to the AI settings 2024-02-10 15:24:25 -05:00
johnnyq
d9f7a2d128 Moved Recurring Invoices Inside Invoices and same with Recurring Expenses inside expense to reduce side nav menu bloat similar to recurring tickets 2024-02-10 15:13:52 -05:00
johnnyq
3374a7042a Revert Mail Queue Query Change, update the db structure to include new fields 2024-02-10 14:34:34 -05:00
Johnny
d78b667e0b Merge pull request #875 from twetech/0.1.8.2
0.1.8.2 (Scheduled tickets, and Email Improvements)
2024-02-10 14:30:30 -05:00
Johnny
4e2f107d4c Merge pull request #876 from wrongecho/cert-pull-details-fix
Bugfix: Unable to update certificate details
2024-02-10 13:57:29 -05:00
Marcus Hill
d09082bd18 Bugfix: Unable to update certificate details for existing certificate entries 2024-02-10 13:36:41 +00:00
o-psi
12f6f86581 Update for long tickets 2024-02-10 02:42:37 +00:00
o-psi
5ac03e7086 Merge branch '0.1.8.2' of https://github.com/twetech/itflow into 0.1.8.2 2024-02-09 22:49:52 +00:00
o-psi
2bf0a2aef8 cleanups 2024-02-09 22:49:12 +00:00
o-psi
f0d2f5b02a SonarCloud Cleanups 2024-02-09 16:40:51 -06:00
o-psi
971830ac21 Unassigned filter incorrect 2024-02-09 22:17:09 +00:00
o-psi
34b5e96e5a Update DB and fix Calendar 2024-02-09 22:15:31 +00:00
o-psi
6e14406364 Update Calendar to show past scheduled tickets as different colors based on status. 2024-02-09 22:06:34 +00:00
johnnyq
083d9eadc3 Added Pop Over title to Expense Date to show the TimeStamp that expense was actually created in The Database. Will implement more Title Popovers throughout ITFlow where additional info like that can be useful 2024-02-09 16:29:49 -05:00
o-psi
c72a4a2413 Update ticket scheduled post actions. 2024-02-09 17:10:59 +00:00
johnnyq
f2cba616a4 Added Axios js started testing AI Capabilities in blank.php 2024-02-08 18:47:17 -05:00
o-psi
672e51b21a Update DB to match 2024-02-08 21:41:31 +00:00
Andrew Malsbury
3d3587a525 Merge branch 'master' into 0.1.8.2 2024-02-08 14:34:39 -06:00
o-psi
b3df9fc9f6 Fix email for iCal 2024-02-08 14:16:27 -06:00
o-psi
e2392c3c6c Add iCal functionality 2024-02-08 12:59:36 -06:00
johnnyq
4dae89dabc The option to set the timezone in PHP was disabled to prevent inconsistencies with MariaDB/MySQL, which utilize the system's timezone, Although can still select timezone in the app the system time will overide it. So its best to set timezone on the system itself 2024-02-08 13:01:54 -05:00
johnnyq
919c46c03d Moved Tags on top 2024-02-05 21:55:55 -05:00
johnnyq
717f4d9e1a Fix DB Download to include ITFlow in filename 2024-02-05 21:28:53 -05:00
johnnyq
74fb7931f0 Fix DB Download to include company name and ITFlow 2024-02-05 21:26:23 -05:00
johnnyq
09838f10ed [UI] Setting Nav reorganization, eventually we will split Administration into two side naves one for Administration and one for settings 2024-02-05 21:19:12 -05:00
johnnyq
6f6b56dcfd Update Icon and wording 2024-02-05 21:12:32 -05:00
johnnyq
dc69101624 [Feature] The Start of AI Integration within ITFlow 2024-02-05 21:01:34 -05:00
johnnyq
e7586fcfb5 Update All the bulkSelect Lists to use the new format still need to fix the bulk delete submit button to allow for a confirm 2024-02-05 18:37:43 -05:00
Andrew Malsbury
50b2c3ad6c Merge branch 'itflow-org:master' into 0.1.8.2 2024-02-05 09:18:52 -06:00
Johnny
f8615bf51b Merge pull request #874 from wrongecho/api-clients-create
Api - clients create
2024-02-04 22:21:06 -05:00
Marcus Hill
102481d09f API - Add client create endpoint 2024-02-04 14:51:58 +00:00
Marcus Hill
8a9a4fd97e Bugfix: Prevent preg_replace passing null parameter error when no phone is present 2024-02-04 14:50:38 +00:00
johnnyq
8347edc04e added more days to invoice alert 2024-02-03 18:43:16 -05:00
johnnyq
f97f6ebdb6 Set Item Order to 998 for Late fee so they appear at the bottom of the invoice. Note: Item Order 999 is used for payment gateway fees 2024-02-03 18:31:26 -05:00
johnnyq
877ae71284 Additional wording 2024-02-03 18:13:56 -05:00
johnnyq
a3567af8a1 Added some legal terms to client pays fees and some links to stripe's current pricing 2024-02-03 18:11:48 -05:00
johnnyq
b386cbb170 Client Payment Gateway Fee is added as a line item if client pays fees is on and client chooses online pay this Fixes the negative invoice Balances when client pays fees is enabled 2024-02-03 17:44:48 -05:00
johnnyq
a6a93fd820 Fix client pays fees calculation. I didn't quite understand why the previous formula was used until i read this https://support.stripe.com/questions/passing-the-stripe-fee-on-to-customers 2024-02-03 17:14:48 -05:00
johnnyq
4f4bb56820 update .gitignore to include custom favicon 2024-02-03 14:33:48 -05:00
johnnyq
5d9ab76689 Remove Custom favicon 2024-02-03 14:32:08 -05:00
johnnyq
e9c85297eb Feature: Allow to upload custom fav icon under settings > Theme, icon is limited to .ico format only 2024-02-03 14:30:03 -05:00
johnnyq
01b717615e Added favicon condition everywhere 2024-02-03 13:18:20 -05:00
johnnyq
a5f08af78e Added condition to check if favicon.ico exists in /uploads else use the default 2024-02-03 13:11:04 -05:00
johnnyq
16420f417f Add Default Fav icon for now 2024-02-03 13:02:24 -05:00
johnnyq
505ecb2701 Fix Delete Confirmation for services, missing </div> Tag in add Service was causing it, also tidyed up service code 2024-02-03 12:25:38 -05:00
Andrew Malsbury
c26787b1d2 Merge pull request #2 from twetech/Unbilled-tickets-dashboard
Add unbilled tickets to dashboard if tickets and accounting is on
2024-02-02 13:28:27 -06:00
Andrew Malsbury
23770ac114 Merge pull request #1 from twetech/scheduled-tickets
Scheduled tickets
2024-02-02 12:38:33 -06:00
o-psi
3a74786cc4 Update side_nav.php to highlight "scheduled_tickets.php" as active 2024-02-02 17:42:24 +00:00
o-psi
f71d3d9b19 finish rename scheduled tickets to recurring tickets in UI 2024-02-02 15:08:44 +00:00
o-psi
0ac36f91eb Update recurring expenses icon 2024-02-02 14:40:35 +00:00
o-psi
a6f105e660 Update side_nav.php with recurring tickets link 2024-02-02 14:40:24 +00:00
o-psi
03d3b04bdb Update side_nav.php: Changed label from "Scheduled Tickets" to "Recurring Tickets" 2024-02-02 14:38:25 +00:00
Andrew Malsbury
6c247e0f58 Merge branch '0.1.7' into scheduled-tickets 2024-02-01 21:42:24 -06:00
johnnyq
1303f18218 Tidy 2024-01-31 22:16:21 -05:00
johnnyq
28e7a6b195 Removed Gateway Fee from the baance of Guest View Invoice and displayed it on the Pay Online button, as the client can pay other ways if they decide to not pay online if Client Pays Fees is enabled 2024-01-31 22:11:27 -05:00
johnnyq
1bbb4426f6 Fix Expense being off for Payment Gateway Fee 2024-01-31 21:33:37 -05:00
johnnyq
96ff92d070 Feature: Bulk Edit Category, Client and Account for expenses 2024-01-31 17:09:35 -05:00
johnnyq
19f4e215de feat. Bulk Reply To Tickets including create a private note 2024-01-31 15:24:54 -05:00
johnnyq
7975505823 feat. Updated Bulk Close Ticket to allow for a Private Note instead of public 2024-01-31 14:49:25 -05:00
johnnyq
5818c7fe18 feat. Added Contact Roles to Bulk Actions 2024-01-31 14:23:47 -05:00
johnnyq
dad2a7d376 Update Contact Department wording to also include group changed icon from building to users which is more suitable 2024-01-31 13:56:00 -05:00
johnnyq
00197cef96 feat: Bulk Set Contact Department / Group 2024-01-31 13:53:25 -05:00
johnnyq
da98f84774 Move the MailQueue Action out of the get email loop on close Bulk Tickets this prevent unessessary mysql connections 2024-01-30 16:55:04 -05:00
johnnyq
e524f1ce7c Fix issue with adding slashes to close email config_from_name vars 2024-01-30 16:40:19 -05:00
johnnyq
80fdad81e9 Fix Not being able to Enable Stripe Pay on Updated or new Installs 2024-01-30 16:25:27 -05:00
johnnyq
731b60b07a Feature: Added Bulk Ticket Closure 2024-01-30 16:04:29 -05:00
johnnyq
c6f1a25692 Feature: Added Bulk Set Priority on Tickets 2024-01-30 14:54:00 -05:00
johnnyq
db8ae13135 Feature: Add Bulk Move Folder Action to Client Documents and Files 2024-01-30 14:11:29 -05:00
johnnyq
ff1616de94 Updated Guest Invoice logic so if they payed gateway fee is not shown 2024-01-29 21:56:13 -05:00
johnnyq
e82ba786a5 Added One more code piece from Pull #866 to fix Gateway Fees shown and to fix balance on guest view invoice 2024-01-29 21:17:12 -05:00
johnnyq
007d07d417 Added unbilled ticket wording per Pull Req #866 2024-01-28 15:57:27 -05:00
johnnyq
f8dc67fbf9 Added Gateway Fee to the Guest View Invoice and minor fix for ticket counter per Pull Request #866 also added stripe flat and percent config vars to guest view invoice. Note We do not need to merge Pull #866 as all changes nessessary have been implented manually 2024-01-28 15:55:05 -05:00
johnnyq
5afacf78cf Convert strip Percentage Decimal from decimal vlaue to percentage value on view form and then reconvert from Percent back to Decimal value on POST 2024-01-28 15:23:58 -05:00
johnnyq
9bd924dc67 Only create a Stripe Expense if client pays fee is off, a stripe expense vendor and expense category is selected in settings 2024-01-28 14:54:28 -05:00
johnnyq
063d042378 Update guest_ajax.php with the new stripe vars 2024-01-28 14:45:43 -05:00
johnnyq
56c138fb12 cleanup 2024-01-28 02:08:11 -05:00
johnnyq
3d3bb6a436 Feature: Stripe Payment now logs an expense to the selected account 2024-01-28 01:49:49 -05:00
johnnyq
b986f04a0c Add More Configurable variabled for Stripe including such as Flat Rate and Percent Fees, expense vendor and expense category update guest stripe pay to take advantage of these vars and updated settings 2024-01-28 00:00:28 -05:00
johnnyq
777637277b Fix Issue where if you edited first record that shared the same form input name like location then it would blank out the first record if edited this is fixed by adding bulk_ in front of the form Input names under the bulk modals not sure why this happens but this is the fix 2024-01-27 14:15:18 -05:00
johnnyq
c711db937d Updated Edit Location logic in contacts added Pop Over Title for archived Items in assets and contacts 2024-01-27 14:01:10 -05:00
johnnyq
50b00c5712 Feature: Bulk Edit Contact Phone Number useful where the share an Office Number but have seperate extensions 2024-01-27 13:45:11 -05:00
johnnyq
8b85ae377a Updated the way Archived Items are displayed in asset list view and when editing, this will be standard going forward, added Bulk Set Asset Status, further work on improving the archived logic, assets is pretty much gold standard here now 2024-01-27 13:23:44 -05:00
johnnyq
d8de41d937 Do Not show archived items when copying asset 2024-01-27 11:59:05 -05:00
johnnyq
36e9f8cd3d Add Red X next to Assigned to for Archived Users still palying with this design maybe just make the user text red with a pop over that says archived when hovered 2024-01-27 03:44:32 -05:00
johnnyq
0b7b7e298a Remove unessesary () 2024-01-27 03:35:22 -05:00
johnnyq
d3153a29cb Asset Assignment Do not show all archived users from the date the asset is created instead if an asset has an archive user show that user and all new users 2024-01-27 03:32:30 -05:00
johnnyq
9184fa3ab3 Fix Copy IP to clipboard in Assets missing clipboardjs class 2024-01-27 03:10:54 -05:00
johnnyq
8562906fa6 Prevent Copy to Clipboard button from submitting in assets since we wrapped listings in a form to allow for bulk actions this caused buttons like this to act as submits unless we add type='button' 2024-01-27 03:04:43 -05:00
johnnyq
e139190377 UI: Set IP Column to Text no wrap to prevent the Copy IP Button from wrapping 2024-01-27 02:55:06 -05:00
johnnyq
fe33cfa4e9 UI: Fix the client top head city state postal below the address from being offset by using a font awesome dummy icon 2024-01-27 02:48:31 -05:00
johnnyq
3c28c2b89b Prevent Password Manager from asking to save password for every asset edit / add / bulk submit 2024-01-27 02:16:41 -05:00
johnnyq
7e50634c07 Added Bulk Assign contacts to Assets 2024-01-27 01:56:10 -05:00
johnnyq
1deba6eac5 Added Bulk Assign Location to Assets 2024-01-27 01:41:25 -05:00
johnnyq
ee3087725d Rename inconsistent multi Actions to Bulk Actions 2024-01-27 01:03:18 -05:00
johnnyq
f2719a612e Feature: Bulk Action - Assign Location for contacts 2024-01-26 23:59:24 -05:00
johnnyq
dec2f484ab added - between App Name and Task for ticket assignment email 2024-01-26 22:57:41 -05:00
johnnyq
a197151286 Update email wording on tech notify of assigned tickets 2024-01-26 22:35:40 -05:00
johnnyq
d7a58c01f9 Update bulk assign tech to only notify by one email with all tickets assigned instead of multiple same with notification, updated some wording as well and include a ticket count in the logging email and notification 2024-01-26 22:30:55 -05:00
johnnyq
47d2ad993e Don't show checkboxes next to closed tickets 2024-01-26 21:44:03 -05:00
johnnyq
6dbbb232ed Update Bulk Ticket assign action: Updated button, not notifies newly assigned tech via email and in app notification and now logs properly 2024-01-26 20:21:55 -05:00
johnnyq
fd48d991d9 Feature: Ticket Bulk Actions Assign Tech has been added, still work in progress, update ticket reply added tech notification add logging, do not allow to assign ticket on closed ticket and more refinements 2024-01-26 17:12:57 -05:00
johnnyq
937397e9c0 Allow .vsdx and .drawio diagram files to be uploaded via client files 2024-01-25 12:01:09 -05:00
johnnyq
9ce280d80d Fix Redirect to non-existent page after login when force MFA is enabled 2024-01-24 15:46:30 -05:00
wrongecho
861c8e4252 Merge pull request #873 from braadaaay/master
Spelling corrections in Web UI
2024-01-24 06:23:47 +00:00
Brady Williams
b854e9569b Remove extra "you" in dialog 2024-01-24 17:58:54 +13:00
Brady Williams
07c126db2b Fix Spelling from "wather" to "watcher" 2024-01-24 17:57:05 +13:00
johnnyq
4b6495b01a UI Update for Asset Listing, combined columns to allow for a better display 2024-01-23 16:44:30 -05:00
Johnny
981010b2f7 Merge pull request #871 from wrongecho/logins_js_cleanup
Logins JS Cleanup
2024-01-22 16:37:20 -05:00
Marcus Hill
ba0917e142 Logins JS Cleanup
- Remove old JS
- Standardize generate password JS style to match existing
- Move JS functions to own files
2024-01-22 21:25:21 +00:00
wrongecho
4e0c7230f3 Update README.md
Reword read me contribution section to emphasize proposing features on forum first
2024-01-22 20:47:21 +00:00
johnnyq
9e8c3ed2fd Fix Redirect Link in Stripe Pay 2024-01-22 12:27:47 -05:00
johnnyq
8d2a9bbf60 Fix Broke Guest Pay Invoice via Stripe removed additional ) 2024-01-22 12:17:06 -05:00
johnnyq
ad1ec7d338 Allow to set an optional queue time in bulk mail, update cron_mail_queue.php to only send mail after its queued_at date and time 2024-01-21 15:52:15 -05:00
johnnyq
62fb73875b Updated addToMailQueue Function to allow specifing an optional queue time to schedule outbound mail 2024-01-21 15:27:15 -05:00
johnnyq
9db7947004 Bulk Mail: Make contacts select table responsive 2024-01-21 14:34:45 -05:00
johnnyq
2ee21c3f9a Bulkmail: Use default mail from email and mail from name but still can be changed 2024-01-21 14:25:56 -05:00
johnnyq
782b0cfd96 Bulk Mail: Show dash if title is blank 2024-01-21 14:22:18 -05:00
johnnyq
a8872ae804 Bulk Mail: Don't show contacts that have no email address 2024-01-21 14:18:55 -05:00
johnnyq
413645154d Feature: Add initial basic Bulk Mail Sending capabilities via client section 2024-01-21 14:15:10 -05:00
johnnyq
0ca50bf6de Switch from ~ to -- in signature footer 2024-01-21 00:27:01 -05:00
johnnyq
cb1b6e4231 Fix client portal reset password 2024-01-20 23:37:12 -05:00
johnnyq
bd8c93cb71 Update client portal login reset for the new mail function and made some minor UI / Code changes 2024-01-20 23:28:00 -05:00
johnnyq
623ed33a27 Update Portal UI elements and Mail Functions 2024-01-20 23:11:35 -05:00
johnnyq
3b71e6132e Change Respond icon from check mark to a paper plane in ticket view 2024-01-20 22:08:41 -05:00
johnnyq
493c83e3f1 Added Days over due by to invoice reminders 2024-01-20 21:44:58 -05:00
johnnyq
d390bee0bc Update/Fix Mail Functions in cron.php - sanitize POST vars instead the whole mail subject and body which prevents having a mixed of confusing redundant escaped and unescaped vars 2024-01-20 21:16:28 -05:00
johnnyq
c801e58cc9 Removed redundent get stripe client pays fee as the var is already aquired in beginning 2024-01-20 20:58:53 -05:00
johnnyq
b1fd0fb4aa fixed 2024-01-20 20:56:00 -05:00
johnnyq
00d4f7d66f moved config_stripe_client_pays_fees out of an unnessesary function and moved it to the setup stripe section 2024-01-20 20:54:56 -05:00
johnnyq
3c3e0f5f80 Cleaned up guest_pay_invoice_stripe.php incorrect DB Handling for vars was HTML encoding instead of proper SQL escaping 2024-01-20 20:49:37 -05:00
johnnyq
0cdf49f69a Update/Fix Mail Functions in POST/user.php and ajax.php - sanitize POST vars instead the whole mail subject and body which prevents having a mixed of confusing redundant escaped and unescaped vars 2024-01-20 20:31:46 -05:00
johnnyq
63d4419ff5 Update/Fix Mail Functions in POST/quote.php - sanitize POST vars instead the whole mail subject and body which prevents having a mixed of confusing redundant escaped and unescaped vars also 2024-01-20 20:10:33 -05:00
johnnyq
1479caa8e8 Set Textarea rows from 4 to 5 2024-01-20 19:26:00 -05:00
johnnyq
9d60ccdf3e Updated UI on add/Edit Calendar events 2024-01-20 19:25:15 -05:00
johnnyq
92ccd7de14 Update/Fix Mail Functions in POST/contact.php and event.php - sanitize POST vars instead the whole mail subject and body which prevents having a mixed of confusing redundant escaped and unescaped vars also fixed scheduling calendar events was not working to send an email out 2024-01-20 19:08:51 -05:00
johnnyq
91eff8f9b6 no need to SQL escape , in the emails, so removed the \, escaping in post invoice, ticket and ticket_email_parser 2024-01-20 18:13:47 -05:00
johnnyq
a46e41ce9c Update/Fix Mail Functions in POST/invoice.php - sanitize POST vars instead the whole mail subject and body which prevents having a mixed of confusing redundant escaped and unescaped vars 2024-01-20 17:58:54 -05:00
johnnyq
d3aa2e7239 Only allow A-Za-z- for Ticket Prefix 2024-01-20 16:45:39 -05:00
johnnyq
31d6605647 Updated Closed Ticket Email as well 2024-01-20 15:15:49 -05:00
johnnyq
0a32415b38 Updated ticket mail parser to not escape the entire subject and body of sending emails as this is all done by vars instead 2024-01-20 15:11:07 -05:00
johnnyq
669d2f74ed Update Ticket POST Email body to Use -- instead of ~ for closing signature 2024-01-20 13:49:27 -05:00
johnnyq
5f3b08a543 Fix Mail Array causing duplicate sending 2024-01-20 13:33:54 -05:00
johnnyq
b942bf0e18 Update/Fix Mail Functions in POST/ticket.php - sanitize POST vars instead the whole mail subject and body which prevents having a mixed of confusing redundant escaped and unescaped vars, also fixed watchers where if a watcher was added it would just emai the last watcher selected and skip the main contact and any other watchers selected 2024-01-20 13:18:17 -05:00
johnnyq
a656340c8b Fix mis-spelling sanitize not santize 2024-01-19 19:37:34 -05:00
johnnyq
79175b9e70 Sanitize Ticket Prefix and From Name in Cron Ticket Email Parser 2024-01-19 19:18:26 -05:00
Johnny
d282083f0a Merge pull request #868 from wrongecho/user_profile_fixes
User profile fixes
2024-01-19 19:08:18 -05:00
johnnyq
2f3e26b285 Fix Ticket Settings 2024-01-19 19:01:26 -05:00
Marcus Hill
1fcf559e13 Prevent users setting/hashing an empty password 2024-01-19 23:45:02 +00:00
Marcus Hill
ee68bf10b8 Don't require admin role to edit user profiles (otherwise techs/accountants can't edit their page) 2024-01-19 23:39:15 +00:00
johnnyq
56d0188ccb Fix Oppps 2024-01-19 17:56:04 -05:00
johnnyq
289031b691 Updated Cron Mail Queuer - Removed HTMLPurify and HTML Encoding using HTMLEntities as these are unnessaery and were cuasing extra cpu load and possible data corruption and are passed off to PHPMailer which handles this by default plus recipient email clients should handle XSS as well 2024-01-19 17:39:28 -05:00
johnnyq
9559c11c25 Cleaned up the initial create ticket email, removed customization for now, added some better comments to cron mailer etc 2024-01-19 17:28:17 -05:00
johnnyq
6af48594f6 Added Scheduled Ticket Count 2024-01-19 13:14:57 -05:00
johnnyq
d0dd43bef9 Fixed issue with email failing to send on password updates and email name changes was using the old formatting for the legacy way of sending emails out 2024-01-19 10:31:09 -05:00
o-psi
1ffdce6bbc Add unbilled tickets to dashboard if tickets and accounting is on
otherwise, show recurring invoices.
2024-01-18 22:49:18 +00:00
o-psi
53ad94cc06 Update Database to match 2024-01-18 22:48:20 +00:00
o-psi
13cf4df473 Scheduled Tickets 2024-01-18 19:50:01 +00:00
johnnyq
9bd28b1c56 Update Mail Send Test to use the proper from name when sending a test also show the from name from the select 2024-01-16 22:56:35 -05:00
johnnyq
e07fb9ce50 Expanded timeAgo function to incoude time ahead, added this functionality to client overview 2024-01-15 22:59:39 -05:00
johnnyq
b5e67eb3f6 Add Contact Types to Contact Details Cleanup code in asset details and contact details 2024-01-15 22:18:55 -05:00
johnnyq
cd732b4dd6 Do not allow the deletion of Parent document under revisions, create new function to delete document version and redirect back to the parent document, also delete all versions of the document if deleted from the document list 2024-01-15 21:44:13 -05:00
johnnyq
483bf4bcfd Added more informative notes placeholder for contact as well 2024-01-15 20:06:25 -05:00
johnnyq
73ebfcc233 Made Location notes placeholder offer some better examples like parking and building access then just enter some notes 2024-01-15 19:58:02 -05:00
johnnyq
a113b1390c Allow more space for quick notes 2024-01-15 15:13:03 -05:00
johnnyq
9f1f88b64e Updated breadcrumbs in Asset Details to include clients 2024-01-15 15:10:20 -05:00
johnnyq
717b63855e Updated some icons fr asset details 2024-01-15 15:06:44 -05:00
johnnyq
a11de364c8 Show correct Contact Details when on Asset Details 2024-01-15 14:56:59 -05:00
johnnyq
b1d1e39ab1 Forgot to add contact name under assigned in asset details 2024-01-15 14:44:35 -05:00
johnnyq
53b9d0a5ad Asset Details UI Use card Header for Asset name and description and use just icon for edit 2024-01-15 14:41:35 -05:00
johnnyq
9cd570b603 Updated Asset Details Page to include all the asset values 2024-01-15 14:34:41 -05:00
johnnyq
50002b0783 Added login uri 2, NAT IP and asset URI 2 to the UI, also created new tab in asset network and split form items between assignment and network 2024-01-15 13:50:46 -05:00
johnnyq
d35f1ff7fd Increased the character limit for login uris, added login uri 2 and asset nat ip currently not exposed on the ui 2024-01-15 13:08:46 -05:00
johnnyq
365c790600 Set column width of stales tickets to 4 2024-01-14 22:24:30 -05:00
johnnyq
b7fa80503f Moved Recent Client Activities to the bottom of client overview 2024-01-14 22:22:11 -05:00
johnnyq
62d5adfa9d Added asset location to the client PDF Export 2024-01-14 21:42:39 -05:00
johnnyq
d9a99b8d93 Increase the Asset URI limit from 250 to 500 and added asset URI 2 field for additional Asset URIs 2024-01-14 14:09:15 -05:00
johnnyq
9c5c501f04 Moved Browser Extension specific setting to user prefs 2024-01-13 17:16:21 -05:00
johnnyq
813e8c7e59 Renamed Profile to Account, Added a user Side nav to seperate various user preference entities 2024-01-13 17:15:20 -05:00
johnnyq
b2ad67e26d readed back ticket timer at the top as it broke the counter 2024-01-12 18:41:32 -05:00
johnnyq
625a6cac6c Included WebKlex PHP-IMAP Library in plugins folder to allow for future use when we convert IMAP to allow OAUTH2 2024-01-11 12:51:11 -05:00
johnnyq
9520148d4d Set batch payment button to color default 2024-01-11 12:10:25 -05:00
johnnyq
d25396f19a Rename rec back to recurring on the client side nav 2024-01-11 11:44:00 -05:00
johnnyq
3bb2986c4c Rename rec back to recurring on the side nav 2024-01-11 11:43:05 -05:00
johnnyq
65b73f4120 Fix Force Recurring Invoice updated more delete alerts to be red instead of green 2024-01-11 11:30:23 -05:00
johnnyq
d33d11acd2 Set lock file cront ticket email parser once again from 300 sec aka 5 mins to 180 secs aka 3 mins 2024-01-11 00:34:36 -05:00
johnnyq
a38e62c412 Set lock file cront ticket email parser from 600 sec aka 10 mins to 300 secs aa 5 mins, update telemetry to include website 2024-01-11 00:32:31 -05:00
Johnny
e69317e376 Merge pull request #865 from twetech/v0.1.5
Update to V0.1.5
2024-01-10 21:22:42 -05:00
Andrew Malsbury
b499b52f49 Merge pull request #14 from twetech:unbilled-tickets-report
Adjust filter to only show unbilled
2024-01-10 17:06:52 -06:00
o-psi
3ea326b0ac Adjust filter to only show unbilled 2024-01-10 23:05:42 +00:00
Andrew Malsbury
e30c0a14e5 Merge pull request #13 from twetech:unbilled-tickets-report
Fix increment bug in ticket_unbilled_count
2024-01-10 17:02:20 -06:00
o-psi
691a1bc019 Old Python Habits Die Hard (i++) 2024-01-10 23:01:34 +00:00
Andrew Malsbury
1afc9751e7 Merge branch 'itflow-org:master' into v0.1.5 2024-01-10 16:57:03 -06:00
Andrew Malsbury
aa2b471e0f Merge pull request #12 from twetech:unbilled-tickets-report
Add Unbilled Tickets Report
2024-01-10 16:42:41 -06:00
o-psi
234d5dde09 Remove Creepy smiley 2024-01-10 22:41:48 +00:00
johnnyq
f8757fc2e0 Added back Yearly option under edit Recurring Invoice 2024-01-10 17:41:38 -05:00
o-psi
d7e8e60693 Update message for no tickets. 2024-01-10 22:40:51 +00:00
o-psi
9a649529d2 Refactoring for better readability 2024-01-10 22:33:24 +00:00
o-psi
e1cb9655d7 Add notice if there are no unbilled tickets. 2024-01-10 22:32:21 +00:00
o-psi
d6454427bb Validate Access to unbilled report. 2024-01-10 22:26:56 +00:00
o-psi
59cf07bf49 Update filter to allow for closed and open when looking for unbilled. 2024-01-10 22:23:29 +00:00
o-psi
87f1b9c0be Add filter to Client Tickets 2024-01-10 22:16:40 +00:00
o-psi
b764506f28 Fix bug in client_tickets.php 2024-01-10 22:15:00 +00:00
o-psi
a7ee5737af Add link to tickets screen on unbilled report 2024-01-10 22:12:46 +00:00
o-psi
77d115d1f2 Update report to not have modal. Too many steps for UI. 2024-01-10 22:06:19 +00:00
o-psi
c7c6b08a11 Add Basic Unbilled tickets report 2024-01-10 21:54:43 +00:00
Andrew Malsbury
6bde67f9ad Merge branch 'itflow-org:master' into v0.1.5 2024-01-10 15:38:24 -06:00
Andrew Malsbury
ac405e1eec Merge pull request #11 from twetech:Invoice-add-ticket-modal-update
Improve invoice add ticket modal UI
2024-01-10 15:31:48 -06:00
o-psi
8dad54e450 Update badge color based on status. 2024-01-10 21:25:22 +00:00
o-psi
25c26cc2a6 Fix striped Table 2024-01-10 21:15:25 +00:00
o-psi
6ca277a636 Make table striped 2024-01-10 21:15:12 +00:00
o-psi
cf87a232c4 Invoice add ticket modal UI improvements. 2024-01-10 21:12:23 +00:00
o-psi
945eb7c87a Add Label to add column on invoice add ticket modal 2024-01-10 21:09:07 +00:00
o-psi
4ed2c7923c Change add button to a plus icon 2024-01-10 21:01:56 +00:00
o-psi
e5f8921322 Invoice add ticket modal UI Fix 2024-01-10 20:59:52 +00:00
o-psi
c24aece046 Fix Parenthesis 2024-01-10 20:56:31 +00:00
o-psi
39ba7d83fd Add ticket status to invoice filter. 2024-01-10 20:45:18 +00:00
johnnyq
29be864675 Removed Re: from ticket replies as this is reserved if following an email thread changed back to Ticket update instead 2024-01-10 13:31:56 -05:00
johnnyq
b7894ffd58 Add Missing Send Recurring Invoice Notification Email 2024-01-09 11:58:22 -05:00
johnnyq
02ed6986ec Fix Assets page not loading missing closer } 2024-01-07 12:43:28 -05:00
johnnyq
efdffa1a74 Forgot to do a DB Dump after DB Update well here it is 2024-01-06 16:07:37 -05:00
johnnyq
0948fd4dc6 Added a setting to enable destructive delete, disabled by default must enable it in the DB for now not in the settings DB 1.0.0 has been reached 2024-01-06 16:05:28 -05:00
johnnyq
e260cbf626 Scaled down the action menu under assets to fit the actions for 1 row displays 2024-01-06 15:34:59 -05:00
johnnyq
56d7772e26 Remove Delete option from asset action menu as delete is too destructive, functionality is still there in POST and Allow Tech to Archive Assets as well 2024-01-06 14:31:24 -05:00
johnnyq
6d4584be90 Remove Asset Tickets Modal, Related Documents and Files as this can be viewed in Asset Details Page 2024-01-06 14:27:21 -05:00
johnnyq
1ae6a8d757 Update Collections Report for Round Down to the nearest for Monthes behind and other formatting fixes) 2024-01-06 13:57:55 -05:00
johnnyq
5914996c41 Add Company Website to Guest Sharing footer 2024-01-04 18:39:19 -05:00
johnnyq
74abe28c33 Fix Archiving Ticket Replies 2024-01-03 18:33:09 -05:00
johnnyq
6c9fa7a607 Fix the ticket reponse count to not count archived replies 2024-01-03 18:29:32 -05:00
johnnyq
5c5871ba0d Merge branch 'master' of github.com:itflow-org/itflow 2024-01-03 18:25:42 -05:00
johnnyq
d8edf339c4 Clean up Ticket Printing: When printing a ticket do not show interactive elements 2024-01-03 18:23:39 -05:00
wrongecho
051ce46d37 Update README.md - clarify install and release date 2023-12-31 20:28:48 +00:00
wrongecho
48f0531643 Merge pull request #851 from wrongecho/bugfix-inv-quo-quantity-math
Bugfix: Quote/Invoice quantity 4 digits
2023-12-31 20:09:13 +00:00
Marcus Hill
ef2a33403b Bugfix: Quote/Invoice quantity 4 digits
Perform quote/invoice quantity number formatting after invoice sub-total is calculated to prevent math issues due to comma added for thousands
2023-12-31 20:00:01 +00:00
Johnny
622811302f Merge pull request #850 from wrongecho/notes
Add notes field & multi-select to networks/certs/domains
2023-12-31 12:43:40 -05:00
Marcus Hill
55d716642a Bugfix 2023-12-31 13:02:37 +00:00
Marcus Hill
1b567ee253 Add multi-select to networks, certificates and domains.
Fix multi-select count bug
2023-12-31 12:49:58 +00:00
Marcus Hill
9076012d2a Bugfix Undefined variable: service_created_at 2023-12-31 12:25:12 +00:00
Marcus Hill
224aa00694 Correct comments 2023-12-31 12:05:25 +00:00
Marcus Hill
78f79759dc Correct comments 2023-12-31 12:05:11 +00:00
Marcus Hill
756c3aa7ca Tidy for consistency 2023-12-31 11:20:43 +00:00
Marcus Hill
86b31ada1f Add notes to certs 2023-12-31 11:13:57 +00:00
Marcus Hill
d3b59edfe4 Add notes to domains 2023-12-31 11:13:48 +00:00
Marcus Hill
1a1b4ee810 Add notes to networks; move networks js to its own file 2023-12-31 11:13:24 +00:00
Marcus Hill
114a72424c Add domain_notes database field 2023-12-31 10:34:01 +00:00
johnnyq
938f8bb4ae Wording change on Client Address to Location 2023-12-29 17:27:29 -05:00
johnnyq
3c53caf964 UI: Fix Padding and margin Account Types Header, also send telemetry if config_telemetry detailed in selected 2023-12-29 17:21:03 -05:00
johnnyq
ed42ec9707 By default Collapse Client Top Header unless in Client Overview while in the Client section 2023-12-29 15:14:48 -05:00
Johnny
1a130ac2ab Merge pull request #849 from twetech/v0.1.4
V0.1.4
2023-12-29 14:19:13 -05:00
Johnny
815ef3da6e Merge pull request #848 from twetech/v0.1.3
v0.1.3 (no edits compared to main)
2023-12-29 14:17:19 -05:00
Andrew Malsbury
31dc8965df Merge pull request #10 from twetech:Fix-Guest-View-Partial-Invoices
Fix SQL query in invoices.php
2023-12-29 13:12:15 -06:00
o-psi
35394f3e6f Fix SQL query in invoices.php 2023-12-29 19:11:51 +00:00
o-psi
e7628ad5a6 Fix SQL query in invoices.php 2023-12-29 19:07:22 +00:00
Andrew Malsbury
ae3c52074f Merge branch 'itflow-org:master' into v0.1.4 2023-12-29 13:06:49 -06:00
johnnyq
b2dc9a123c Do not allow archived client contacts to reset their passwords 2023-12-28 22:25:57 -05:00
johnnyq
c4e4dc3a44 Do not allow archived client contacts client portal login access 2023-12-28 22:18:39 -05:00
johnnyq
7c12a716a4 When Archiving a contact remove Important, Billing and Technical Roles along with Blanking out Auth and Hashed Password 2023-12-28 22:14:45 -05:00
johnnyq
e38aad1e61 User Profile UI Spruce up / Cleanup 2023-12-28 20:45:28 -05:00
johnnyq
456545fb62 Settings Formating 2023-12-28 20:23:28 -05:00
johnnyq
bcd0eb69a1 Send Telemetry if is greater than 0 2023-12-28 20:03:08 -05:00
johnnyq
7759f54260 renamed settings alerts to notifications and reworked the notification UI to allow for future growth 2023-12-28 19:52:24 -05:00
Andrew Malsbury
d953540440 Merge pull request #9 from twetech:fix-drafts-on-ticket-invoice
adjust visuals when invoicing tickets.
2023-12-28 16:56:20 -06:00
o-psi
da42f35ff9 adjust visuals when invoicing tickets. 2023-12-28 22:55:43 +00:00
Andrew Malsbury
ae444142c6 Merge pull request #8 from twetech/ticket-add-to-invoice-drafts
Ticket add to invoice drafts
2023-12-28 16:32:28 -06:00
johnnyq
db4fd095d6 Fix Undefined Checkbox POST vars in settings ticket 2023-12-28 14:42:11 -05:00
johnnyq
6d769a5e05 When choosing to share Data via Setup make sure telemetry gets enabled after setup 2023-12-28 14:13:26 -05:00
johnnyq
deb84cc2a8 set Placeholder for Global search from just search to search everywhere 2023-12-28 13:43:24 -05:00
johnnyq
bc9ad24c76 Added badge color light blue 2023-12-27 22:44:24 -05:00
johnnyq
c30d9b4bdf Added theme light blue 2023-12-27 22:43:51 -05:00
johnnyq
4a5b0b9202 Remove Themes, lime dark-gray and light as their text was not very readable 2023-12-27 22:37:47 -05:00
johnnyq
58c7dfe2c8 Fix Client Self Service Password Reset due to new mail queue system change 2023-12-27 22:06:19 -05:00
johnnyq
a966fc9395 Fix Add and Editing Contact passwords because of a commit that change the post name from contact_password to password 2023-12-27 21:51:12 -05:00
johnnyq
c9e92cb3bb Cleaned up cron ticket parser to work better with the new mail queuer 2023-12-27 20:35:23 -05:00
johnnyq
ff5e5f950b Removed unused edit ticket watcher, we handle this differently 2023-12-27 17:47:05 -05:00
johnnyq
d6a7747935 Add Watcher via select of client contacts and can enter manual emails as well 2023-12-27 17:44:17 -05:00
johnnyq
a9dfc0d5fe Add the ability to delete a ticket watcher 2023-12-27 17:21:17 -05:00
johnnyq
a9d49c9785 Spurced up ticket Attachments view in ticket details 2023-12-27 17:02:04 -05:00
johnnyq
51a5b7d79a Moved notification badge number over 3 to allow for 3 numbers without overlapping the bell 2023-12-27 16:36:41 -05:00
johnnyq
220d565544 Commented out open ticket as its still Work IN Progress and not ready for stable 2023-12-27 16:27:42 -05:00
johnnyq
c8b51b01d3 Fix for Scheduled Ticket Umlauts 2023-12-27 16:16:52 -05:00
johnnyq
0fad6727dc Fix missing ; 2023-12-27 15:35:11 -05:00
johnnyq
51754be319 Santized Pre Vars in Cron and remove dup santized code as the new mail queue system now requires input sanitzation 2023-12-27 15:24:38 -05:00
Andrew Malsbury
8a4075a4cd Merge branch 'itflow-org:master' into v0.1.3 2023-12-27 13:27:39 -06:00
Andrew Malsbury
c4bfb314a2 Merge branch 'master' into ticket-add-to-invoice-drafts 2023-12-27 11:29:42 -06:00
Johnny
4e5bc814d5 Merge pull request #846 from wrongecho/contact-api-via-num
Contacts API
2023-12-26 17:46:48 -05:00
johnnyq
52a4963b83 Fix Edit Contact Do not make the contact Password field required as it will not allow to submit form, instead this is handled in POST if the password field is blank then dont create a password 2023-12-26 17:36:54 -05:00
Andrew Malsbury
4689faf518 Merge branch 'itflow-org:master' into v0.1.3 2023-12-26 09:17:05 -06:00
Marcus Hill
f45a5e0b51 Contacts API
Allow looking up contacts via mobile / phone number
2023-12-24 20:05:04 +00:00
Johnny
fa452dbf02 Merge pull request #845 from wrongecho/ticket-tt-gui
Time tracking input field spacing
2023-12-24 00:42:08 -05:00
Marcus Hill
bdb0cc1e38 Time tracking input field spacing
Reduce size of hrs, min, sec input fields
2023-12-23 23:41:51 +00:00
Marcus Hill
e04c681ca5 Time tracking input field spacing
Reduce size of hrs, min, sec input fields
2023-12-23 23:15:20 +00:00
Johnny
29867d6d11 Merge pull request #844 from twetech/delete-tickets-go-to-tickets.php
Redirect to tickets.php after deleting a ticket
2023-12-23 16:07:46 -05:00
Johnny
25087dd85f Merge pull request #843 from twetech/v0.1.2
Update to v0.1.2 of TWETech/ITflow
2023-12-23 16:06:29 -05:00
Andrew Malsbury
16f3cef0f4 Merge pull request #7 from twetech/delete-tickets-go-to-tickets.php
Redirect to tickets.php after deleting a ticket instead of the delete…
2023-12-22 17:22:46 -06:00
o-psi
5ef96f7860 Redirect to tickets.php after deleting a ticket instead of the deleted tickets' page. 2023-12-22 23:20:21 +00:00
Andrew Malsbury
7ecabbaf0d Merge pull request #6 from twetech/ticket-billable-module
Fix typo in accounting module condition
2023-12-22 11:57:43 -06:00
o-psi
5dda94a1ec Fix typo in accounting module condition 2023-12-22 17:45:39 +00:00
Andrew Malsbury
d448562a24 Merge branch 'itflow-org:master' into v0.1.2 2023-12-22 11:34:05 -06:00
Johnny
471e6a9f8f Merge pull request #842 from twetech/ticket-billable-module
Disable ticket billable options in accounting module
2023-12-22 12:33:18 -05:00
Johnny
27b7db63ee Merge pull request #839 from twetech/Create-Payment-Bugfix
Fix email data assignment and select option bug in invoice.php and ticket_invoice_add_modal.php
2023-12-22 12:32:27 -05:00
Andrew Malsbury
0077a03be7 Merge pull request #5 from twetech/Readable-Passwords
Readable passwords
2023-12-22 11:32:09 -06:00
Andrew Malsbury
10b04c79d0 Merge branch 'v0.1.2' into Readable-Passwords 2023-12-22 11:31:36 -06:00
Andrew Malsbury
c8d3f3df69 Merge pull request #4 from twetech/client-replied-warning-badge
Added autoclose to dark
2023-12-22 11:21:41 -06:00
o-psi
77145432ee Added autoclose to dark 2023-12-22 17:19:00 +00:00
Andrew Malsbury
6bceb4b33b Merge pull request #3 from twetech:client-replied-warning-badge
Add ticket status color for "Client-Replied"
2023-12-22 11:17:08 -06:00
o-psi
0535a903ee Add ticket status color for "Client-Replied" 2023-12-22 17:16:26 +00:00
Andrew Malsbury
fc5507272e Merge pull request #2 from twetech/Fix-for-user-IDs-in-tickets
Fix ticket assignment filter bug
2023-12-22 11:09:33 -06:00
o-psi
61a0086514 Fix ticket assignment filter bug 2023-12-22 17:06:48 +00:00
Andrew Malsbury
a6d43d97af Merge pull request #1 from twetech/Fix-for-user-IDs-in-tickets
Fix ticket_assigned_to filter in SQL query
2023-12-22 10:50:11 -06:00
o-psi
eb29f74fab fix error messages in log 2023-12-22 16:25:36 +00:00
o-psi
7709627e5b Accounting module disable ticket billable options 2023-12-22 16:19:51 +00:00
o-psi
17217019d1 Fix typo in variable name and add condition for invoice status 2023-12-22 15:19:00 +00:00
o-psi
dd7131cae1 Fix ticket_assigned_to filter in SQL query 2023-12-22 15:14:56 +00:00
o-psi
87e8f9e042 Fix email data assignment and select option bug in invoice.php and ticket_invoice_add_modal.php 2023-12-22 14:52:02 +00:00
johnnyq
f8702557c8 Remove Trailing slash for config_base_url during setup 2023-12-21 19:18:45 -05:00
johnnyq
da73b6d634 Fixed Client Pays fee not being able to be turned off 2023-12-21 19:13:14 -05:00
johnnyq
11da9ff0d4 Fix Undefined Status Array errors in tickets 2023-12-21 18:59:57 -05:00
johnnyq
435206dded Properly fetch the user dashboard settings 2023-12-21 16:56:02 -05:00
johnnyq
297148bc63 DB Update add User settings to enable / disable Dashboard Items Financial and Technical 2023-12-21 16:36:31 -05:00
johnnyq
d21e5fafca Added Your Tickets to the technical portion of the dashboard 2023-12-21 16:04:07 -05:00
johnnyq
12b8f2e005 Update Year select 2023-12-21 14:20:39 -05:00
johnnyq
5138f84575 Removed financial and technical dashboards in settings default page as these are no merged 2023-12-21 14:05:41 -05:00
johnnyq
6a63335a4a Bump PHPMailer from 6.8.1 to 6.9.1 2023-12-21 13:23:44 -05:00
johnnyq
19a18126de Bump TinyMCE from 6.7.3 to 6.8.2 2023-12-21 13:19:16 -05:00
Johnny
a1be7f2a3c Merge pull request #837 from twetech/Billable-ticket-qol
Quality of Life - Billable Tickets
2023-12-21 13:10:11 -05:00
johnnyq
afc6dd674c Add some more padding and spacing for toggles and Year Select on the dashboard 2023-12-21 13:07:20 -05:00
johnnyq
e639b69db9 Merged All Dashboards into 1 allow you to toggle between show financial and show technical 2023-12-21 13:03:37 -05:00
o-psi
3eaaf73744 Add more billable status functionality 2023-12-21 17:10:15 +00:00
o-psi
f1516b06ee Refactor calculateInvoiceBalance function to sanitizr
This commit refactors the calculateInvoiceBalance function in functions.php. The invoice_id parameter is now properly sanitized using intval() to prevent SQL injection attacks. Additionally, the SQL query for retrieving the invoice and payments data has been formatted for better readability.
2023-12-21 14:37:19 +00:00
johnnyq
70d99d28bf Removed Unused var 2023-12-21 02:40:41 -05:00
johnnyq
08a6d1d9be Update in more places 2023-12-21 02:10:09 -05:00
johnnyq
d6660bff04 Fix sending mail on item sharing 2023-12-21 02:02:40 -05:00
johnnyq
957bbc5f55 Update from name and email in other areas as well 2023-12-21 01:47:24 -05:00
johnnyq
e8a53cbd6a Update new mail queue function to use the proper mail from name and mail from email 2023-12-21 01:37:21 -05:00
johnnyq
cdaca0e06b Update a few var names for the new mail addToMailQueue function 2023-12-21 01:05:59 -05:00
Johnny
a35a6f3ea0 Merge pull request #835 from twetech/ticket_notifications
Notifications for technicians in tickets
2023-12-20 23:45:00 -05:00
Johnny
8ff6271058 Merge pull request #834 from twetech/billable_tickets
Update ticket billing functionality
2023-12-20 23:43:51 -05:00
johnnyq
82ec1408de FEATURE: Added Batch Payment to multiple invoices, currently works by paying the oldest invoices firest this can be accessed through client invoices and will show as long as the client has a balance 2023-12-20 18:47:14 -05:00
o-psi
86d836f3d3 Add vscode to .gitignore 2023-12-19 23:18:11 +00:00
o-psi
999c8ddb40 Add sanitations
Forgot to add in the sanitations.
2023-12-19 23:11:50 +00:00
o-psi
4e142b26e9 Missing "}" after confict resolution 2023-12-19 23:05:56 +00:00
Andrew Malsbury
ae1496adae Merge branch 'master' into ticket_notifications 2023-12-19 17:04:05 -06:00
o-psi
98f731b4d4 Remove any "Send Single Email" declarations except in mail queue.
All emails go through the mail queue, using the addToMailQueue() function.
2023-12-19 23:02:05 +00:00
o-psi
70a9120147 Add notification for ticket replies 2023-12-19 22:39:25 +00:00
o-psi
8b4beacf0e Update MailQueue to use function 2023-12-19 22:36:51 +00:00
johnnyq
77b431cb61 Fix Folder ID for file references 2023-12-18 14:54:49 -05:00
johnnyq
7894efedf0 Related Items under Document Details can be clicked on and opened as a new window link 2023-12-18 14:53:06 -05:00
johnnyq
2d06f923d4 Fix Adding NULL logins when editing license 2023-12-18 14:09:34 -05:00
o-psi
d6f4695a03 removed php shorthand for if statements. 2023-12-18 18:21:36 +00:00
o-psi
ebaa2a084a add readable password generation 2023-12-18 17:34:59 +00:00
o-psi
f0567c1fb7 add password generation functionality 2023-12-18 17:34:39 +00:00
o-psi
e0c8b0c30d Readable Password Function 2023-12-18 17:34:22 +00:00
o-psi
43d7f86d90 Readable Password Ajax 2023-12-18 17:34:11 +00:00
johnnyq
29c7f53b8b Fixed incorrect function in statements should be nullable_htmlentities not nullable_html_entities 2023-12-18 12:08:33 -05:00
Johnny
8e86f19bcc Merge pull request #833 from twetech/statements
Statements
2023-12-18 11:59:09 -05:00
o-psi
25fba91642 Put show modals javascript above pretty content. 2023-12-18 15:27:45 +00:00
o-psi
320d534319 Fixed invoice_url 2023-12-18 14:36:50 +00:00
o-psi
961f97f79a fix database 2023-12-17 20:38:11 +00:00
o-psi
7004d9217d Convert account_id and invoice_id to integers in calculateAccountBalance and calculateInvoiceBalance functions 2023-12-17 20:34:39 +00:00
o-psi
78260a2b4e Updates to mark tickets billable, and keep track of which have been billed. 2023-12-17 20:28:57 +00:00
johnnyq
fc7e67f5d0 Fix missing dot for allow .ps1 files 2023-12-14 12:23:55 -05:00
o-psi
1f46ea79fc Escaped Variables 2023-12-14 15:35:03 +00:00
johnnyq
3b6cfeff73 Add cfg and ps1 to the allow file upload list 2023-12-13 20:59:01 -05:00
o-psi
1a18022cc6 remove debug 2023-12-13 16:21:40 +00:00
o-psi
5d56bb2066 update collections report to include link to statement. 2023-12-13 16:12:23 +00:00
o-psi
5be0f9f934 add calculate invoice balance function 2023-12-13 16:10:08 +00:00
o-psi
8e17dbf5ba Add side nav button for statements 2023-12-13 16:09:42 +00:00
johnnyq
74aa0e829f Fix Invoice Item order in Ticketing, When creating an invoice from a ticket make sure the item added has an item_order of 1 2023-12-09 16:31:28 -05:00
johnnyq
594c8565ce Remove Weekly option when converting an invoice to a recurring invoice 2023-12-09 16:17:19 -05:00
johnnyq
72e448e4f0 Item Ordering Fix for Copy Quote or Invoice, Recurring Invoice to Invoice Cron, Force Recurring, Invoice to Recurring. It was not carrying over the item order on these tasks causing item ordering to break 2023-12-09 16:12:31 -05:00
johnnyq
3b7fe290af Removed Weekly option for Recurring Invoices soon will add Quarterly and Bi Annually 2023-12-09 15:24:41 -05:00
johnnyq
b6bc13ddd4 Removed Action Column on Client Tickets similar to the previous commit regarding Global Tickets 2023-12-09 15:08:32 -05:00
johnnyq
dccec2d5f5 Removed actions column from tickets as edit ticket and Delete should be done within the ticket itself, however you can still change priotity and assigned to within the list view. This makes a tremendous impact on performance as ticket details wont need loaded for each row Soon we will impelment bulk actions 2023-12-09 15:04:30 -05:00
Johnny
0eaf9febeb Merge pull request #830 from stehled/master
Fix domain edit for .eu and other domains.
2023-12-06 08:44:03 -05:00
Johnny
aad7b21b24 Merge pull request #831 from twetech/master
Fix for guest pay stripe with fees
2023-12-06 08:43:28 -05:00
o-psi
0aa08dac83 Fix for guest pay stripe with fees 2023-12-04 21:44:31 +00:00
Eduard Stehlík
f47c5cca84 Fix domain edit for .eu and other domains. 2023-12-04 18:40:53 +01:00
johnnyq
7d0813a163 Opps forgot to dump DB when remember_me_token was added causing remember_me on new installs to fail 2023-12-01 11:53:30 -05:00
Johnny
469c8aa501 Merge pull request #828 from wrongecho/quote-fix
Bugfix: Quotes to invoice item ordering
2023-11-30 12:50:15 -05:00
Johnny
d36dca508f Merge pull request #829 from twetech/stripe-pays-fees-undeclared-variable
Fix undeclared variable on Guest Online Pay
2023-11-30 12:50:01 -05:00
o-psi
a74bd5ade1 Fix undeclared variable on Guest Online Pay 2023-11-30 16:29:29 +00:00
Marcus Hill
a0a4e5524a Bugfix: Quotes to invoice item ordering
- Fix item ordering not working for invoices generated from quotes
- Other small quote bugfixes
2023-11-29 21:36:03 +00:00
Johnny
5772146d14 Merge pull request #827 from wrongecho/loc-primary
Bugfix: New locations are set as the primary
2023-11-25 14:14:41 -05:00
Johnny
59aeb1e976 Merge pull request #826 from wrongecho/admin-settings-csrf
Require CSRF token to edit more admin settings
2023-11-25 14:07:31 -05:00
Johnny
e50fbd76ae Merge pull request #824 from wrongecho/disable-personal-dash-link
Temporarily disable the personal dashboard link to prevent confusion
2023-11-25 13:34:25 -05:00
Johnny
e261651370 Merge pull request #823 from wrongecho/agent-email-key
Include login key in agent invitation email
2023-11-25 13:34:10 -05:00
Johnny
0196e86c16 Merge pull request #822 from wrongecho/client-tickets-default-open
Ticketing updates
2023-11-25 13:33:55 -05:00
Marcus Hill
fe369a4078 Bugfix: New locations are set as the primary
Bugfix: Every time you add a new location, it is marked as the primary location in the modal by default as the location_primary variable is overwritten with each iteration of a location.
This PR defaults to no location being the primary, to avoid unnecessarily overwriting the primary location.

Future work: Re-add fixed logic used to determine if a primary location is missing
2023-11-25 18:31:05 +00:00
Marcus Hill
8068cb6081 Require CSRF token to edit more admin settings - thanks again to @stehled 2023-11-25 18:15:25 +00:00
wrongecho
51ac53dc50 Merge pull request #825 from wrongecho/csrf-stripe
Require CSRF token to edit Stripe settings - thanks to @stehled
2023-11-25 16:39:14 +00:00
Marcus Hill
432488eca3 Require CSRF token to edit Stripe settings - thanks to @stehled 2023-11-25 16:36:05 +00:00
wrongecho
3158353921 Update first-interaction.yml
Bump to 1.2.0 to see if this fixes
2023-11-25 14:37:10 +00:00
Marcus Hill
55b35d16f1 Temporarily disable the personal dashboard link to prevent confusion as it is not yet in use 2023-11-25 14:31:09 +00:00
Marcus Hill
48c381ac2d Include login key in agent invitation email 2023-11-25 12:12:45 +00:00
Marcus Hill
c0eb94efc3 Ticketing updates
- Client ticket view now defaults to showing Open tickets
- Client ticket view now has ability to quick filter between open/closed tickets
- Don't render modals for closed tickets (~6x performance boost 0.030 seconds before vs 0.005 seconds after) (we really need dynamic modals for ticketing!)
2023-11-25 11:29:08 +00:00
wrongecho
c1d0a2368d Merge pull request #821 from twetech/Fix-collections-link
Fix link to client overview in collections
2023-11-25 10:31:35 +00:00
Andrew Malsbury
5653518f50 Merge branch 'master' into Fix-collections-link 2023-11-22 12:22:57 -06:00
Andrew Malsbury
fe86d3982c Fix the link to client overvier in collections 2023-11-22 18:18:17 +00:00
Andrew Malsbury
d90280011f Revert "Add scheduled ticket end date field"
This reverts commit d81a04a1d4.
2023-11-22 17:45:01 +00:00
Andrew Malsbury
d81a04a1d4 Add scheduled ticket end date field 2023-11-22 17:44:43 +00:00
Johnny
2adb500612 Merge pull request #819 from twetech/fix-collections-formatting
Add missing currency variable
2023-11-22 11:47:24 -05:00
Johnny
d19706e0c9 Merge pull request #818 from twetech/Fix-new-trips-modal-for-trips.php
Fix-new-trips-modal-for-trips.php
2023-11-22 11:47:05 -05:00
Andrew Malsbury
61f6735ceb added missing currency variable 2023-11-22 16:31:14 +00:00
Andrew Malsbury
7c93a073b2 fix option 2023-11-22 15:01:49 +00:00
Andrew Malsbury
dc04deaada Fix new trip on trips.php 2023-11-22 15:00:42 +00:00
johnnyq
b3c37b6c5f Added ability revoke a users Remember Me Token from the users listing 2023-11-21 18:28:42 -05:00
johnnyq
41ba04b881 Spacing Tidy 2023-11-21 17:37:30 -05:00
johnnyq
90bb9499d5 Moved Remember Me to the Enter MFA Screen Only 2023-11-21 17:36:45 -05:00
Johnny
be10ac0b46 Merge pull request #817 from twetech/remove-gateway-fees-from-client-invoice
Remove Stripe fee from main invoice display
2023-11-21 17:00:34 -05:00
Andrew Malsbury
6ce72e7cc1 Remove Stripe fee from main invoice display 2023-11-21 21:57:04 +00:00
Johnny
c95060727c Merge pull request #816 from twetech/collections-report
Add collections report
2023-11-21 16:55:35 -05:00
johnnyq
a01269ccea Updated Tax Rate to be a floatval instead of a intval 2023-11-21 16:51:05 -05:00
johnnyq
c1d6220e6a Added Tax Name and Rate to the products listing 2023-11-21 16:34:26 -05:00
johnnyq
48177e4250 Updated Quote and Recurring to Automatically select the Tax based off the product tax 2023-11-21 16:17:17 -05:00
johnnyq
3ec2e79e91 Attempt to automatically select Tax based off the products tax code in invoices, it works just doesnt update the select box to show selected 2023-11-21 16:06:12 -05:00
johnnyq
1f9c6578d5 Sanitize each Status in Array 2023-11-21 15:41:03 -05:00
johnnyq
3749cbfca1 Updated multiple ticket status selection 2023-11-21 15:22:38 -05:00
Andrew Malsbury
73e14c164b Add collections report 2023-11-21 19:03:38 +00:00
johnnyq
900ec75303 Reverted Multi Status Select using select2 in Ticket filtering as it broke existing filtering 2023-11-21 12:36:37 -05:00
Johnny
5c89e9849b Merge pull request #813 from twetech/fix-balance-sheet
Redo Balance Sheet Report
2023-11-21 11:57:03 -05:00
Johnny
af7ef5cf20 Merge pull request #814 from twetech/fix-ticket-query
Update Array for ticket Query
2023-11-21 11:55:58 -05:00
Andrew Malsbury
c28727f9a7 Update Array 2023-11-21 16:27:10 +00:00
Andrew Malsbury
230e649e2c Redo Balance Sheet Report 2023-11-21 16:04:41 +00:00
johnnyq
f18bb340bf Keep the Remember Me checkbox selected upon inital submit 2023-11-20 21:18:35 -05:00
johnnyq
0d6c58f1d0 Added Remember Me option by checking this you wont have to enter your MFA for up to 14 days on the device 2023-11-20 20:49:33 -05:00
johnnyq
dcd5103819 Hide Financial Reports, Financial Dashboard, Client Portal Invoices/Quotes of Accounting module is disabled, also included the settings into the client portal, so all settings vars are easily accessable within the portal 2023-11-20 17:20:49 -05:00
johnnyq
ed625b2d98 Fix Client Side Menu Wording 2023-11-20 17:00:04 -05:00
Johnny
26b439554b Merge pull request #810 from twetech/client-pays-fees
Enable passing stripe fee to clients
2023-11-20 16:49:16 -05:00
Johnny
a997896c46 Merge pull request #812 from wrongecho/comment-maintenance-unused
Hide currently unused "Maintenance" from Settings side navbar
2023-11-20 12:33:07 -05:00
Johnny
e9881ff32c Merge pull request #811 from wrongecho/cron-schd-tickets-agent-notif
Scheduled tickets - New ticket notifs + bugfix
2023-11-20 12:32:50 -05:00
Johnny
774531836a Merge pull request #809 from twetech/tax-report
Add functions for retrieving setting values and calculating taxes
2023-11-20 12:24:36 -05:00
Johnny
208f55fad2 Merge pull request #806 from twetech/add-client-replied-to-ticket-status-sort
Add Client-Replied and update select2 statuses in ticket sort dropdown
2023-11-20 12:23:34 -05:00
Andrew Malsbury
88392d0dea Add Stripe fee calculation to guest_ajax.php and
guest_view_invoice.php
2023-11-20 16:42:29 +00:00
Andrew Malsbury
6ab96b3b16 Update settings 2023-11-20 16:42:11 +00:00
johnnyq
02e0692b85 Fix Badge colors not working correctly after custom color tag update 2023-11-19 14:56:49 -05:00
Marcus Hill
b65b8c1c43 Hide currently unused "Maintenance" from Settings side navbar 2023-11-18 12:34:37 +00:00
Marcus Hill
41cfd8d27b Scheduled tickets
- Notify agent DL when scheduled tickets are raised (if configured)

- Bugfix: Ticket numbering if two or more scheduled tickets are raised in the same script execution
- Bugfix: Email processing if a contact replied to a scheduled ticket email (still showing original #--itflow# line rather than ##- Please type your reply above this line -##)
2023-11-18 11:53:24 +00:00
Andrew Malsbury
cc5d274596 Update database version to 0.9.5 and add
config_stripe_client_pays_fees field
2023-11-17 22:44:10 +00:00
Andrew Malsbury
5cfae2520e Add functions for retrieving setting values and
calculating taxes
2023-11-17 21:43:37 +00:00
johnnyq
fe1b8ce88f minor UI update on update 2023-11-17 15:19:48 -05:00
Johnny
75238ce0fb Merge pull request #803 from twetech/See-All-Timers
Add timers modal to see all timers
2023-11-17 14:28:06 -05:00
johnnyq
3781026c79 Commented Out Remember me as it is not feature complete yet 2023-11-17 14:21:41 -05:00
Andrew Malsbury
955b7cc53b Refactor variable declarations to use let instead
of var
2023-11-17 18:30:43 +00:00
Andrew Malsbury
feea83d380 Merge branch 'master' into See-All-Timers 2023-11-17 12:28:20 -06:00
Andrew Malsbury
011bacd1a2 Add ticket timer functionality and clear all
timers button
2023-11-17 18:27:31 +00:00
johnnyq
b1c60fa4d8 Update Categories Create and Edit Modals to take advantage of custom colors 2023-11-16 18:54:49 -05:00
johnnyq
76e348a3a1 Updated UI Create Calendar Modal 2023-11-16 18:42:21 -05:00
johnnyq
2779d6543e Updated Tag Create and Edit Modal UI, added icons, added ability to choose any color 2023-11-16 18:36:22 -05:00
johnnyq
d54a026a33 Wording: Change Passwords to Logins under global search 2023-11-16 18:14:02 -05:00
johnnyq
e8f4c5a672 Fixed Where clause in services 2023-11-16 18:08:21 -05:00
Johnny
8eccdc6b6a Merge pull request #807 from twetech/add-asset-uri-to-ticket-information
Add asset URI to client asset details page
2023-11-16 13:23:51 -05:00
johnnyq
7f7e05873a Bump InputMask from 5.07 to 5.08 2023-11-16 11:31:44 -05:00
johnnyq
b85e045202 Bump PDFMake 0.2.7 to 0.2.8 2023-11-16 11:15:14 -05:00
johnnyq
9cfb9b2f04 Bump JQuery 3.5.1 to 3.7.1 2023-11-16 11:11:47 -05:00
johnnyq
7baceb8c5a Bump TinyMCE from 6.7.0 to 6.7.3 2023-11-16 11:00:46 -05:00
johnnyq
834956624b Reduced the heading font sizes on the the right side ticket details to allow more info to be displayed 2023-11-16 10:40:54 -05:00
johnnyq
32203565a7 UI update for ticket timer, removed the appended H S M to free some clutter 2023-11-16 10:27:14 -05:00
johnnyq
48b153613f Changd Passwords to Logins, made Licenese icon consistent 2023-11-16 00:20:36 -05:00
Andrew Malsbury
41748a03b6 Merge branch 'See-All-Timers' of https://github.com/twetech/itflow into See-All-Timers 2023-11-15 16:30:13 +00:00
Andrew Malsbury
bdda03d8b2 Update ticket link in header_timers.js 2023-11-15 16:30:10 +00:00
Andrew Malsbury
e5752dc335 Add asset URI to client asset details page 2023-11-15 15:32:37 +00:00
Andrew Malsbury
94b4d4aeca Merge branch 'master' into See-All-Timers 2023-11-14 20:00:13 -06:00
Andrew Malsbury
a6a49604a8 Merge branch 'itflow-org:master' into add-client-replied-to-ticket-status-sort 2023-11-14 19:52:02 -06:00
johnnyq
201860798a Fix Ticket Timer to allow for 00 for hour 2023-11-14 18:02:12 -05:00
Andrew Malsbury
35b709fa18 Merge branches 2023-11-14 18:31:30 +00:00
Andrew Malsbury
f01d9d0530 Updated to use prepared statements as 2023-11-14 18:30:18 +00:00
johnnyq
63a4eab8bc Added Pattern Attribute to only allow correct input for the ticket timer 2023-11-14 13:20:51 -05:00
johnnyq
16aff5f634 UI Update to the ticket timer. reworked sizing to be a small input field, set the fields to text instead of numeric as the number updown element was taking up too much space 2023-11-14 13:15:49 -05:00
Andrew Malsbury
4060bea7a6 Add new ticket status and refactor ticket status
filter.
2023-11-14 17:41:30 +00:00
Andrew Malsbury
5657c153be Merge branch 'master' into See-All-Timers 2023-11-14 11:24:26 -06:00
Andrew Malsbury
973307524d Update to fix main screen 2023-11-14 17:23:13 +00:00
Andrew Malsbury
1d401874f3 Update to select2 multiple statuses. 2023-11-14 17:09:43 +00:00
Andrew Malsbury
a0cd266c8b Add Client-Replied to ticket sort dropdown 2023-11-14 15:53:04 +00:00
Johnny
5dfc0d0d2c Merge pull request #802 from twetech/update-timer-when-pending
Time tracking paused when pending
2023-11-13 23:29:15 -05:00
johnnyq
f11ad402e9 Moved the rest of the Import / Export Buttons into the Create and some exports in the Advanced filter button 2023-11-13 20:24:57 -05:00
johnnyq
4a74d7b402 Do not show other Assets if there are none 2023-11-13 19:52:03 -05:00
Johnny
c2a5f02308 Merge pull request #805 from twetech/Fix-for-quotes-and-recurrings
[HOTFIX] Fix editing of recurring and quotes
2023-11-13 14:19:30 -05:00
Andrew Malsbury
cdacb7735c Update to remove 2023-11-13 18:45:31 +00:00
Andrew Malsbury
d837a10013 Fix editing of recurring and quotes 2023-11-13 17:50:42 +00:00
Andrew Malsbury
47fe6fe233 Add timers modal to see all timers 2023-11-12 23:47:44 +00:00
Andrew Malsbury
efb4709519 Time tracking paused when pending 2023-11-12 21:23:06 +00:00
johnnyq
104bbee422 Converted Client Services Multiple Select Boxes to use Select2: 2023-11-10 16:34:21 -05:00
Johnny
9c4d9f14b1 Merge pull request #801 from wrongecho/mail-parse-blank-emails
Mail parse - Handle blank/unexpected emails better
2023-11-09 17:57:52 -05:00
Marcus Hill
0de99fda61 Mail parse - Handle blank/unexpected emails better 2023-11-09 22:18:57 +00:00
johnnyq
f6076ad97a Remove Quick Add Instead redirect them to the categories settings page when plus is clicked 2023-11-09 13:09:38 -05:00
johnnyq
8975fcf2ee Place Advanced filter back on the left final decision was made to do so and I like it 2023-11-09 11:23:45 -05:00
johnnyq
408a596efa Add logging if creating a referral via create client 2023-11-08 23:35:00 -05:00
johnnyq
0103e05093 Ability to create a referral when adding a client 2023-11-08 23:30:44 -05:00
johnnyq
89cbdd1038 Added industry select array 2023-11-08 22:54:33 -05:00
johnnyq
cbf15f4e81 Updated button colors on accept decline quote 2023-11-08 22:28:29 -05:00
johnnyq
88a6fdd36d Start page is a required select box with the option of putting in a custom value 2023-11-08 22:17:51 -05:00
johnnyq
5bd4c32f4d Reorganized Create Software License added multi select2 to assign asset and user licenses 2023-11-08 16:46:15 -05:00
johnnyq
a300248f90 Remove the old add remove ticket watcher js code 2023-11-08 14:38:48 -05:00
johnnyq
7e2d3c4159 Add Function Select2 Multiple Capabilities to add ticket watchers in create client ticket 2023-11-08 14:37:03 -05:00
johnnyq
eb01e4b4d5 Clean up Logic for Client Add and Client Edit Modals, same for trip add copy edit 2023-11-08 13:34:58 -05:00
Johnny
40b6723fac Merge pull request #800 from wrongecho/azure-sso-error-wording
AAD SSO - Wording
2023-11-07 17:28:37 -05:00
johnnyq
3a61b56c6e Fix SQL Syntax error 2023-11-07 16:52:02 -05:00
johnnyq
5d1c283533 Do not show disabled or users that were before the trip creation date 2023-11-07 16:34:32 -05:00
Marcus Hill
51ec92c72e AAD SSO - Wording
Slight change to the error wording when a user doesn't exist in ITFlow as a contact / has the wrong auth method set (blank/local rather than Azure)
2023-11-07 21:18:46 +00:00
johnnyq
afc040bfe6 Updated UI on add / edit Client moved the tagging functionality to using select2 to increase space and merge tags and notes tabs 2023-11-07 16:02:15 -05:00
johnnyq
3f2f405596 Allow Manual Input of Trip Destination or select from client locations, Added Remember me checkbox for future implementation 2023-11-06 19:37:48 -05:00
johnnyq
d2e3c1e12d Fix Domains Icon in Global Search, remove unnessesary > 2023-11-06 17:03:34 -05:00
johnnyq
a9304a3784 Move Calendar under support Move Trips under Finance 2023-11-06 15:25:54 -05:00
johnnyq
c18dbc5985 Rename Events in Client Side Nav to Calendar 2023-11-06 15:22:51 -05:00
johnnyq
91924bc239 Feature: Part 2 - Added Default Hourly rate to settings pane, default to the default hourly rate when adding a client 2023-11-06 15:05:07 -05:00
johnnyq
1f0d2ff1ab Feature: Part 1 - DB Schemea update for Default Hourly Rate 2023-11-06 14:52:01 -05:00
johnnyq
69e9691de9 Remove elevation CSS tag from tickets as this was not consistent and unnessary 2023-11-06 14:43:19 -05:00
johnnyq
76f20225f5 Fix IT Docs not showing, keep assets side nav active when viewing asset details page 2023-11-06 14:38:22 -05:00
johnnyq
c40be56869 Disable Documentation section of Client Side Nav of IT Doclumentation is disabled 2023-11-06 14:33:23 -05:00
johnnyq
a8ee791d64 Allow to set quick notes under asset details 2023-11-06 14:25:55 -05:00
johnnyq
dff4eff5cc Do not show related content in edit service if the entity archived date is greater than when the service was created 2023-11-06 13:46:52 -05:00
johnnyq
167c2a5b43 Remove Document from many to many service_documents table when archiving or deleting a document prevents from showing up under document service relation 2023-11-06 13:27:58 -05:00
johnnyq
11b814b4c8 Do not show archived content when adding a service 2023-11-06 13:19:27 -05:00
johnnyq
43b94ebddc Restored New Quote Functionality under clients this was disabled for debugging but never re-enabled back 2023-11-06 12:44:44 -05:00
Johnny
210530e673 Merge pull request #798 from wrongecho/client-is-lead-fix
Fix undefined client_is_lead errors
2023-11-05 10:49:43 -05:00
Johnny
7044c6bf54 Merge pull request #797 from wrongecho/api-additions
API - Documents
2023-11-05 10:49:30 -05:00
Marcus Hill
ba86af9efa Fix undefined client_is_lead errors
- Defines client_is_lead within the general client include file to prevent the following error filling up logs on almost every page load.
> "PHP Notice: Undefined variable: client_is_lead in itflow/client_edit_modal.php on line 111"
2023-11-05 11:03:49 +00:00
Marcus Hill
573eaf179b API - Documents
- Add create and update methods
2023-11-05 10:42:46 +00:00
wrongecho
a31c012487 Merge pull request #796 from wrongecho/fix-trip-export
Fix trip export to csv
2023-11-05 08:31:16 +00:00
Marcus Hill
7ccd69a26f Fix trip export to csv 2023-11-05 08:24:19 +00:00
Johnny
f7e0f06eb6 Merge pull request #795 from nellistc/globalsearch-domains
Update global search to include client domains
2023-11-03 16:44:50 -04:00
nellistc
7ab032fa3f Update global search, add client to domain search results
Show client name and link to client overview in domain search results
2023-11-04 07:31:21 +11:00
nellistc
008ad76c68 Update global_search.php
add domains to global search results
2023-11-03 18:22:24 +11:00
johnnyq
fbf535444b Updated Quote and Recurring to match invoice UI updates 2023-11-02 16:31:25 -04:00
johnnyq
ef213e34d4 Invoice UI Update: Bolded Due Date, Moved Subtotal to the top added - sign in front of discount, do not subtract the discount from the subtotal as this is reservered for total, do not show tax discount or paid in pdf if they are 0 2023-11-02 16:12:06 -04:00
johnnyq
015d8265e0 Fix Quotes duplicated php start close tags in edit quote discount field 2023-11-02 13:19:13 -04:00
johnnyq
cd99e91ac3 Bold the contact name in client listing 2023-11-01 18:55:41 -04:00
johnnyq
5a7c62c150 Added back number_format() function as there was a way to just remove the commas but keep the decimal place so 290.90 doesnt look like 290.9 2023-11-01 18:16:12 -04:00
johnnyq
572f12eaef Removed num_format(),2 function for pricing and cost fields as it was putting in commas as this is unacceptable for floatvals 2023-11-01 17:51:35 -04:00
johnnyq
5c0ab72d69 Moved creating lock file after all other checks have passed to prevent locking if a certian check has not passed, turned off imap extend log as it could cause mysql errors also remove lock before exiting if cannnot connect to imap 2023-11-01 13:59:35 -04:00
johnnyq
43786a72ab Moved Advanced Filter button to the right for invoices and quotes 2023-10-31 17:24:46 -04:00
johnnyq
7f19ea6c55 Moved Advanced Filter button to the far right toolbar under clients 2023-10-31 17:16:14 -04:00
johnnyq
b26c1b28c3 Show Archived Items for licenses and password and moved import exports to New DropDown 2023-10-31 16:24:59 -04:00
johnnyq
c94c88dc88 Show Archived Items for locations, vendors and assets and moved import exports to New DropDown 2023-10-31 16:16:15 -04:00
johnnyq
be279b4e8d Added more hints between leads and clients under client management 2023-10-31 15:38:40 -04:00
johnnyq
174a8d932f Reworked the sahow Client Leads button to radio style 2023-10-31 15:12:38 -04:00
johnnyq
638d59e1c1 Sort items by item order when exporting invoices or quotes to PDF in app view and guest view 2023-10-31 14:57:45 -04:00
johnnyq
036c687bf8 Fix up item moving on invoice, quotes and recurrung, removed unnessesary tags, re-arranged the arrows to the top rename remove to delete with a trash can as its more proper 2023-10-31 14:51:38 -04:00
johnnyq
8a5f51845c Reworked the Dashboard so only 1 Dashboard shows on the Side nav and now has a top nav to select dasbords, Personal Dashboard coming 2023-10-31 14:22:03 -04:00
johnnyq
4a4924f4f6 Bring back editing of username and password for an asset in the asset details page 2023-10-31 13:30:38 -04:00
johnnyq
365ed3a79a Merged Client Leads into Client Management 2023-10-31 11:03:46 -04:00
Johnny
4ab38b42f8 Merge pull request #794 from twetech/timer-tracking-remember-manual-changes
Update timer to remember manual edits
2023-10-31 10:26:57 -04:00
Andrew Malsbury
fb45bceae5 Update timer to remember manual edits. 2023-10-30 13:22:29 +00:00
Johnny
d4d4d9cd7a Merge pull request #793 from wrongecho/schd-contact
Add ability to edit contact on a scheduled ticket
2023-10-29 13:32:09 -04:00
Marcus Hill
d6cf04b8f2 Codesmell 2023-10-28 14:40:27 +01:00
Marcus Hill
e88d0b1e23 Add ability to edit contact on a scheduled ticket 2023-10-28 14:32:15 +01:00
Johnny
48753e6462 Merge pull request #792 from twetech/update-timer
Timer - Record time even if closed
2023-10-27 20:36:25 -04:00
johnnyq
3c8a026b7c Fixed Cron mail queue and email parser missing ' 2023-10-27 13:05:29 -04:00
Andrew Malsbury
adafd38684 Timer - Record time even if closed 2023-10-26 19:19:46 +00:00
johnnyq
f9d3d3b2f9 Also Added logging to cron mail queue and mail parser when attempting to execute when its already executing by checking to see if the lock file is present 2023-10-25 18:05:19 -04:00
johnnyq
c30e0f7768 Remove Lock files older than 10 Mins aka 600 Secs and log it for Cron Email Parser and Cron Mail Queue 2023-10-25 17:57:35 -04:00
Johnny
87da66b069 Merge pull request #791 from twetech/save-timer-to-local
Save ticket timer to local storage
2023-10-25 17:35:21 -04:00
Johnny
430e148815 Merge pull request #790 from twetech/Discounts-pt-2
Update Quotes and Recurrings with discounts
2023-10-25 17:34:34 -04:00
Johnny
903e9437c4 Merge pull request #789 from twetech/sort-for-quotes-and-invoices
Update for sorts
2023-10-25 17:34:19 -04:00
Johnny
a1e511d8ac Merge pull request #788 from twetech/topnav-notification-fix
Removed useless assignment
2023-10-25 17:34:06 -04:00
Andrew Malsbury
f6cdf5ac51 Added comments because I dont know JavaScript 2023-10-25 19:37:17 +00:00
Andrew Malsbury
a29a97214a Update to keep incrementing while tab is closed 2023-10-25 19:16:07 +00:00
Andrew Malsbury
ea3e1df784 clear local storage when responding 2023-10-25 19:02:23 +00:00
Andrew Malsbury
6a0b291acd Save timer to local Storage 2023-10-25 18:26:33 +00:00
Andrew Malsbury
62d3cab389 Update Quotes and Recurrings with discounts 2023-10-25 17:15:41 +00:00
Andrew Malsbury
79c112b0af Merge branch 'itflow-org:master' into topnav-notification-fix 2023-10-25 09:36:09 -05:00
Andrew Malsbury
5f2a1298a1 Fix quotes screen, and update others for looks. 2023-10-25 14:32:46 +00:00
Andrew Malsbury
85a759f7db Removed useless assignment 2023-10-25 14:07:47 +00:00
Johnny
5faac97491 Merge pull request #785 from o-psi/Update-Timer
Update Timer to stop when in focus
2023-10-24 21:10:48 -04:00
o-psi
53c953b60e Update the timer to stop when focused. 2023-10-24 20:09:07 +00:00
o-psi
6c13773706 Revert "Enhance timer: Pause during input edits"
This reverts commit 2a3156cd59.
2023-10-24 20:08:22 +00:00
o-psi
2a3156cd59 Enhance timer: Pause during input edits 2023-10-24 20:07:10 +00:00
johnnyq
b05e5bb575 Fix Broken cron.php broke as of 10-20-2023 2023-10-23 13:51:16 -04:00
johnnyq
7b94e29aa4 Fix Broken Select2 andDateRangePicker JS Plugins 2023-10-21 22:59:00 -04:00
Johnny
b34fd85ad4 Merge pull request #784 from wrongecho/portal-ticket-attachments
Portal ticket attachments
2023-10-21 16:00:14 -04:00
Johnny
e0f1adb446 Merge pull request #783 from wrongecho/email-to-ticket-extensions
Expand range of allowed file extensions for email to ticket attachments
2023-10-21 15:59:25 -04:00
Johnny
68220cc063 Merge pull request #782 from wrongecho/ticket-assigned-wording
Change modal unassigned wording from "No one" to "Not Assigned"
2023-10-21 15:59:13 -04:00
Johnny
33abf8a9eb Merge pull request #781 from wrongecho/session-timeout-garbage-workaround
Add background ajax query in an attempt to prevent session timeout
2023-10-21 15:59:00 -04:00
Johnny
abc2226b4f Merge pull request #780 from wrongecho/fix-client-page
Fix clients.php page after leads were added
2023-10-21 15:58:37 -04:00
Marcus Hill
31be8034e7 Revert different change covered in separate PR 2023-10-21 15:27:21 +01:00
Marcus Hill
218cdcdc4c Allow contacts to upload attachments when adding ticket replies in portal
- Adds the ability for contacts to add file attachments when posting a ticket reply
- Enhancements to checkFileUpload(): Adjust file reference name generation & bad extension handling
2023-10-21 15:24:15 +01:00
Marcus Hill
7aadad3597 Expand range of allowed file extensions for email to ticket attachments 2023-10-21 14:40:14 +01:00
Marcus Hill
1c6c90845c Change modal unassigned wording from "No one" to "Not Assigned" 2023-10-21 13:01:11 +01:00
Marcus Hill
65168fe702 Add background ajax query in an attempt to prevent session timeout 2023-10-21 12:34:34 +01:00
Marcus Hill
2240f641dc Fix missing variable assignment for client_is_lead 2023-10-21 11:54:41 +01:00
johnnyq
ba9442e6c3 Added Confirmation to Close Ticket in Client Portal - Seperated cofirmation modal to a seperate JS file which is now included in the Client Portal 2023-10-20 19:10:25 -04:00
johnnyq
fcfb162ec8 Enable domain expire alerts and send invoice reminders did not respect their settings it would still execute as long as cron was executing, updated the desription of the options as well 2023-10-20 18:38:48 -04:00
johnnyq
509a955277 Comment out on End Task Logs as it wasnt producing correct information 2023-10-20 17:43:31 -04:00
johnnyq
6db576c80e Update setup so Asset Type Account type can be created before it adds the cash on hand account so it may reference the assets type 2023-10-20 16:42:10 -04:00
Johnny
dd644a39b8 Merge pull request #779 from o-psi/clean-requires-and-includes
Update constructs to not have parenthesis.
2023-10-20 16:32:29 -04:00
johnnyq
7a834b0f5f Update Payments to only show account_type_parent 1 which is assets 2023-10-20 16:27:43 -04:00
o-psi
53c11edc8c Update constructs to not have parenthesis. 2023-10-20 15:25:52 -05:00
Johnny
4080774602 Merge pull request #778 from o-psi/update-di
Update discounts to allow decimals
2023-10-20 16:19:33 -04:00
johnnyq
881f43bdb7 Updated Account Selection under Pay Invoice to show only Asset Accounts which is asset_type_parent = 1 2023-10-20 16:18:06 -04:00
johnnyq
8257fc3193 Updated Accounts Listing to use take adavantage of the new account_type_parent 2023-10-20 16:10:45 -04:00
o-psi
aed411dc45 Update discounts to allow decimals 2023-10-20 15:05:42 -05:00
johnnyq
762dafab7e Updated Account Types liasting and posting to use the new account_type_parent field, also update setup to inset the correct account types into the correct account_type_parent 2023-10-20 15:40:52 -04:00
johnnyq
fcc49c2b40 DB Update: Adds an account_type_parent field to represent the parent type 1 being default and representing Assets, 2 Liabilities, 3 Equity this will be the new way to identify the parent account type instead of using account_type_id min and max values ex 10-19 was Assets, 20-29 was Liabilities, Equity being 30-39. This was improper as the primary key should never be static 2023-10-20 14:56:40 -04:00
Johnny
8b9efb2e6d Merge pull request #777 from o-psi/payments-to-assets-accounts-only
Update Payments to only show Asset Accounts
2023-10-20 12:48:23 -04:00
o-psi
987944f992 Update Payments to only show Asset Accts 2023-10-20 08:33:28 -05:00
Johnny
56b91f3278 Merge pull request #776 from o-psi/discounts
Discounts
2023-10-19 18:34:44 -04:00
Andrew Malsbury
a382092dab Merge branch 'master' into discounts 2023-10-19 17:19:32 -05:00
o-psi
6e6e0d5f71 Update variable definition 2023-10-19 17:03:50 -05:00
o-psi
824db5865b Update Guest View Payment Screen 2023-10-19 17:01:09 -05:00
o-psi
ea1dadf792 update db ver number 2023-10-19 16:34:57 -05:00
Johnny
e379587c06 Merge pull request #772 from o-psi/leads
Leads
2023-10-19 16:41:59 -04:00
o-psi
8bea3f0022 Update Guest View 2023-10-19 14:05:58 -05:00
o-psi
fdaa176486 Post handling for calculating Discounts 2023-10-19 13:56:58 -05:00
o-psi
5317f298dc Add view for discount. 2023-10-19 13:56:26 -05:00
o-psi
541bd9e0ca add discount to model 2023-10-19 13:56:01 -05:00
o-psi
25d2b48542 Add discount to modal, reformat. 2023-10-19 13:54:39 -05:00
o-psi
8182144bdc Update database to have discount field on invoice. 2023-10-19 13:53:53 -05:00
Johnny
6aeefd3d5d Merge pull request #775 from o-psi/update-readme
Default install script doesnt like the oneliner.
2023-10-18 11:43:07 -04:00
Johnny
9806fc9283 Merge pull request #774 from o-psi/Fix-Setup-Page
[Urgent] - Fix Setup Page
2023-10-18 11:42:41 -04:00
o-psi
1296e6b5f0 Default install script doesnt like the oneliner. 2023-10-18 09:38:50 -05:00
o-psi
aae3845b16 removed erroneous 's' 2023-10-18 09:34:28 -05:00
o-psi
f16a175eed fixed intentionallity issue 2023-10-16 23:40:08 -05:00
o-psi
2f9b6d97b9 update post to support leads 2023-10-16 22:52:22 -05:00
o-psi
fa1feba237 add leads to client model 2023-10-16 22:50:21 -05:00
o-psi
44e5b6c2bd add leads to sales 2023-10-16 22:50:09 -05:00
o-psi
0d02c8b855 adjust clients to filter out leads 2023-10-16 22:49:59 -05:00
o-psi
efba7ffc8b make new leads screen to view leads. 2023-10-16 22:49:45 -05:00
o-psi
b19af06dae update edit modal to support leads and modals 2023-10-16 22:49:32 -05:00
o-psi
34db62e8ee Update add modal to support leads and clients 2023-10-16 22:43:48 -05:00
o-psi
4fa186179d DB Updates to support leads functionality 2023-10-16 19:30:31 -05:00
Johnny
de91afe1a0 Merge pull request #771 from o-psi/add-links-in-reports-to-clients
Add link to client in reports
2023-10-16 17:25:22 -04:00
johnnyq
fba1115b0d Fix DB Update database version was set it 0.8.10 which caused it not to update instead chnaged it to 0.9.0. items table also does not exist updated to invoices items for the new sort function redumped DB Structure. 2023-10-16 17:21:21 -04:00
o-psi
cc9dc4e6e7 add link to client overview page 2023-10-16 16:14:15 -05:00
Johnny
d0312e75cb Merge pull request #770 from o-psi/hide-archived-clients
Dont show archived clients in new invoice screens
2023-10-16 17:07:35 -04:00
Johnny
9818c57ecb Merge pull request #769 from o-psi/other-sorts
Sorting Recurring and Quotes
2023-10-16 17:06:42 -04:00
o-psi
4763110267 Dont show archived clients in new invoice screens 2023-10-16 15:53:54 -05:00
Andrew Malsbury
2d061c0163 Merge branch 'master' into other-sorts 2023-10-16 15:40:04 -05:00
Johnny
cce1dc86c2 Merge pull request #768 from o-psi/invoice-sort-1.b
Invoice Sort Updates
2023-10-15 23:39:36 -04:00
o-psi
3c391b9d50 Database Updates to match 2023-10-15 22:26:01 -05:00
o-psi
5221a3676e quote sort logic 2023-10-15 22:14:36 -05:00
o-psi
47db00e90c recurring item sort logic 2023-10-15 22:14:24 -05:00
o-psi
b04dd98370 update sort for recurring 2023-10-15 22:14:03 -05:00
o-psi
0c98d8b45b add logic for recurring 2023-10-15 22:13:51 -05:00
o-psi
5ba0649e4a sort by order 2023-10-15 22:08:19 -05:00
o-psi
64a00551c6 Fix Quote View for Sort 2023-10-15 22:08:04 -05:00
o-psi
e51d0b74a6 Cleaned up logic 2023-10-15 20:01:15 -05:00
o-psi
5f839d8768 Added logic to hide buttons 2023-10-15 20:00:42 -05:00
johnnyq
33c1e72dcc Fix Wrong Timezone var name 2023-10-15 12:15:48 -04:00
Johnny
8d5bda529c Merge pull request #767 from o-psi/unarchive-for-account-types
Updates for account types
2023-10-15 12:09:25 -04:00
o-psi
37399a90ce Added Search 2023-10-15 00:15:00 -05:00
o-psi
845b2397fb Add 'all' button 2023-10-15 00:00:03 -05:00
o-psi
26fc756175 Fixed a bug with not showing unless query given 2023-10-14 23:54:12 -05:00
o-psi
1f3c103032 changed view from long list to broken down by type 2023-10-14 23:34:54 -05:00
o-psi
ab308af4f9 changed number to name 2023-10-14 23:34:31 -05:00
o-psi
68b232e4fd set default per type page 2023-10-14 23:34:14 -05:00
o-psi
56a5e903df added unarchiving to account types post 2023-10-14 23:33:49 -05:00
Johnny
ee7d2e9dba Merge pull request #766 from o-psi/categories_archived
Allow Unarchiving and Deleting Categories.
2023-10-14 21:46:28 -04:00
o-psi
87b4345b87 Updated to use pagination head code. 2023-10-14 19:05:39 -05:00
o-psi
b107eb232c Add archived to table. 2023-10-14 14:11:02 -05:00
o-psi
0a98c4322c Allow unarchiving in Post.php 2023-10-14 14:10:41 -05:00
johnnyq
592e2a80d2 Increment the Database version to take adavantage of the new item ordering under invoices 2023-10-14 13:58:20 -04:00
Johnny
5a21271c45 Merge pull request #765 from o-psi/Localization-Cleanup
Condensed localization to a separate file
2023-10-14 13:54:54 -04:00
Johnny
966a8b0770 Merge pull request #763 from o-psi/add-php-info-to-debug
Expand debug screen with PHPInfo
2023-10-14 13:54:16 -04:00
Johnny
766df19223 Merge pull request #762 from o-psi/Invoice-items-order
Sort invoice items
2023-10-14 13:54:01 -04:00
Johnny
21a5006a43 Merge pull request #761 from o-psi/edit-currnet-expenses-amount-regex
Allow for commas in recurring expense modals
2023-10-14 13:50:56 -04:00
o-psi
ed269e1245 changed to item_order 2023-10-13 22:49:28 -05:00
o-psi
ee8e758a49 Condensed ~1.6 LOC by 50x, and reduced duplication 2023-10-13 22:42:11 -05:00
Andrew Malsbury
29279d0a7e Merge branch 'itflow-org:master' into edit-currnet-expenses-amount-regex 2023-10-13 22:12:03 -05:00
o-psi
08a11cb53e added php info and handling to bottom of debug 2023-10-13 21:56:50 -05:00
o-psi
0270a680a6 update invoices 2023-10-13 20:54:41 -05:00
o-psi
7a6c3ec470 Removed the order_id echo statement for production 2023-10-13 20:48:44 -05:00
o-psi
b4396fe244 post actions for changing sort 2023-10-13 20:13:40 -05:00
o-psi
ffa0226067 add item sort dropdowns 2023-10-13 20:13:28 -05:00
o-psi
097690bfbd add sort to guest view 2023-10-13 20:12:58 -05:00
o-psi
141dad23fe Update database, did not do increment 2023-10-13 20:12:43 -05:00
o-psi
3124ca2777 adjust regedit to allow for commas as thousands 2023-10-13 17:40:06 -05:00
o-psi
00effcf79d remove commas before trying to make a float 2023-10-13 17:39:41 -05:00
Johnny
45acc5866d Merge pull request #760 from o-psi/dashboard-links
Dashboard links
2023-10-13 15:30:47 -04:00
Johnny
604a788112 Merge pull request #759 from o-psi/Assets-Report
Assets report
2023-10-13 15:30:36 -04:00
Johnny
ff424330b4 Merge pull request #758 from o-psi/add-archive-for-account-types
Add archive option for account types
2023-10-13 15:30:06 -04:00
o-psi
b747bd4e9d Make all boxes links 2023-10-13 10:53:20 -05:00
o-psi
157263cf8a Add link to Assets on technical dashboard 2023-10-13 09:58:56 -05:00
o-psi
78032dcf6d Added a report to view all assets by client. 2023-10-13 09:56:38 -05:00
o-psi
37a5100742 Add archive option for account types 2023-10-13 13:57:17 +00:00
Johnny
2f8ee11a77 Merge pull request #757 from o-psi/Update-Documentation-Capitalization
Update Capitalization for Documentation
2023-10-12 18:30:49 -04:00
o-psi
3d31cf0d9d Move support above documentation 2023-10-12 22:03:40 +00:00
o-psi
ab6e8dde00 Update Services location 2023-10-12 22:02:28 +00:00
o-psi
9372ca4bc3 Update Capitalization for DOCUMENTATION 2023-10-12 20:43:26 +00:00
johnnyq
8c56426186 Fixed a layout issue if no previos ticket exists for a selected contact under ticket details 2023-10-12 16:09:31 -04:00
Johnny
5a1b93ae17 Merge pull request #754 from o-psi/fixed2-typo-in-product-logging
Fixed a typo in product logging
2023-10-12 12:57:57 -04:00
Andrew Malsbury
9b7ef4761c Merge branch 'itflow-org:master' into fixed2-typo-in-product-logging 2023-10-12 11:55:07 -05:00
Johnny
df14ac8a83 Merge pull request #753 from o-psi/remove-foreign-key
Remove-foreign-key
2023-10-12 12:54:33 -04:00
o-psi
38c5547307 changed modifyed to modified 2023-10-12 16:54:18 +00:00
o-psi
8bce945a11 Moved accounts back to top, removed accounts type. 2023-10-12 16:49:56 +00:00
Andrew Malsbury
33cd0e89ca Merge branch 'itflow-org:master' into master 2023-10-12 11:40:40 -05:00
Andrew Malsbury
df9f5fb001 Update db.sql 2023-10-12 11:23:38 -05:00
Andrew Malsbury
c7ca89b2e3 Update db.sql 2023-10-12 11:09:26 -05:00
Johnny
63ecb38bb7 Merge pull request #752 from o-psi/fix-account-type-fk
[Urgent] Fix Foreign Key for account types
2023-10-12 12:01:57 -04:00
Andrew Malsbury
aa9163ae98 Merge pull request #1 from o-psi/fix-account-type-fk
fix fk for account types
2023-10-12 10:54:59 -05:00
Andrew Malsbury
befbf457e8 fix fk for account types 2023-10-12 10:22:45 -05:00
wrongecho
448aaa8c1c Merge pull request #751 from o-psi/fix-account-type-default
[Critical] Fix bug introduced in account type update
2023-10-12 15:49:03 +01:00
Andrew Malsbury
6506f64a6e Update db.sql
Fix bug introduced in account type table
2023-10-12 09:27:38 -05:00
Johnny
101488f9f1 Merge pull request #750 from o-psi/Rename-Assets-SideNav-Category
Rename Assets and move documentation and files in
2023-10-11 22:21:09 -04:00
Andrew Malsbury
aaf04f18c5 Rename Assets and move documentation and files in 2023-10-12 02:00:12 +00:00
johnnyq
e6b15a0ff3 Do not Export Archived Data when Exporting client data to a PDF 2023-10-11 17:03:20 -04:00
johnnyq
964ff6740c Fix last commit opps on balance sheet report. use not equal to 0 instead of equal 0 as it will just sum up all the transfers 2023-10-11 15:12:14 -04:00
johnnyq
25751bdd85 Fix Balance sheet report so it doesn't calculate transfers, transfers use the expense and revenue tables as well. To fix this a transfer always has a vendor_id 0 in the expense table and category_id is always 0 for the revenues table, so dont sum those 2023-10-11 15:08:20 -04:00
johnnyq
66c16d6cff Increment Database again to insert the account types for PR #734 Add Balance Sheet report 2023-10-11 14:46:44 -04:00
johnnyq
fb60412686 Increment the Database version as this was missed in PR #734 Add Balance Sheet report 2023-10-11 14:37:27 -04:00
Johnny
c248af81fb Merge pull request #749 from o-psi/remove-gui-custom-fields
Removed gui for custom fields
2023-10-11 14:34:38 -04:00
Johnny
f1e74d926d Merge pull request #748 from o-psi/quote_guest_view
Update guest quote view to make more sense
2023-10-11 14:34:18 -04:00
Johnny
7986a797a7 Merge pull request #747 from o-psi/technical-dashboard-for-admins
Update technical dashboard links.
2023-10-11 14:33:34 -04:00
Johnny
44671d4769 Merge pull request #734 from o-psi/balance-sheet
Add balance sheet report
2023-10-11 14:31:45 -04:00
Andrew Malsbury
ddff9b929d Other PR code snuck in. Still learning git sry 2023-10-11 17:31:15 +00:00
Andrew Malsbury
ce16db9413 removed gui for custom fields 2023-10-11 14:42:22 +00:00
Andrew Malsbury
7e9c22171b Update button logic to disallow on draft... 2023-10-10 22:49:34 +00:00
Andrew Malsbury
533a547622 Update technical dashboard links. 2023-10-10 18:31:01 +00:00
Andrew Malsbury
74e2866a01 Adjusted the type dropdown 2023-10-10 16:52:00 +00:00
Andrew Malsbury
22a072f2b4 Merge branch 'itflow-org:master' into balance-sheet 2023-10-10 08:27:14 -05:00
Andrew Malsbury
7b772cf529 Something is broken with the confirm-link 2023-10-09 23:21:48 +00:00
Andrew Malsbury
96e493df4a Removed a testcase 2023-10-09 23:16:22 +00:00
Andrew Malsbury
4fbf448597 Updated balance sheet to use DB types 2023-10-09 22:15:27 +00:00
Andrew Malsbury
bb559a4bdb Fixed account type not showing by default on edit 2023-10-09 21:42:03 +00:00
Andrew Malsbury
9c099f7f98 Account Types bug 2023-10-09 21:24:31 +00:00
Andrew Malsbury
d5e03f101a fixed what @wrongecho suggested. 2023-10-09 20:39:32 +00:00
Andrew Malsbury
aef4ec0d20 Post handling for add and edit 2023-10-09 20:32:19 +00:00
Andrew Malsbury
31043da039 add more default account types 2023-10-09 20:31:54 +00:00
Andrew Malsbury
e4fc7bca23 New settings menu 2023-10-09 20:31:31 +00:00
Andrew Malsbury
72da87e608 New Settings Screen 2023-10-09 20:31:21 +00:00
Andrew Malsbury
3ef045eea1 New Modal 2023-10-09 20:28:12 +00:00
Andrew Malsbury
a8e03d4660 Switched to DB controlled Account Types 2023-10-09 20:27:53 +00:00
Andrew Malsbury
69272a8800 added account type post handling 2023-10-09 20:27:28 +00:00
Andrew Malsbury
03c8f47cf0 added account types table 2023-10-09 20:27:09 +00:00
Andrew Malsbury
81f34e20d7 Updated Version 2023-10-09 20:26:48 +00:00
Andrew Malsbury
749281a3e8 Switched to DB controlled Account Types 2023-10-09 20:26:36 +00:00
Andrew Malsbury
8b6c909d95 Switched to DB controlled Account Types 2023-10-09 20:26:03 +00:00
Andrew Malsbury
f190e100e8 Switched to DB controlled Account Types 2023-10-09 20:24:54 +00:00
Andrew Malsbury
2ee87f0f66 Switched to DB controlled Account Types 2023-10-09 20:24:49 +00:00
johnnyq
537f18efd2 Fix Incorrect var when setting timezone 2023-10-08 20:03:16 -04:00
johnnyq
43dc95c55a Fix missing </div> in ticket when we tried to fix merge conflicts 2023-10-08 19:59:26 -04:00
Johnny
20602c6f89 Merge pull request #746 from wrongecho/telemetry-small-edits
Telemetry - Fix typo & add polite note
2023-10-08 19:55:56 -04:00
Johnny
ebbe1e18c7 Merge pull request #738 from wrongecho/contact-click-call
Contacts phone numbers - add tel: hyperlink for click-to-call
2023-10-08 19:55:43 -04:00
Johnny
fac9f9502a Merge pull request #736 from wrongecho/ir-agent-force-pw-reset
Add function to reset all user/agent passwords in case of IR
2023-10-08 19:55:30 -04:00
Johnny
dcd17c7556 Merge pull request #735 from wrongecho/contact-details
Contact small edits
2023-10-08 19:55:16 -04:00
Johnny
1f067c17c4 Merge pull request #733 from wrongecho/ticket-update-type-email-match
Ticket updates - Default to internal update if contact is agent
2023-10-08 19:54:19 -04:00
Johnny
edf6e18dc3 Merge branch 'master' into ticket-update-type-email-match 2023-10-08 19:54:14 -04:00
Johnny
d1a627c209 Merge pull request #732 from wrongecho/email-parse-domains
Email parsing for all domains registered under a client
2023-10-08 19:50:44 -04:00
Marcus Hill
22f14cd5e7 Telemetry - Fix typo & add polite note regarding importance of telemetry data 2023-10-08 21:30:15 +01:00
wrongecho
5b49d35f1a Update SECURITY.md
Add placeholder for 1.0
2023-10-08 20:13:42 +01:00
wrongecho
ac51e6a8ad Update SECURITY.md
Reword security policy, include an escalation process (forum private discussion)
2023-10-08 20:09:17 +01:00
wrongecho
f1b017fc46 Merge pull request #737 from o-psi/Update-readme-with-install-script
Update readme with install script
2023-10-08 19:34:39 +01:00
Andrew Malsbury
f241d247be Update oneliner to not save the install file.
Updated oneliner to pipe the script directly to bash.
2023-10-08 13:07:56 -05:00
wrongecho
cd006d0625 Update first-interaction.yml
Refer bugs/features/support to forum
2023-10-08 17:32:21 +01:00
wrongecho
57403e1707 Update bug_report.md
Refer bugs/features/support to forum
2023-10-08 17:29:01 +01:00
wrongecho
0f4f670f9c Update feature_request.md
Refer bugs/features/support to forum
2023-10-08 17:28:56 +01:00
wrongecho
4025cfdcea Update support.md
Refer bugs/features/support to forum
2023-10-08 17:28:53 +01:00
Marcus Hill
623ebc783c Contacts phone numbers - add tel: hyperlink for click-to-call 2023-10-08 13:35:13 +01:00
wrongecho
b9cadd508d Update README.md / Update readme with install script #737 2023-10-08 09:03:25 +01:00
wrongecho
92eabf1e70 Update README.md / Update readme with install script #737 2023-10-08 09:02:18 +01:00
Andrew Malsbury
605eda879d Updated wording 2023-10-08 02:09:26 +00:00
Andrew Malsbury
221a020ec7 Update Readme to suggest install script. 2023-10-08 02:06:54 +00:00
Marcus Hill
45b3311f54 Add function to reset all user/agent passwords in case of IR 2023-10-07 22:44:29 +01:00
Marcus Hill
dff0b689ce Add confirm to anonymise and archive 2023-10-07 20:48:40 +01:00
Marcus Hill
263382073d Contact small edits
- Adjust behaviour when selecting "Send user e-mail with login details?" (show reset link OR prompt user to change password if tech set one)
- Email wording change (remove ITFlow reference and replace with MSP name)
- Show contact PIN in the portal
- Bump password min length to 8 (and enforce on tech side)
- Bugfix undefined send_email value
2023-10-07 20:42:48 +01:00
Andrew Malsbury
1455e20fad Added Total Equities and Liabilities 2023-10-07 18:05:21 +00:00
Andrew Malsbury
6a485a95b4 Allows for negative numbers for credit cards 2023-10-07 17:32:34 +00:00
Andrew Malsbury
3e96751bf0 Bug - Liabilities is showing Assets total 2023-10-07 17:31:55 +00:00
Andrew Malsbury
d63da07122 Updated setup - Cash Account: current asset type 2023-10-07 17:21:31 +00:00
Andrew Malsbury
3a879088ae Add balance sheet to side nav 2023-10-07 16:16:04 +00:00
Andrew Malsbury
5d964c9282 New Balance sheet report screen 2023-10-07 16:15:50 +00:00
Andrew Malsbury
f8bc2ee4b4 Add "account_type" to accounts table 2023-10-07 16:15:02 +00:00
Andrew Malsbury
844a85cee7 Update DB 2023-10-07 16:14:39 +00:00
Andrew Malsbury
29e2e5e0d7 Update DB, and added comments for next new guy. 2023-10-07 16:14:28 +00:00
Andrew Malsbury
bc95bb4e15 Update Accounts screen to show type 2023-10-07 16:13:46 +00:00
Andrew Malsbury
db5eee0ebb Add type dropdown 2023-10-07 16:13:10 +00:00
Andrew Malsbury
ccb67d8e5d Add type dropdown, and update opening balance star 2023-10-07 16:13:00 +00:00
Andrew Malsbury
9551399b08 Update add and edit to accomodate type 2023-10-07 16:11:19 +00:00
Marcus Hill
69eef8220d Ticket update behaviour - Default to internal update when contact email matches the agent email 2023-10-07 16:10:00 +01:00
Marcus Hill
4ac7841882 Email parsing for all domains registered under a client
- Add support for email parsing/contact creation for all domains registered under a client in the domains module, rather than just the client main website.

- Additionally fix domain_created_at bug and move the new ticket auto-reply message to the email queue instead

Future work: Make ticket parsing work with HTML emails (HTML emails break agent notifs)
2023-10-07 15:51:58 +01:00
johnnyq
0c0d89c1a6 do not allow user logged in to edit their own user by clicking on their avatar under users 2023-10-04 23:00:46 -04:00
johnnyq
6760997beb Set Company Timezone properly upon login 2023-10-04 22:38:29 -04:00
johnnyq
f842d2578f Add Software Key to export client pdf 2023-10-04 22:15:35 -04:00
johnnyq
8cfa0e97d4 Allow ticket priority and status to be searchable in main tickets view 2023-10-04 22:02:08 -04:00
johnnyq
b839f188ef Allow Contact name, Vendor name and asset_name to be searchable under both client tickets and the main tickets view 2023-10-04 21:59:05 -04:00
johnnyq
7e595d9436 Fix table offset issue with Assets Listings 2023-10-04 00:38:28 -04:00
Johnny
435c789e7f Merge pull request #731 from wrongecho/password-rotation-report
Client logins/passwords - Add basic password rotation report
2023-10-02 17:55:04 -04:00
Marcus Hill
f49cdf3a35 Client logins/passwords - Add basic password rotation report
This basic report shows you which client login entries have not had their passwords changed/rotated in the last 90 days.
Password rotation is no longer encouraged for users memorising their own passwords. However, password rotation is essential for service/shared accounts commonly used by MSPs in situations where individual accounts aren't available/viable.
2023-10-02 22:24:42 +01:00
johnnyq
7abdf53e9f Add .ovpn files to allow upload file list 2023-10-02 11:44:06 -04:00
Johnny
1e47107ed0 Merge pull request #730 from wrongecho/improve-totp-security
Client logins/passwords - Ajax change + logging
2023-10-01 22:45:05 -04:00
Johnny
51316f8c1d Merge pull request #729 from wrongecho/login-password-changed-at
Client logins/password - Add tracking in DB when passwords are changed
2023-10-01 22:44:50 -04:00
Johnny
e02e5efbec Merge pull request #728 from wrongecho/ticket-notif-spacing
Agent new ticket notifs - add more spacing
2023-10-01 22:44:36 -04:00
Johnny
5cda6156d4 Merge pull request #727 from wrongecho/settings-user-prevent-self-mod
Users - Prevent modifying yourself via users.php, should use profile
2023-10-01 22:44:22 -04:00
Marcus Hill
041fcb5613 Client logins/passwords - Ajax change + logging
A few changes to the credential manager TOTP function:

- The "hover to view" function now sends the login_id to ajax.php, rather than the TOTP secret
- Viewing the TOTP code is now audited in the logs under Login/View TOTP
2023-10-01 16:32:57 +01:00
Marcus Hill
c768034a1b Client logins/password - Add tracking in DB when passwords are changed/rotated 2023-10-01 15:22:42 +01:00
Marcus Hill
526503d786 Agent new ticket notifs - add more spacing 2023-09-30 23:21:30 +01:00
Marcus Hill
d02d2d4e4a Users - Prevent modifying yourself via users.php, should use profile 2023-09-30 20:32:34 +01:00
johnnyq
203ef85997 Show MFA status in user listing 2023-09-30 15:24:46 -04:00
Johnny
f726df8f80 Merge pull request #726 from wrongecho/setup
Small adjustments to setup: add subheadings and links to docs
2023-09-30 14:10:00 -04:00
johnnyq
90ac7042ba Allow Assigning a contact to all assets in some cases where network or servers may be co-managed 2023-09-30 13:52:04 -04:00
wrongecho
67c181b14b Update first-interaction.yml
Mention GNU GPL
2023-09-30 17:41:04 +01:00
Marcus Hill
0bee5956dc Small adjustments to setup: add subheadings and links to docs 2023-09-30 17:07:21 +01:00
Marcus Hill
63ba33afde Small adjustments to setup: add subheadings and links to docs 2023-09-30 17:04:42 +01:00
Johnny
90327a959f Merge pull request #724 from wrongecho/misc-wording-edits
Small wording edits (sharing links, documents, updater)
2023-09-30 11:50:07 -04:00
Johnny
24707e89d5 Merge pull request #725 from wrongecho/fix-client-delete
Fix client delete function
2023-09-30 11:36:59 -04:00
Marcus Hill
33628d81a1 Fix client delete function 2023-09-30 15:42:00 +01:00
Marcus Hill
c3dd9a80b6 Fix client delete function 2023-09-30 15:33:48 +01:00
Marcus Hill
9bb6e0b1c7 Touch-ups 2023-09-30 13:57:48 +01:00
Marcus Hill
2924791538 Codesmell 2023-09-30 13:55:49 +01:00
Marcus Hill
ac5b6c5424 Enhance git fetch error: include error on page if possible 2023-09-30 13:52:46 +01:00
Marcus Hill
05f25b3ebf Enhance git fetch error: include error on page if possible 2023-09-30 13:51:39 +01:00
Marcus Hill
ff161ab47b Small wording edits
- Ajax: Make link sharing text clearer/friendlier, include company name in subject and shared item description in body to help legitimise the message from spam
- Client doc details: Make edit summary text smaller
- Update: Enhance git fetch error wording, mention forum for support
2023-09-30 13:41:41 +01:00
johnnyq
e5e549482c Removed horizontal line on the botton of all the side navs 2023-09-29 22:44:26 -04:00
johnnyq
375d5af974 Fix issue with roundToNearest15 Function would break php if the time worked was empty 2023-09-27 16:01:44 -04:00
johnnyq
f914fbb96f Fix current_version var in cron.php when telemetry is configured this was caused by the cron not know what its working directory was added change to current working directory 2023-09-27 12:15:12 -04:00
johnnyq
f658fe0c6c Fix Close Ticket not showing when accounting module is disabled plus remove some extra markup not needed in ticket.php 2023-09-27 11:50:27 -04:00
johnnyq
31c9a6ad6c Fix invoice ticket price issue for auto price divide client rate into 4 to acommodate 15 Min increments 2023-09-26 18:13:00 -04:00
johnnyq
8ebe7eda03 Changed roundUpTo15 function to just round to the closest 15 2023-09-26 17:59:11 -04:00
johnnyq
d82e6f99ab Reworked how watchers get added and edited 2023-09-26 16:58:46 -04:00
johnnyq
e1ef89a9a4 Added DHCP option to IP Address field 2023-09-26 16:40:24 -04:00
johnnyq
498f9c7209 Changed button text from Show Archived to just Archived 2023-09-26 15:33:22 -04:00
johnnyq
8b3adae49d Dropdown UI fix icon alignment 2023-09-26 15:31:20 -04:00
johnnyq
7848043a40 shorted show_archive to just archived 2023-09-26 15:28:26 -04:00
johnnyq
35055489e5 Added Show Archived Button to contacts, setup logic to work in other List views as well 2023-09-26 15:24:31 -04:00
johnnyq
f8cdb79114 Moved import and export contact to the New Contact button dropdown as its not used as often and clear space for multi action or further search options 2023-09-26 14:56:26 -04:00
johnnyq
477e092b27 Updated client portal ticket details and document detail to use prettyContent js function 2023-09-26 14:28:36 -04:00
johnnyq
51489c2420 Update and move pretty tables function to a seperate js file and also add img-fluid to <img> tags so images dont run off the page and also update ticket details page with prettyContent function 2023-09-26 14:22:58 -04:00
johnnyq
1a5cd14208 Added format tables in document templates 2023-09-26 13:55:59 -04:00
johnnyq
48d8fdd760 Major UI update on Document Details, do not use TinyMCE to display document, created js function to add class table to tables for nicer look. Redesigned the Header 2023-09-26 13:47:18 -04:00
johnnyq
8b403613a8 updated document templates to include created by and other UI updates 2023-09-26 13:17:10 -04:00
johnnyq
f6d032f1d2 Moved Document Templates to settings 2023-09-26 12:55:38 -04:00
johnnyq
c8d1d4d5e1 Restore Client Delete functionality for clients for compliance sake 2023-09-26 12:01:49 -04:00
johnnyq
4adc0c7cd1 Remove destructive client delete from the frontend, still present in the backend, fix the ticket assign to no show active users 2023-09-25 12:20:42 -04:00
johnnyq
6af002122a Remove Relations on document when deleted or archived, added Short description field to summerize document changes or summerize a document, add header to Document Details showing Title, Date Created, Prepared by 2023-09-24 22:29:48 -04:00
johnnyq
26196a18e7 Updated DB Structure in Documentents to allow for created, updated by and document_description 2023-09-24 20:38:42 -04:00
johnnyq
c051afd52c Count the documents in the root folder as well 2023-09-23 19:43:11 -04:00
johnnyq
1218094270 When deactivating Shared Link delete it 2023-09-23 19:16:19 -04:00
johnnyq
0312a5f957 Client Side UI: Removed the black on white on black badge counters they were just to distracting changed it to a more suble light number, also merged side alert badges 2023-09-23 19:11:08 -04:00
johnnyq
51b2f6b4e5 Document Versioning: When opening a versioned document clearly define it is an archive file and the date it was archived at the top of document details 2023-09-23 18:18:03 -04:00
johnnyq
3b59f31d86 Fix Document Versioning not carrying related items 2023-09-23 18:09:43 -04:00
johnnyq
6b22390604 Tweaked Document Versioning logic, this update will update the db to update all exisiting document to update document_parent with the same primary_key ID 2023-09-23 17:57:06 -04:00
johnnyq
8d9f031cab Feature: Document Versioning is here! 2023-09-23 15:54:31 -04:00
johnnyq
61c9c0c8b9 Feature: Automatically calculate tickert to invoice based off time worked rounded up to the near 15 min mark multiplied by Client Rate, Changed all Price, cost fields to use text field with numeric patterns instead of number fields, set pricing to always display 2 decimal spots 2023-09-22 15:19:05 -04:00
johnnyq
1ccaa936ac Removed number type on 2FA input field replaced with text and inputmode='numeric' pattern='[0-9]*' 2023-09-22 12:43:18 -04:00
johnnyq
a8b3b24fba Added Document Revsion placeholder under document details also merged card and card-body div class to reduce indentation better code readability 2023-09-22 12:16:11 -04:00
johnnyq
9aa62a8b36 Add Vendor, asset and watchers now work as a 1 click under ticket details 2023-09-21 20:01:07 -04:00
johnnyq
b9fe774fe6 Reworked Markup code under ticket details, added frontend to change Vendor and asset 2023-09-21 18:50:34 -04:00
johnnyq
ba6e79dc8c Feature: Added Document Rename Modal to Document Listing 2023-09-21 17:03:53 -04:00
johnnyq
0bc10a30e8 Fix issue with login being restricted if HTTPS_ONLY is True and SSL is terminated at a proxy and then forwarded to ITFlow App as HTTP 2023-09-21 12:00:46 -04:00
Johnny
82893c8c72 Merge pull request #720 from wrongecho/start-email-customisation-basics
Ticketing: Custom subject/body example
2023-09-21 01:13:20 -04:00
johnnyq
ee79e43fad Do not count new Clients or Vendors on the dashboard if they were archived 2023-09-20 18:55:38 -04:00
johnnyq
cea210bcea Added asset_uri field to the API 2023-09-20 16:39:55 -04:00
johnnyq
d31127c137 set current code to an intval since its a number only 2023-09-20 14:58:05 -04:00
johnnyq
40d34bb71d Set 2FA Field on login to a number field so it only shows the numbers on a mobile phone 2023-09-20 14:53:07 -04:00
johnnyq
5938925a35 Added an error if accessing ITFlow by HTTP:// and is set to true 2023-09-20 14:51:29 -04:00
johnnyq
150defe815 You can now link files to documents 2023-09-19 23:35:10 -04:00
johnnyq
ca82a567d7 When client replies to a ticket via email update the status to Client-Replied 2023-09-19 18:29:17 -04:00
johnnyq
3bd8842171 Add 2FA code for Login/Password sharing 2023-09-19 18:21:57 -04:00
johnnyq
6bccc61b4a Display Asset Icon in asset Details 2023-09-19 18:00:10 -04:00
johnnyq
f3b949499d Client Assets now link to asset details page when click upon 2023-09-19 17:47:38 -04:00
johnnyq
ff281c923e Further additions to asset_details 2023-09-19 17:43:42 -04:00
johnnyq
5f779c33a2 Started working on a asset details page similar to contact details 2023-09-19 17:18:38 -04:00
johnnyq
f897705135 Fix 3 Letter Client Abbrevation function to remove htmlentity characters to fix ' being replace with a 0 2023-09-19 16:24:41 -04:00
johnnyq
0c0cb2cec9 Added UI support for linking assets, contacts, and licenses to Documents 2023-09-19 15:55:35 -04:00
johnnyq
5d74226762 Fix unlinking lock file 2023-09-19 11:40:11 -04:00
johnnyq
946f8d0b97 Initial start of Maintenance under settings 2023-09-19 11:39:11 -04:00
johnnyq
080a79c59d Fix Replicating email opps 2023-09-19 11:10:51 -04:00
johnnyq
65cf8519d0 Added file locks on the mail queue and ticket parse cron jobs to prevent over runs, reverted last commit back to not marking all messages in ticket parse as read 2023-09-19 10:51:52 -04:00
johnnyq
d56c8a91d1 Fix a possible race condition with duplicating tickets: Revert marking Email body peeking and flag all other emails not matching the ticket parser 2023-09-19 02:13:46 -04:00
johnnyq
5990f2e53a Bump TinyMCE from 6.4.2 to 6.7.0 2023-09-18 20:56:23 -04:00
johnnyq
40ced0f748 Updated the UI for downloading and displaying ticket attachments under ticket replies 2023-09-18 19:14:41 -04:00
johnnyq
f2a3c54ed7 Do not change ticket status upon ticket reply, just update the ticket update timestamp 2023-09-18 18:51:54 -04:00
johnnyq
2e12c3e9c1 UI Fix issue with browser status covering bottom portion of the side navs 2023-09-18 17:12:06 -04:00
johnnyq
a0f46cc049 If no contact selected give option to add one under ticket details 2023-09-18 16:36:35 -04:00
johnnyq
485bb68055 A Ticket Contact is now optional 2023-09-18 16:29:19 -04:00
johnnyq
d713031545 Priority and Contact are now clickable and changeable within ticket details 2023-09-18 15:07:12 -04:00
johnnyq
301d798963 You can now change ticket priority, contact or ticket Assignment by clicking on the element in the ticket listing 2023-09-18 13:23:21 -04:00
johnnyq
6109933f42 Updated Notification titles 2023-09-17 21:26:31 -04:00
johnnyq
827b880b28 Fixed edit scheduled ticket updated shoertenClient function to be even more intelligent 2023-09-17 20:08:41 -04:00
johnnyq
1b90a005e4 Added a php function to intelligently shorten a clients name to 3 characters 2023-09-17 19:49:09 -04:00
johnnyq
0987f3121f fix Pending tickets notification 2023-09-17 19:00:31 -04:00
johnnyq
40aaddd09b Update cron to Create notification of tickets pending assignment 2023-09-17 18:55:44 -04:00
johnnyq
8fa76daf3a Update cron ticket parser to set new ticket status to Pending-Assignment instead of Open 2023-09-17 18:42:17 -04:00
johnnyq
fdc7416ae9 Wording 2023-09-17 18:38:46 -04:00
johnnyq
beaa56dc36 Removed Ticket assignment through edit ticket, has to be done within the ticket itself, properly update the status to assigned and pending-assignment based off whos assigned to the ticket 2023-09-17 18:36:48 -04:00
johnnyq
fed51928c7 Updated Status Badge Colors 2023-09-17 18:10:21 -04:00
johnnyq
b23631226b Updated and added more descriptive Ticket Statuses 2023-09-17 18:06:07 -04:00
johnnyq
dbb28a9a4c Added new ticket status array for better communication and sorting 2023-09-17 17:25:28 -04:00
johnnyq
077fc1cf35 Added additional fields to cvategories for icon support and sub category support 2023-09-17 17:16:20 -04:00
Marcus Hill
2b6be6ba45 Ticketing: Add example logic for how we might allow customised subject/ticket body 2023-09-17 12:00:27 +01:00
wrongecho
d4c71955c6 Merge pull request #718 from ColDog5044/readme-release-update
Update estimated release month in README
2023-09-16 23:21:15 +01:00
johnnyq
6bd2919c18 Do not mark unprocessed email as read 2023-09-15 17:02:07 -04:00
Collin Laney
8e714e7afa Update estimated release month in README
Browsed the ITFlow Forum to find the estimated release month. Changed July to December. https://forum.itflow.org/d/257-v10-roadmap

Keep up the good work
2023-09-14 21:09:23 -04:00
johnnyq
deb5e87630 Tidy Queries and moved client to the ends of each entity in global search 2023-09-12 13:15:07 -04:00
johnnyq
19e9c3eeb5 Added Assets to Global Search 2023-09-12 12:51:00 -04:00
johnnyq
15d433f1d9 Invoice are now searchable via global search 2023-09-12 12:06:02 -04:00
johnnyq
7d1cfc586d Revert last commit invoice quote and recurring were already searchable by its concat prefix and number 2023-09-12 11:31:23 -04:00
johnnyq
878582f7c5 Allow to search via invoice, quote, recurring numbers 2023-09-11 18:46:43 -04:00
johnnyq
43fcf86a41 Fix 2023-09-11 18:22:21 -04:00
johnnyq
3f5c1c270a Fix Certificate Renewals 2023-09-11 18:20:59 -04:00
johnnyq
ba09ea7c67 Opps fix 2023-09-11 16:13:18 -04:00
johnnyq
f44641c5e4 Sort Client tags alphabetically when being show under client details, client listing and ticket details 2023-09-11 16:01:47 -04:00
johnnyq
7561364e91 remove get Cert Expiry date from cron job as its in functions now 2023-09-11 15:32:17 -04:00
johnnyq
9028f219b9 Moved get Cert Expiry date to functions.php 2023-09-11 15:31:43 -04:00
johnnyq
b80d730910 Added Cron task to update Certificate Expiry fields 2023-09-11 15:21:16 -04:00
johnnyq
b77886cc7e Bump PHPMailer from 6.8.0 to 6.8.1 2023-09-11 13:38:57 -04:00
johnnyq
3b645fc5fb Added missing asset description under client details 2023-09-11 13:07:39 -04:00
johnnyq
277c5bad68 Also subscribe the mail folder so it shows up under mail folders 2023-09-10 22:06:22 -04:00
johnnyq
f4963cbc45 Change folder name for ITFlow Proessed mail to ITFlow and put in the root instead of INBOX Folder. Also dont flag all other mail 2023-09-10 21:41:35 -04:00
johnnyq
2c14ae1a76 Added more padding to client overview cards 2023-09-10 20:32:05 -04:00
johnnyq
9753b96fed Fix mismatch of word URI and URL to just URI, fix it to not removed Service:// 2023-09-09 23:57:55 -04:00
johnnyq
bc1e2f1ea4 Updated DB schema with the new asset_uri 2023-09-09 23:43:12 -04:00
johnnyq
747e793e54 Added Asset URI can be used for a remote link 2023-09-09 23:40:18 -04:00
Johnny
be7492ae73 Merge pull request #714 from wrongecho/qr-charts-api
Google Charts - Use HTTPS instead
2023-09-09 14:13:20 -04:00
Johnny
a5fd5a2068 Merge pull request #716 from wrongecho/ticket-api-create
API: Tickets
2023-09-09 14:12:11 -04:00
Marcus Hill
c489a85fc0 API: Tickets
Add Create API endpoint for tickets.

Supported fields:
- Client ID
- Client Contact
- Subject
- Details
- Priority
- Agent assignee
- Vendor ID
- Vendor ticket ref
2023-09-09 15:28:18 +01:00
wrongecho
89d4f85869 Merge pull request #715 from wrongecho/asset-import
Bug fix: Asset import
2023-09-09 12:08:18 +01:00
Marcus Hill
19e159e9fd Bug fix: Asset import 2023-09-09 11:53:12 +01:00
Marcus Hill
a593e4cbbb Use HTTPS instead (eventually to move this into a local library) 2023-09-09 08:33:29 +01:00
johnnyq
6cb3d8f9d0 Truncate Client Name on client side nav 2023-09-08 01:51:29 -04:00
johnnyq
21a60c0619 Added confirm delete on delete contact 2023-09-08 01:15:12 -04:00
johnnyq
3d5c09abd0 Added a mail resend option under mail queuer it reset the the failed count to 3 2023-09-07 19:31:18 -04:00
johnnyq
85c1dede07 Show password field when local is selected for both edit and add contact 2023-09-07 18:18:27 -04:00
johnnyq
420647d481 Seperated domain refresher to seperate cron job this will need to be added manually if you want domain info to be refreshed, did this because sometimes it would break 2023-09-07 17:51:35 -04:00
johnnyq
3c8c173427 Fix Bad column count error upon importing passwords via CSV 2023-09-07 17:10:50 -04:00
johnnyq
6d1420712d Minor UI/UX update on mail settings 2023-09-07 16:46:36 -04:00
johnnyq
5f53082900 Spelling fix 2023-09-07 16:40:52 -04:00
johnnyq
0ae3a7fed1 Added more common net terms 2023-09-07 16:39:17 -04:00
johnnyq
718605dd8c Removed Mail from settings under ticket, invoice and quote settings as this is all configured under mail settings now 2023-09-07 16:28:36 -04:00
johnnyq
7dee46eee9 Changed company icon from a building to a briefcase 2023-09-07 15:50:20 -04:00
johnnyq
3e039f8664 Added Timezone selection under setup 2023-09-07 15:49:04 -04:00
johnnyq
e56d78b0a8 Added timezone selection to localiztion settings 2023-09-07 15:41:01 -04:00
johnnyq
44508cfa7c Moved Company Details settings localiztion settings to its own seperate settings called localiztion 2023-09-07 15:22:16 -04:00
johnnyq
b625400638 Renamed setting side nav to administration more suitable than settings 2023-09-07 15:06:05 -04:00
johnnyq
90b483e424 Moved Calendar, Trips and Reports under More sub heading on side nav 2023-09-07 14:44:36 -04:00
johnnyq
e1e966806c Added Login Description to Contact details to mimic client passwords 2023-09-06 11:23:42 -04:00
johnnyq
725370408c Decreased Content padding for mobile view, also decreased card body content in clients for mobile 2023-09-06 02:11:32 -04:00
johnnyq
903efec1dd When local auth is selected show the password box 2023-09-06 00:49:31 -04:00
johnnyq
747b7de143 Feature: Force MFA Part 3 - Enforce MFA by redirecting users to their user_profile to setup MFA if Force MFA is checked, next up is to lock them there until 2FA is set 2023-09-06 00:08:21 -04:00
johnnyq
17c8a9ab0c FEATURE: Force MFA Part 2 - Added to add, edit user 2023-09-05 23:44:42 -04:00
johnnyq
2a142f1c42 FEATURE: Force MFA Part 1 - DB Structure 2023-09-05 23:23:16 -04:00
johnnyq
8fb211c2dc Keep current view when switching between folders 2023-09-05 23:16:14 -04:00
johnnyq
eb1048ea4a Added Confirmation to Ticket Details Page, Closing ticket archiveing reply deleting etc 2023-09-05 19:04:43 -04:00
johnnyq
54c1befed9 Added Confirmation to Delete and Archiving tasks, also fixed broken trips page 2023-09-05 19:02:52 -04:00
johnnyq
4b368ee5af FEATURE: Confirmation Modal only grab clients initials for client side nav 2023-09-05 18:26:15 -04:00
johnnyq
316afa5603 Top bar is now fixed by default also fixed markup for side top headers 2023-09-05 17:19:02 -04:00
johnnyq
97521d1df7 added more actionable notifications 2023-09-05 16:44:31 -04:00
johnnyq
52b0a17e02 added more actionable notifications 2023-09-05 16:42:33 -04:00
johnnyq
853fbf0ba7 Ticket Notifications now are clickable and will go to the ticket details 2023-09-05 16:23:10 -04:00
johnnyq
7a27e5f6d2 FEATURE: Actionable Notifications Part 1 - Added Notificaiton Action to the DB this will allow notifications to become actionable 2023-09-05 16:12:31 -04:00
johnnyq
b1a9dda896 Ticket update bar Formatting Fix 2023-09-05 15:33:03 -04:00
johnnyq
d978e475bb Removed Closed from the Ticket Dropdown as it was accidenally hit sometimes 2023-09-05 15:31:09 -04:00
johnnyq
a5b034f877 Added Ticket Watchers card to the ticket details side bar 2023-09-05 15:25:25 -04:00
johnnyq
3513173ad0 Dudup Pagination requirement 2023-09-05 14:48:58 -04:00
johnnyq
941cbd37be Add Pagination to File Grid / Thumbnail View 2023-09-05 14:46:51 -04:00
johnnyq
baea5ed997 Fixed issues with ticket notifications 2023-09-05 13:53:42 -04:00
Johnny
d76f864c56 Merge pull request #713 from wrongecho/anonymise-contact-2
Auditing bugfix
2023-09-05 11:45:42 -04:00
Marcus Hill
06c88a0c8f Bug fix: Log entries auditing tickets created by agents now correctly log under the client 2023-09-03 22:09:58 +01:00
Johnny
0c4cded64e Merge pull request #712 from wrongecho/anonymise-contact
Add Anonymize Contact feature
2023-09-03 12:42:33 -04:00
Marcus Hill
b500556403 Add Anonymize Contact feature
- Contact name is redacted
- Contact details are removed
- Contact name/email is redacted from tickets & logs
- Contact is archived
2023-09-03 17:02:42 +01:00
wrongecho
1370ac3d6c Merge pull request #711 from wrongecho/portal-sso-fix
Fix Client Portal AAD SSO Button
2023-08-31 20:24:03 +01:00
Marcus Hill
dd43d8fd26 Adjust Client Portal AAD SSO Button to be HTML rather than Javascript due to CSP blocking inline JS. 2023-08-31 20:20:49 +01:00
johnnyq
81029e4605 Agent Resassign Ticket Email notification now uses the new mail queue system 2023-08-29 14:20:05 -04:00
johnnyq
34a4f27b19 Close Ticket Email notifications now utilize the new mail queue system 2023-08-29 13:23:36 -04:00
johnnyq
353b082f0c Converted Create Ticket Email Notification to the new mail queue system 2023-08-29 12:56:00 -04:00
johnnyq
1e254c9de4 Fix Broken domain listing 2023-08-28 18:23:18 -04:00
johnnyq
0898732ee7 Added more archiving capabilities across the board also dont show delete if folder is not empty, still need to add show archived data 2023-08-28 16:21:09 -04:00
johnnyq
a959f588f3 Updated hopefully everywhere for account so account_archived works properly also do not allow archiving of account if equals online payment account 2023-08-27 17:50:10 -04:00
Johnny
1c5398d85e Merge pull request #709 from wrongecho/new-ticket-notifications
Add notify by email function when a new ticket is created
2023-08-27 15:53:41 -04:00
Johnny
c070a14b0e Merge pull request #708 from wrongecho/link-backup-docs
Link to the backup docs when informing users to perform backups
2023-08-27 11:59:32 -04:00
Marcus Hill
b7108436fd Add notify by email function when a new ticket is created 2023-08-27 12:24:15 +01:00
Marcus Hill
42b5d82e2c Link to the backup docs when informing users to perform backups 2023-08-27 10:08:52 +01:00
Johnny
ac023a1eaa Merge pull request #706 from chandachewe10/master
Copy Updated Currencies from setup.php to get_settings.php
2023-08-26 10:39:07 -04:00
chanda chewe
bfae617d6e Copy Updated Currencies from setup.php to get_settings.php 2023-08-26 14:15:54 +02:00
johnnyq
90a3644eb9 Prepend Re: to ticket reply subject lines 2023-08-25 22:46:02 -04:00
johnnyq
eb98e82505 Remove tag icon top client header 2023-08-25 21:23:10 -04:00
johnnyq
f3c571f4eb Added Border on top of Card headers in Client Top Header 2023-08-25 21:16:35 -04:00
johnnyq
7b4efb4f17 Another Update to client header it does take little more space than the last one but it is collapsable, uncollapsed by default 2023-08-25 20:54:31 -04:00
johnnyq
0cfbe5f9f9 Client Header UI/UX Improvements: Reduced margin and padding, reduced font size in billing and support items, reworked some of the HTML code 2023-08-25 17:43:00 -04:00
johnnyq
38f31f3599 Updated more icons 2023-08-25 15:39:33 -04:00
johnnyq
125bc02323 Changed Zip / Postal to just Postal, chnaged locale to Language with a better icon and do not shot language code during select 2023-08-25 15:11:37 -04:00
Johnny
f6778b5ac1 Merge pull request #705 from chandachewe10/main
Main
2023-08-24 20:56:51 -04:00
johnnyq
6858d1f293 Feature: Vendors can now be linked to documents 2023-08-24 17:03:45 -04:00
chanda chewe
4d563da860 Added single missing quotes to currecies 2023-08-24 21:32:04 +02:00
chanda chewe
3b63290911 Added single missing quotes to currecies 2023-08-24 21:26:33 +02:00
chanda chewe
d931205798 Added single missing quotes to currecies 2023-08-24 21:24:49 +02:00
chanda chewe
2c807f433c Added single missing quotes to currecies 2023-08-24 21:22:14 +02:00
chanda chewe
37ad8cfd7f Added single missing quotes to currecies 2023-08-24 21:18:21 +02:00
chanda chewe
a70f20ff20 Added single missing quotes to currecies 2023-08-24 21:14:20 +02:00
johnnyq
6325301a00 Remove Licene Actions from Contact details this should be modified in licneses also removed the Login link with the asset as this can cause dupelicate assets if more than 1 password is assigned to an asset. This is due to 1 to 1 relation and really needs to be many to many relationship 2023-08-24 14:44:50 -04:00
johnnyq
01164e5415 Fixed Duplicating Licenes issue under client contact details page. This was becuase it was linking logins with licenses so if you had 5 logins for the license it would dupe 5 times. I need to change this code to be many to many relation in future. 2023-08-24 14:33:18 -04:00
johnnyq
597b7575d6 Reworked mail settings to include all mail related thing to be in one spot and easy to understand Also updated test email to test email from each email from address configured 2023-08-24 13:23:03 -04:00
chanda chewe
19e355f1a1 Added Missing Currencies 2023-08-24 10:52:20 +02:00
chanda chewe
2c3ac9d554 Added Missing Currencies 2023-08-24 10:03:44 +02:00
chanda chewe
c79c19bf8d Added Missing Currencies 2023-08-24 09:57:31 +02:00
chanda chewe
549fe8cc05 Added Missing Currencies 2023-08-24 09:37:00 +02:00
chanda chewe
44d84d2273 Added Missing Currencies 2023-08-24 09:25:49 +02:00
chanda chewe
f2a5963d84 Added Missing Currencies 2023-08-24 09:24:46 +02:00
chanda chewe
606307d255 Added Missing Currencies 2023-08-24 09:23:39 +02:00
johnnyq
0377eeb94e Add some padding between search and folders on phones in Client files and documents 2023-08-23 18:17:53 -04:00
johnnyq
12bbfd1db1 Add select2 Class on folder 2023-08-23 18:12:59 -04:00
johnnyq
f88f04edd8 Feature: Added Folder support for files 2023-08-23 18:02:51 -04:00
johnnyq
d200575aec Updated info to include only max 20 files can be uploaded at once 2023-08-23 16:52:57 -04:00
johnnyq
03e6e31f8c Also added 500MB Limit 2023-08-23 16:51:10 -04:00
johnnyq
1083ac88d9 Create some javascript that limits the amount of files to 20 that can be uploaded at once. 2023-08-23 16:48:42 -04:00
johnnyq
811f253470 DB Dump, store file hash in the db 2023-08-23 16:27:59 -04:00
johnnyq
a95b32a57e Upon upload the file contents are not hashed in Sha256 and used for the reference file in the DB 2023-08-23 16:10:15 -04:00
johnnyq
2633477575 Added Commented code to has the file contents itself instead of the name 2023-08-23 16:04:42 -04:00
johnnyq
4ec7c686c3 Updated the checkFileUpload fucntion to use SHA256 instead of MD5 for file reference and check file ext before checking size, also adding some error returns 2023-08-23 15:59:10 -04:00
johnnyq
30a6b3dadf Added a hint about selecting multiple files for upload 2023-08-23 15:50:51 -04:00
johnnyq
0897217357 Major UI / UX enhancements to Client Files. Files are now searchable can select between thumbnail and list view, pagination enabled, file renaming capabilities 2023-08-23 15:43:47 -04:00
johnnyq
037ae820a1 Removed old files upload code 2023-08-23 13:25:22 -04:00
johnnyq
44c4beba1e Feature: You can now upload multiple files at a time in the client files section 2023-08-23 13:24:05 -04:00
johnnyq
8f9753489f Updated contact extention ui 2023-08-23 10:41:14 -04:00
johnnyq
8fdc93ebde Show contact extention in the listing 2023-08-23 10:37:04 -04:00
johnnyq
1cf015c0b7 Use correct icon for mail queue 2023-08-22 18:36:56 -04:00
johnnyq
8402ca99ae Use correct icon for audit logs 2023-08-22 18:34:13 -04:00
johnnyq
c43b22ddd5 Fix initial DB Structure was causing new installs to direct to a non existent page dashboard.php 2023-08-22 18:19:15 -04:00
johnnyq
94e56f6d68 fixed an old unused var in client_locations which was allowing someone to delete a primary location which shouldnt be allowed 2023-08-22 15:48:55 -04:00
johnnyq
715938f367 Update login cred share guest sharing look 2023-08-22 14:19:28 -04:00
johnnyq
e5fea3ab9b Further cleanup of the guest sharing page 2023-08-22 13:55:42 -04:00
johnnyq
b361b3a384 Updated Guest sharing removed irrelevant info such as warnings about this will expire and notes as this will be sent in the pre email message, Removed App name and sharing from the top. Formatted the Style into a card, Added Company Info at the footer 2023-08-22 13:41:04 -04:00
johnnyq
c49ac5eb80 oops fix, added company name to guest share 2023-08-22 13:22:56 -04:00
johnnyq
42e23b6f08 Fix issue with editing client if accounting module was disabled due to the handling of client currency 2023-08-22 12:45:52 -04:00
johnnyq
6231d7b43c Fix logic to always show tech dashboard if accountiong module is disabled 2023-08-22 10:57:21 -04:00
johnnyq
9a7bea6ef9 Fix logic for showing billing column under client Management User role is admin or accountant and Module Accounting / billing is enabled 2023-08-22 10:50:40 -04:00
johnnyq
e31a0269b3 Make Client visible note optional in sharing 2023-08-22 10:15:01 -04:00
johnnyq
7c1cb0f617 Updated Sharing to include Unlimited Time and the option to use 0 for unlimited views 2023-08-22 09:57:57 -04:00
johnnyq
3f9c7fe220 Fixed empty var Last_login 2023-08-21 18:49:42 -04:00
johnnyq
8ef806ed1c Fix php error in users listing while fetching the last log it would return error if empty 2023-08-21 18:39:41 -04:00
johnnyq
9368a3b58d Fix user agent var is guest view 2023-08-21 18:20:27 -04:00
johnnyq
583fe9807d Updated placeholders for SMTP user and pass to inform users to leave blank if no auth is required 2023-08-21 12:25:10 -04:00
johnnyq
2fa442028a Updated sendSingleEmail function to allow for authless email sending 2023-08-21 10:44:54 -04:00
johnnyq
1ed4eeaafc Remove extra bottom margin below error msg on client login 2023-08-20 15:43:39 -04:00
johnnyq
880e1be08c Did the same for client portal login as well center forgot password 2023-08-20 15:30:36 -04:00
johnnyq
1d0e2ad758 Removed some of the right and left padding to allow for larger login messages 2023-08-20 15:27:43 -04:00
johnnyq
709cec8d7e More Icon Updating and matching 2023-08-20 15:06:08 -04:00
johnnyq
2d0fe45898 Enhance the client name font and place an arrow next to client to better indicate client section will be revealed when clicked on 2023-08-19 14:48:40 -04:00
johnnyq
257d3c0c9b UI: Updated icons for the client side nav 2023-08-19 14:34:52 -04:00
johnnyq
b7fcfb90e5 UI: Updated icons in setting nav 2023-08-19 14:21:05 -04:00
johnnyq
ff840bdeb5 UI: Updated some side nav icons that were more suitable for the item 2023-08-19 14:08:26 -04:00
johnnyq
7c3d6fc07a Rename side nav items again as the new names just took too much precious UI space 2023-08-19 14:00:20 -04:00
johnnyq
c3fd6824bf More descriptive naming for the main side navigation menu 2023-08-19 13:50:34 -04:00
johnnyq
c02448dff2 Small UI/UX update used mt-1 for better spaceing than <br> made export an outline button and cleaned up the small font in clients listing page 2023-08-19 13:25:15 -04:00
johnnyq
3652e9da08 sort recent tickets by created date 2023-08-19 00:45:00 -04:00
johnnyq
c89dbb4df3 Properly format category name for HTML Displaying in budget 2023-08-18 20:37:41 -04:00
johnnyq
78de89271c Create Budget report 2023-08-18 20:36:23 -04:00
johnnyq
94a3a3fa0e Var Fix 2023-08-18 20:07:28 -04:00
johnnyq
35b3c844ad New Dashboard stat for recurring Invoice added for selected year 2023-08-18 20:06:07 -04:00
johnnyq
d4510ddafb Fix Number of clients added on dashboard not directing to the right page when clicked 2023-08-18 19:53:37 -04:00
johnnyq
c7e981646f Show recurring Monthly expenses on the dashboard 2023-08-18 19:48:54 -04:00
johnnyq
47753f4419 Fix wrong vars in budget 2023-08-18 19:36:44 -04:00
johnnyq
b1aa8d3a91 Feature Budget working need to add some more features down the line 2023-08-18 19:34:20 -04:00
johnnyq
adf313f183 Feature - Budgets - Part 1 - DB Structure Created 2023-08-18 18:21:25 -04:00
johnnyq
258287ae0c Fix Export Clients removed extra space in delimiter 2023-08-18 17:37:01 -04:00
johnnyq
4a36efce38 Fix issue with document not showing when sending a shared Link 2023-08-18 16:58:29 -04:00
johnnyq
0672063ddd Fix Incorrect var in mail_queue.php 2023-08-18 16:35:54 -04:00
johnnyq
169f542039 Show Alerts and Defaults in settings if module accounting is disabled 2023-08-18 16:26:36 -04:00
johnnyq
cd27decb37 Fix issue when sending shared links it was using the ticket_from_email_address instead of the generic Email address programmed in settings > Mail > SMTP > Mail from Email 2023-08-18 16:11:57 -04:00
johnnyq
5e88bd4b37 Fix Opps 2023-08-18 15:37:35 -04:00
johnnyq
0d497163fe Feature: Login Message now complete can be set in settings > security 2023-08-18 15:35:31 -04:00
johnnyq
b987782adb Feature - Login Message Part 1 - DB Structure 2023-08-18 15:07:39 -04:00
johnnyq
d7ab2b2fec Fix issue with umlaught characters causing the contact name not to display properly in ticket details 2023-08-17 21:04:18 -04:00
johnnyq
ed9cb5c997 Split Mail Settings into 2 form sections, one for SMTP and one IMAP 2023-08-17 20:54:54 -04:00
johnnyq
ce2ba6d3d2 Feature: Records per page is now user specific and persists with logout/login sessions 2023-08-17 19:42:42 -04:00
johnnyq
94caee4aa6 Updated all expirations within 90 days in client overview, stale tickets now use the updated date and not created date and now only show tickets that havent been updated within 3 days as stale, added descriptors to the client overview cards 2023-08-17 16:46:57 -04:00
johnnyq
7d06be0946 Feature - Recurring Expenses - Cron Completed, project finished 2023-08-17 16:03:52 -04:00
johnnyq
3ee38c3fdd Feature - Recurring Expenses - Phase 3 - Completed POST Logic and create edit modals 2023-08-17 15:08:25 -04:00
johnnyq
7527b6d6f8 Feature: Recurring Expenses - Part - Added Side Menu and Listing code 2023-08-16 18:31:52 -04:00
johnnyq
ba9c80cd7d Feature: Recurring Expenses - Part 1 - Initial DB Structure Created 2023-08-16 17:56:32 -04:00
johnnyq
a207e0bc9a Fix Pagination Record select not showing the full number on Chromium based Browsers, fixed up pagination for Mobile view as well 2023-08-16 15:18:59 -04:00
johnnyq
04e22a60ec Fixed Importing Passwords was missing the uri insert field Fixes #704 2023-08-16 14:47:25 -04:00
johnnyq
d9dbe718bd Allow the reuse of colors in tags 2023-08-16 14:37:35 -04:00
johnnyq
2915d7a1b7 Replicated reworked tags code logic under client details and ticket details 2023-08-16 14:07:25 -04:00
johnnyq
86c36e08ab client tag cleanup in add and edit modal 2023-08-16 13:56:35 -04:00
johnnyq
514b5348cb For Client Tags If no icon is present use a tag icon 2023-08-16 13:48:57 -04:00
johnnyq
67de80c97e Cleaned up client tags display logic 2023-08-16 13:47:14 -04:00
johnnyq
b2a154e97a Client Tags are now clicklable within the clients listing page to filter down based on tag 2023-08-16 13:37:50 -04:00
johnnyq
1d277da73c DB Structure Dump to include config_start_page 2023-08-16 13:24:45 -04:00
johnnyq
fda0d203ed Feature: Added Start Page functionality 2023-08-16 13:23:30 -04:00
johnnyq
f93dc32241 Removed the requirement for SMTP username and password since the IP can used as a trusted SMTP relay 2023-08-15 17:48:10 -04:00
johnnyq
7fd795e9fb Added Software Licences expiring within 30 days to client overview 2023-08-15 17:40:02 -04:00
johnnyq
43f016f70f Allow Extra file extentions to be uploaded, increased file upload hard limit in code from 20MB to 500MB 2023-08-09 16:38:53 -04:00
johnnyq
850c3f7942 Fix grammar on share link email 2023-08-07 15:28:03 -04:00
johnnyq
cc80d41964 Cleaned up the watchers Modals 2023-08-03 19:36:02 -04:00
johnnyq
427ed8e57b Replying to a ticket through the ITFLow interface it will also email the watchers 2023-08-03 18:28:17 -04:00
johnnyq
0aedf95892 Removed watcher_created_at field as its irrelevant 2023-08-03 18:08:06 -04:00
johnnyq
dd46c5bcab Ticket watchers can now be add and deleted 2023-08-03 18:03:39 -04:00
johnnyq
76b0954d25 Reissue Previous Fix 2023-08-03 00:37:42 -04:00
johnnyq
73ac6cb8aa Fix issue where recurring invoices that were not sent didnt show up in all recurring invoices 2023-08-03 00:30:00 -04:00
johnnyq
653fa01ecc Fixed issue with scheduled tickets breaking CRON removed invalid character, More work on Ticket Watchers 2023-08-02 16:36:39 -04:00
johnnyq
173230d250 FEATURE - Ticket Watcher - Added Dynamic Add/Remove Watchers Form under new ticket contacts tab 2023-08-01 13:49:15 -04:00
johnnyq
b6dc255f8d FEATURE - Ticket Watchers - Initial Commit for DB Structure for ticker wathers 2023-08-01 13:03:58 -04:00
johnnyq
8511cdd1fe Added the Ability to Toggle the Ticket Timer Pause / Play 2023-07-31 14:30:37 -04:00
johnnyq
2bd6b11f03 Fix Ticket Timer for editing a ticket response / reply 2023-07-31 14:09:12 -04:00
johnnyq
336805e16b Fix Ticket Timer for users that user 12 Hour AM/FM Format, converted from time field to text added icon for timer representation 2023-07-31 14:06:47 -04:00
johnnyq
b195da0f6e Add Move to Folder Option in documents list view 2023-07-31 13:39:58 -04:00
johnnyq
86bf7801e4 Removed Default Todays Date in Add Copy Refund Expense 2023-07-31 13:13:23 -04:00
johnnyq
e26fe1551f Add some facial expression to the update to date 2023-07-25 23:39:39 -04:00
johnnyq
7fe8aafcac Update Latest Updates Wording 2023-07-25 23:29:49 -04:00
johnnyq
2e77999b92 Vendor Templates now has checkboxes for the fields you would like to update globally meaning all clients using that vendor template make it easier for only updating a few fields globally instead of them all like unique fields such as account number or pin 2023-07-21 20:34:02 -04:00
johnnyq
cff56f6507 Update Debug to include all table stats and current DB Version 2023-07-20 17:38:35 -04:00
johnnyq
bd9b5bdc2f Hopefully fixed an issue during initial setup after entering DB credentials and writing the config.php files. This was possible due to a rac condition where intially ITflow install checks to see if it can write config.php to currect directory by actually writing a config.php file then deleting it. This could sometimes interfere with the creation of the config.php file in the next step 2023-07-17 14:33:43 -04:00
johnnyq
956a18b9bb USe Current Timezone and not UTC 0 when calculating 1 hour increments when adding calendar events fixes #567 2023-07-15 16:22:33 -04:00
johnnyq
e09c9cadb5 Added Expire Date field to Quotes also Do not show Guests Accept or Decline if Date is Expired 2023-07-15 15:33:08 -04:00
johnnyq
313191aeb2 On Recurring Invoice List Frequency column should be displayed after Amount which make more sense when reading it 2023-07-13 17:23:18 -04:00
johnnyq
67f5de1170 Fix accidentally zeroed out edit ticket modal 2023-07-13 17:09:08 -04:00
johnnyq
46f7960cd0 Fix issue where primary contact is not being automatically selected when creating a new ticket under client this was due to how we changed the way primary contacts are stored in the Database - Also added display of the contact title and if they are primary or technical. Also Sort Primary first then technical under ticket add or edit -- see here https://forum.itflow.org/d/207-tickets-broke-again 2023-07-13 15:04:14 -04:00
johnnyq
8fa7449084 Fix Creating Scheduled Tickets under Main Scheduled Tickets - Was assigning the primary contact the old way changed it to the new way 2023-07-12 16:32:34 -04:00
johnnyq
c5eb4bddd2 Fix Creating Ticket under Main Ticket - Was assigning the primary contact the old way changed it to the new way 2023-07-12 16:21:42 -04:00
johnnyq
cb20894fc0 Fixed Centering footer for Guest viewing invoices and quotes 2023-07-11 13:47:13 -04:00
johnnyq
13ebb6c627 Late fees will be applied if enabled as a seperate line item on each over due invoice. The late fees will be applied every 30 days after the initial overdue invoice this is done by running cron.php daily 2023-07-11 13:25:37 -04:00
johnnyq
bb16c4b7b8 Feature: Late Fees can now be assessed to unpaid invoices 2023-07-11 11:40:53 -04:00
johnnyq
eb1e792e77 Only Show Monthly Recurring based off the year selected and all previous years 2023-07-10 16:01:53 -04:00
johnnyq
bec2156fa2 Combine Montly Recurring and Yearly Recurring to together to create a new monthly recurring 2023-07-09 12:25:42 -04:00
johnnyq
1bacabc72b Prevent duplicate sort, order and page GET VARs in the URL when Clicking to Sort a field or Clicking a page number. We now unset the GET VAR arrays before recreating the URL GET Strings 2023-07-08 14:40:00 -04:00
johnnyq
e7572c9e8f Rename vars sb to sort, o to order, p to page. This makes the code easier to understand and brings consistency 2023-07-08 12:34:28 -04:00
johnnyq
8213ef1e24 Updated .gitignore added .gitkeep files to HTMLPurifier Cache Directories as git ignore empty folders - fixes https://forum.itflow.org/d/197-actual-answer-to-customer-in-email-is-missing/6 2023-07-07 18:57:45 -04:00
johnnyq
473cf14610 Sort logins marked important always first 2023-07-07 16:50:22 -04:00
johnnyq
c916e249bd Fix Viewing Invoices and Quotes from Client Portal in Edge Browser reversed the slashes from backslashes to forward slashes - see https://forum.itflow.org/d/198-customers-unable-to-view-invoices-client-portal-using-edge 2023-07-07 16:45:48 -04:00
johnnyq
9baf64964a Fixed Umlaughts in email subject with the new Mail Queue System 2023-07-06 15:25:10 -04:00
johnnyq
6ea31adb99 Removed Old Duplicate code for reply tickets as it was using the queue method and the old method 2023-07-06 15:09:52 -04:00
Johnny
b54a388c15 Merge pull request #702 from haymaker/imap-credentials
Feature update: add credentials for IMAP
2023-07-06 14:47:51 -04:00
Haymaker
0633107514 update db migration statements - somehow missed in prev commit 2023-07-05 22:35:34 -04:00
Haymaker
aa984b92ef add credentials for imap 2023-07-04 18:52:00 -04:00
johnnyq
448da5f393 Moved Ticket Replies to the new Mail Queue 2023-07-04 15:00:41 -04:00
johnnyq
12d1fc5cb8 Added HTML Line Breaks after Ticket Reply 2023-07-04 13:32:31 -04:00
johnnyq
379529c6af Fix Regression issue when replying to a ticket via the web app the content doesnt show in the email body see https://forum.itflow.org/d/197-actual-answer-to-customer-in-email-is-missing 2023-07-04 13:08:53 -04:00
johnnyq
7f2f9a3c9e Fix Regression Global Search 2023-07-03 21:56:19 -04:00
johnnyq
9d39ad2628 Fix broken calendar events due to the new contact_primary field being moved 2023-07-03 20:34:15 -04:00
johnnyq
9d7d78473f Removed primary_contact and primary_location from the clients table 2023-07-03 20:23:29 -04:00
johnnyq
a5100ea187 Update the remaining logic to take advantage of the moved contact_primary and contact_location fields 2023-07-03 20:16:39 -04:00
johnnyq
85c19e36c6 Updated client listing logic to work with the new contact_primary and location_primary vars 2023-07-03 18:12:26 -04:00
johnnyq
86ef22dfc9 Copy primary_contact and primary_location enties over to thier respecting tables through a DB update 2023-07-03 17:59:12 -04:00
johnnyq
957b5b583c Sort primary location at the top always 2023-07-03 17:41:43 -04:00
johnnyq
567c01ce3f Update logic for adding and editing primary location 2023-07-03 17:40:14 -04:00
johnnyq
18274d532e When Adding new client add contact as important as well, when assigning a new contact as primary contact label them as important updated the logic add and edit logic to include the new field primary contact field under contacts 2023-07-03 17:31:37 -04:00
johnnyq
70a080a24e Always Sort primary contact at the top and Important Contacts under the primary contact following normal contacts 2023-07-03 16:50:52 -04:00
johnnyq
b12e3677bd DB Structure Update This is the beginnings to move primary_contact and primary_location fields out of the clients table and into their respectable table. Created the fields in contacts and locations, next is to write SQL query to migrate and then update pieces of the codes in the App 2023-07-03 16:40:45 -04:00
johnnyq
66ec189fae removed - 2023-07-03 16:20:28 -04:00
johnnyq
457bc7d471 Feature - Accounting: Added option in account transfer to add selectable payments to transfer notes which is useful to keep track what checks were deposited in a bank transaction such as a deposit as most banks don't display each check in a deposit. 2023-07-03 16:18:01 -04:00
johnnyq
cf494a2f4e Removed Edit Modal Fucntion within document listing, it was causing documents listing to slow with large documents. Still can be edited when clicked into the document 2023-07-02 14:12:43 -04:00
Johnny
335ff27e06 Merge pull request #701 from wrongecho/post-split-1
Separate post.php into sub-module files
2023-07-02 13:49:04 -04:00
Marcus Hill
f6c4e72c86 Fix some codesmells 2023-07-02 15:07:50 +01:00
Marcus Hill
ebecdd3da2 Post.php - Separate 9k lines into separate files by sub-modules (e.g. ticket, invoice, expense) for easier development and troubleshooting 2023-07-02 14:56:12 +01:00
johnnyq
1f29d68ad5 Updated client Documents to use folder icon on the side nav and header. Update Date Format as well 2023-07-01 13:33:42 -04:00
Johnny
2b871e06f0 Merge pull request #700 from wrongecho/cron-ticket-closed-replies
Ticket parser: Better handle clients replying to closed tickets
2023-06-26 19:42:29 -04:00
Marcus Hill
0240d316e7 Ticket parser: Better handle clients replying to closed tickets 2023-06-24 22:10:06 +01:00
johnnyq
1ad1b35101 Mail Queue support added for sending welcome email to contact 2023-06-22 21:51:03 -04:00
johnnyq
7ddff0421a Mail Queue support added to Manual Quote Emailing 2023-06-22 21:28:20 -04:00
johnnyq
149db0e715 Mail Queue support added to adding payment to invoice 2023-06-22 20:54:38 -04:00
johnnyq
76c82128d9 Cleanup send invoie logic 2023-06-22 15:09:57 -04:00
johnnyq
2d0458a2f3 Fix some formatting and additonal white space before contact name in Ticket Details part 2 2023-06-22 11:05:24 -04:00
johnnyq
6ccbe67b59 Fix some formatting and additonal white space before contact name in Ticket Details 2023-06-22 10:57:14 -04:00
johnnyq
682407ad64 Trim white space before and after when adding password to a contact 2023-06-22 10:29:27 -04:00
johnnyq
db9c102f53 Trim white space before and after username and password and before encrypting when adding a client password 2023-06-22 10:23:44 -04:00
johnnyq
9d86c41bcb Added With payments of 600 or more text to vendor expense report 2023-06-21 16:28:42 -04:00
johnnyq
d15eabfee4 Rewrite Expenses by Vendor Report to combine SQL queries into one and sort highest first and add the all years option 2023-06-21 16:25:43 -04:00
johnnyq
e2923304ea Show hint on income for clients report with payments of 600 or more 2023-06-21 16:07:01 -04:00
johnnyq
ab67929a22 Add All Years Option to Income by Clients Report 2023-06-21 16:03:56 -04:00
johnnyq
a67a925868 Another SQL Attempt to fix Client Balance calc 2023-06-21 15:47:19 -04:00
johnnyq
db4c823fc8 Fix Report for Client Balance Query 2023-06-21 15:36:36 -04:00
johnnyq
d3b446706b Modified Report Client with a Balance to Sort Highest Balance First 2023-06-21 15:26:16 -04:00
johnnyq
0c7fbda127 Added Report Clients with a Balance 2023-06-21 15:22:17 -04:00
johnnyq
090ecf2e80 Fixed issue when hovering over a created calendar event the cursor does not change to a finger 2023-06-21 14:47:25 -04:00
johnnyq
b883b31194 Label Top 5 2023-06-21 14:21:56 -04:00
johnnyq
b39f115dd1 Only show Top 5 in the following Doughnut charts: Income and Exp By Cat, and Vendor Expense lump everything else into others if more than 5 cats exist this prevents the graphs from overflowing if you have 10 or 100s of vendors expense cats or income cats 2023-06-21 14:18:20 -04:00
johnnyq
4d90327c79 Created Mail Queue Logs / Viewer in settings, enabled manual send invoice to use the new queue system, now it logs the Email ID so you can reference it in the Queue to see if it sent, also do not send mail to blank billing contact emails 2023-06-21 12:09:32 -04:00
johnnyq
c6afe0b3cf Removed uneeded logging with the mail queue start and end logs 2023-06-20 20:50:55 -04:00
johnnyq
53f05a9469 Update the email status to sending before actually sending to prevent duplicate or more 2023-06-20 20:45:10 -04:00
johnnyq
63100d7cee Remove unessessary date vars and re-enable cron key check for the new cron mailer 2023-06-20 20:37:20 -04:00
johnnyq
8b372c20e0 Update new cron email queuer script to resend failed mail every 30 mins for each failed attempt up 4 attempts 2023-06-20 20:34:29 -04:00
johnnyq
72bc5b41be Added additonal DB field to mail queue for send attempts failed_at timestamp and status along with recipient to name 2023-06-20 19:54:18 -04:00
johnnyq
05f41d1798 Update email sent at field only if the email was sent 2023-06-20 19:37:42 -04:00
johnnyq
6f0505d7e9 cron process mail queue created, now need to convert some of the code over to use the new mail queuer system 2023-06-20 19:34:34 -04:00
johnnyq
75dd00c98c Shortened the document detail and contact detail breadcrumbs to show the root level being the client 2023-06-19 19:15:23 -04:00
johnnyq
bc4607fdb4 Sort Important Contacts first 2023-06-19 19:10:16 -04:00
johnnyq
d1876e829c Added asset description to the API for create and update 2023-06-19 16:34:44 -04:00
Johnny
2c7f6b1127 Merge pull request #699 from wrongecho/login-enhancements
Login page enhancements
2023-06-19 16:29:54 -04:00
Marcus Hill
7f5e63e518 Fix undefined error for company name 2023-06-17 16:16:10 +01:00
Marcus Hill
a966bf0282 Adjust content security policy 2023-06-17 16:13:02 +01:00
Marcus Hill
95cd0ebdc8 Adjust CSP 2023-06-17 16:01:15 +01:00
Marcus Hill
57dab27169 Login page enhancements
- Default to secure cookies (in case var is not defined in config.php)
- Enable content security policy
- Return HTTP 401 response code for invalid username/password combinations
2023-06-17 15:09:01 +01:00
Johnny
8a33a45d20 Merge pull request #698 from wrongecho/fix-braces
Functions.php - IP checker - braces
2023-06-14 19:17:46 -04:00
johnnyq
14b2c48b24 Fix a Syntax err 2023-06-14 19:09:05 -04:00
johnnyq
25f85486d4 Client Portal can now be enabled or disabled in settings > Modules > Enable Client Portal, it is enabled by default 2023-06-14 19:07:39 -04:00
johnnyq
8085f7cd90 User client Rate for price by default for Invoice Ticket 2023-06-14 18:44:24 -04:00
johnnyq
32c9a933ea Invoice Ticket design update, Added functionality for vendor ticket number, asset, login description and contact pin codes 2023-06-14 18:39:24 -04:00
johnnyq
cdbff0d7f6 Updated DB Structure to include asset_description, login_description, contact_pin and a table for the new email_queuing system 2023-06-14 16:59:01 -04:00
Marcus Hill
2c53faddd4 Add curly braces around if statement, adjust to exit for consistency 2023-06-13 20:36:32 +01:00
johnnyq
1b0aaf4d27 Update Document details to use TinyMCE Readonly mode on display. Add Print Button. UI Updates etc 2023-06-06 18:48:19 -04:00
johnnyq
c1ff4f6855 Add link to Telemetry Information to our docs page on the telemetry settings section of ITFlow 2023-06-06 12:21:22 -04:00
johnnyq
1db519d820 Updated Tickets to use timeAgo function along with stand DateTime 2023-06-05 12:38:25 -04:00
johnnyq
f64ab630fd Added TimeAgo Function to convert mysql DataTime to a human readable time like 2 weeks ago similar to other apps like facebook do it. Added to function to Recent Activity under client overview 2023-06-05 12:25:39 -04:00
johnnyq
ca61556c4f Updated Client Overview Removed Recently updated and replaced with recent 8 logs, updated padding and card size per element 2023-06-05 12:11:24 -04:00
johnnyq
40da8a2e69 Bold Important Passwords 2023-06-03 21:49:33 -04:00
johnnyq
6519913eed Bold Important Contacts 2023-06-03 21:47:57 -04:00
johnnyq
cb2b846418 New Tickets that have not been updated now have their whole rows bolded 2023-06-03 21:43:46 -04:00
Johnny
ad7133ddb8 Merge pull request #695 from wrongecho/recently-updated
Client Overview - Enhance Recently Updated section
2023-06-03 20:15:02 -04:00
Johnny
bc4d626a9e Merge pull request #694 from wrongecho/enable-login-key
Enable login key code
2023-06-03 20:14:50 -04:00
johnnyq
4e075b9762 Merge branch 'master' of github.com:itflow-org/itflow 2023-06-03 20:13:37 -04:00
johnnyq
48a660094c Updated setup to wotk with the automatically generated cron key used in the itflow install script 2023-06-03 20:13:17 -04:00
Marcus Hill
82056aee64 Codesmells 2023-06-03 22:00:52 +01:00
Marcus Hill
d86b5d8992 Client Overview - Enhance Recently Updated section
- Move the asset warranty expiring and stale ticket queries out of inc_all_client.php and into client_overview.php, there is no need to load this data on every page load - just for the overview
- Show recently updated documents (in addition to contacts/vendors)
- General tidy
2023-06-03 21:58:34 +01:00
wrongecho
acbc935519 client_login_add_modal.php - capitalize 'software' 2023-06-03 21:24:54 +01:00
Marcus Hill
1175cc4ade Enable login key code (see #680) 2023-06-03 21:04:43 +01:00
johnnyq
39b4bce09e Revert Tidy UI design as it was not very copy paste friendly 2023-05-31 16:59:14 -04:00
johnnyq
f2e518e745 Tidy UI for debug 2023-05-31 16:42:52 -04:00
johnnyq
76d426f793 Add WebServer version 2023-05-31 13:43:15 -04:00
johnnyq
0c9f50fbda Tidy debug 2023-05-31 13:37:43 -04:00
johnnyq
386eb0c382 Added Installed Modules, Database stats such as Number Tables, fields, rows and db size, php, mysql and OS Versions, along with upload directory stats including file count and size 2023-05-31 13:31:03 -04:00
johnnyq
eb99807214 Added Debug report under settings currently only reports Database structure differences between Git Master Repo db.sql and current database structure of the installed instance 2023-05-31 12:43:12 -04:00
johnnyq
689c52ae3e Added select2 class on share with 2023-05-25 17:39:15 -04:00
johnnyq
d3281ecd18 Updated Share Model to have an Expire selection instead of selecting a date and time, also share link will now email a chosen contact that has a valid email with the secure link, along with notifications when link is clicked. The Link now adds the https:// in the beginning for easy copy paste 2023-05-25 17:35:09 -04:00
johnnyq
29dd0f6dee Fix issue under client tickets listing where contact name would appear incorrectly 2023-05-25 15:52:27 -04:00
johnnyq
9449a87a1f Strip Out http and https in domains, vendors and passwords 2023-05-22 10:39:50 -04:00
johnnyq
96d39a328f Remove old multi-company code causing breakage. Closes #689 thanks @Heart1010 2023-05-22 10:30:36 -04:00
Johnny
80fa93626a Merge pull request #688 from wrongecho/client-website-remove-protocol-regex
Add regex to remove http:// or https:// from client_website
2023-05-21 22:43:26 -04:00
wrongecho
20a65089b6 Update invoice_payment_add_modal.php
Tidy spacing
2023-05-20 20:34:20 +01:00
wrongecho
e8b5c881fe Update invoice.php
Tidy spacing
2023-05-20 20:31:12 +01:00
wrongecho
7d3f4fefbf Update functions.php
Tidy spacing
2023-05-20 20:27:37 +01:00
wrongecho
6c84b8edca Update expense_add_modal.php
Tidy spacing
2023-05-20 20:22:20 +01:00
wrongecho
a8f3b0fed1 Update custom_field_edit_modal.php
Tidy spacing
2023-05-20 20:21:23 +01:00
wrongecho
9fd57cef43 Update cron_ticket_email_parser.php
Codesmell
2023-05-20 20:20:05 +01:00
wrongecho
e650b7938e Update client_software_add_modal.php
Tidy
2023-05-20 20:18:15 +01:00
wrongecho
6673f27cec Update client_software_add_from_template_modal.php
Tidy
2023-05-20 20:16:30 +01:00
wrongecho
54911769c6 Update ajax.php
Tidy spacing
2023-05-20 19:50:48 +01:00
wrongecho
337bd27ee8 Update contact.php
Tidy spacing
2023-05-20 19:49:25 +01:00
wrongecho
eb2c42f4a3 Update cron_ticket_email_parser.php
Remove attachments to-do item as completed.
2023-05-20 19:47:33 +01:00
Marcus Hill
d0fa30d476 Add regex to remove http:// or https:// from client_website #684 2023-05-20 18:49:21 +01:00
Johnny
0abc6b384c Merge pull request #686 from bhopkins0/patch-2
Security enchancement for getIP() function
2023-05-20 11:30:49 -04:00
wrongecho
c63b965807 Merge pull request #687 from wrongecho/fix-leftover-vulnerable-code
Remove leftover SQL-injection vulnerable code
2023-05-20 15:36:03 +01:00
Marcus Hill
cea954008f Remove SQL-injection vulnerable code in this file that was previously fixed in inc_all_client.php 2023-05-20 15:33:46 +01:00
Brent Hopkins
23f7866c8f Increased security for getIP() function 2023-05-18 05:41:06 -05:00
johnnyq
c403380562 Sort Recurring Next Date ASC instead of DESC, add missing select2 class to select inputs 2023-05-17 12:04:12 -04:00
johnnyq
11eb104383 Fix carriage return and new lines in reply emails see https://forum.itflow.org/d/169-carriage-return-and-line-feeds-showing-in-ticket-email 2023-05-16 11:07:24 -04:00
wrongecho
a60a9456f0 Merge pull request #685 from wrongecho/rev-679
Ticket.php: Revert PR 679
2023-05-15 21:44:53 +01:00
Marcus Hill
0144132649 Ticket.php: revert PR 679
- Hide previous ticket count for now as this doesn't work as intended
2023-05-15 21:40:59 +01:00
johnnyq
77fb0e008f Stack Contact infosuch as phone, mobile and email for contacts on one column as these don't need tp be sortable and will make room for more detail columns to be sortable 2023-05-15 14:24:11 -04:00
johnnyq
1f580fc638 Updated README to exclude SummerNote and include TinyMCE 2023-05-15 13:33:40 -04:00
johnnyq
0b1b551df5 Remove SummerNote Code we have replaced this with TinyMCE 2023-05-15 13:32:21 -04:00
Johnny
0649931797 Merge pull request #683 from wrongecho/ticket-button-wording
Ticket.php
2023-05-15 13:29:15 -04:00
Marcus Hill
02ced0dbbd Fix codesmell 2023-05-14 20:19:07 +01:00
Marcus Hill
1057481039 Ticket.php
- Change wording of ticket 'Respond' button to 'Add note' if reply is internal
- Fix TinyMCE not loading under certain circumstances
- Correct varname 'prefix' to 'ticket_prefix' in reply alert message
2023-05-14 20:16:04 +01:00
wrongecho
eb4c5cbf34 Merge pull request #682 from wrongecho/master
Code tidy - ticket.php
2023-05-14 19:50:14 +01:00
Marcus Hill
40a8c6d723 Tidy 2023-05-14 19:48:29 +01:00
wrongecho
994d2fa5e4 Update README.md
Bump 1.0 release to July. Clarify security note to match docs.
2023-05-14 07:57:22 +01:00
Johnny
8861243792 Merge pull request #679 from aftechro/patch-11
Update ticket.php
2023-05-14 00:25:21 -04:00
Johnny
ee913da18f Merge pull request #680 from wrongecho/login-get-param
Add database structure for 'login key' protection concept
2023-05-14 00:24:16 -04:00
Johnny
9e91066a09 Merge pull request #681 from wrongecho/cron-email-invoice
Cron - Send invoices to all billing contacts + primary
2023-05-14 00:23:52 -04:00
AFTECH.RO
4183583ef5 Update ticket.php
changed the sql for previous ticket to prevent XSS attacks.
2023-05-13 23:30:33 +01:00
Marcus Hill
c2b6591cda Cron - Send invoices to all billing contacts + primary 2023-05-13 23:10:36 +01:00
wrongecho
d2d1b25e32 Update guest_pay_invoice_stripe.php
Rem comment re multi-company
2023-05-13 22:44:39 +01:00
Marcus Hill
5d6d7e389e Add database structure for 'login key' protection concept 2023-05-13 21:49:09 +01:00
AFTECH.RO
ffe4061429 Update ticket.php
Hide Previous ticket if none exists
2023-05-13 09:42:48 +01:00
AFTECH.RO
052d418bad Update ticket.php
Re-make of Related tickets (total open and closed) and contact card, showing previous ticket and status of it. Also, made the contact mobile and contact phone clickable (tel:$contact_phone)
2023-05-13 02:30:34 +01:00
Johnny
a79baae2a8 Merge pull request #677 from wrongecho/domain-expire-quotes
Fix domain registrar/webhost update not working
2023-05-12 18:51:34 -04:00
Marcus Hill
b281a19e6b Fix domain registrar/webhost update not working
- Quote the expiry field when updating a domain
- Better handle no web host being set
2023-05-12 23:26:39 +01:00
johnnyq
e67a75805c Fix: Authenticated users can craft a POST request to delete any file on the webserver. Thank you @
bhopkins0
2023-05-12 15:24:57 -04:00
johnnyq
51ee479130 oops fix replaced the actualy function with nullable 2023-05-11 18:34:06 -04:00
johnnyq
37fb696e63 Replace the remaining php files with nullable_htmlentites() 2023-05-11 18:27:48 -04:00
johnnyq
ccf0d3ab77 Replace all instances of htmlentities() with the new function nullable_htmlentities() thanks @bhopkins0 2023-05-11 18:23:36 -04:00
Johnny
f136a915b4 Merge pull request #676 from bhopkins0/patch-1
Add function to use htmlentities without deprecated error
2023-05-11 18:05:12 -04:00
Johnny
b1dfbada0c Merge pull request #675 from bhopkins0/master
Fixed clients.php blank page
2023-05-11 18:02:24 -04:00
Brent Hopkins
019050ba82 Add function to use htmlentities without deprecated error 2023-05-11 16:37:21 -05:00
Brent Hopkins
cdd2a31217 Update MySQL query 2023-05-11 16:07:05 -05:00
Brent Hopkins
9de9dcd1b3 Add client_tags.client_tag_tag_id to GROUP BY 2023-05-11 02:43:58 -05:00
Johnny
1e9c822033 Merge pull request #674 from bhopkins0/master
Fix "My Tickets" button CSS
2023-05-11 01:27:35 -04:00
Brent Hopkins
d1fc5c3c99 Change button look 2023-05-10 21:35:48 -05:00
johnnyq
8b89ba31db Fix Raise ticket under client portal another regression when we moved to TinyMCE. Expanded Document view to container width 2023-05-10 11:50:55 -04:00
johnnyq
cf0205ba21 Tidy Portal Header 2023-05-09 16:37:32 -04:00
johnnyq
901b51a18e Merge branch 'master' of github.com:itflow-org/itflow 2023-05-09 15:51:15 -04:00
johnnyq
485510a3ce Fix Create Ticket not submitting due to TinyMCE not respecting required fields in the textarea form inputs, removed the required fields for now 2023-05-09 15:50:26 -04:00
wrongecho
0665ec5701 Update bug_report.md
Add security notice to bug report
2023-05-09 20:30:07 +01:00
wrongecho
ad5743f176 Update support.md
Adjust security link
2023-05-09 20:28:29 +01:00
johnnyq
6f6ae476a9 Added comment in pagination_head.php regarding issue #673 2023-05-09 15:22:02 -04:00
johnnyq
8d666abc40 Tidy 2023-05-09 15:13:44 -04:00
johnnyq
163f14e791 Fixed Escaping issue with sortby unfortuantly with order_by mysql_escape is not enough and must also be filtered with a preg_replace Thanks @tdragon6 2023-05-09 15:12:39 -04:00
johnnyq
cb0366b9f7 Fix XSS in expenses and trips export CSV modal Thanks @tdragon 2023-05-09 12:11:42 -04:00
johnnyq
09ff8b710b Enable browser spell checker for TinyMCE 2023-05-09 00:31:09 -04:00
johnnyq
043a9cfa0a Fixed Ticket Reply currently an issue where required fields using TinyMCE wont POST looking into it 2023-05-08 22:15:23 -04:00
johnnyq
eb3decb4da Enabled TinyMCE for mobile users as well 2023-05-08 21:25:06 -04:00
johnnyq
c3a711d75d More TinyMCE in more places 2023-05-08 19:53:42 -04:00
johnnyq
01a37cb1e1 Replace Summernote WYSIWYG with TinyMCE 2023-05-08 18:44:00 -04:00
johnnyq
018f52eb67 Revert for now added HTML Purify to client tickets as well 2023-05-08 14:38:42 -04:00
johnnyq
eb9a8000b1 Fix Rendering issues with tickets editing because ticket client_tickets and ticket all share the same edit modal which already uses htmlentites to prevent xss but so it doesnt conflict with htmlpurify in ticket details we decided to split the vars to ticket_details and ticket_details_edit which is unfilter initially but gets filtered in the modals 2023-05-08 13:52:43 -04:00
johnnyq
9887fc4a19 Removed HTML Purify on tickets.php and use htmlentities instead to mimic client_tickets.php was causing some rendering issues when you goto edit a ticket under client tickets tested for XSS all tests came back clean 2023-05-08 13:24:43 -04:00
johnnyq
5ee78ef1f3 When deleting quote from the client or global list view redirect quote delete back to the correct corresponsing list view also make Delete Quote Functional on quote details 2023-05-08 12:37:05 -04:00
Johnny
53e0ebdbf6 Merge pull request #672 from wrongecho/portal-modules
Client Portal - quotes & docs
2023-05-08 11:35:34 -04:00
Johnny
226d3ffeb2 Merge pull request #671 from wrongecho/ticket-auto-close-2
Ticket autoclose:
2023-05-08 11:35:14 -04:00
Marcus Hill
db6b88edd3 Codesmell 2023-05-08 10:54:40 +01:00
Marcus Hill
0e062081cb Client Portal
- Allow primary + accounting/billing contacts to see quotes
- Allow primary + technical contacts to see docs
2023-05-08 10:50:53 +01:00
Marcus Hill
3a83a701b5 Ticket autoclose: Clarify auto-close help wording; only show as ticket status option if enabled 2023-05-08 09:43:46 +01:00
johnnyq
03e0dd8f5e Initial DB Structure for Projects and Tasks with Ticket and Client Linkage 2023-05-07 21:43:20 -04:00
johnnyq
93d4f3ebce You can now set the number of hours before a ticket is automatically closed if autoclose is set 2023-05-07 21:09:18 -04:00
johnnyq
37b375c1d9 Remove cruft 2023-05-07 20:47:15 -04:00
johnnyq
78695208b7 Fix custom Fields DB Structure Remove Unique Indexes change defaut type TEXT to text Added Add edit Delete Read for custom fields 2023-05-07 20:46:09 -04:00
johnnyq
0f758c5901 Finished DB Structure for the coming new feature custom fields 2023-05-07 19:45:55 -04:00
johnnyq
ac51f0cb72 Add Quick link to docs.itflow.org on the top bar 2023-05-02 14:58:35 -04:00
johnnyq
072c2f9e14 Fix cron stating cron key is always invalid 2023-05-02 13:45:23 -04:00
johnnyq
a0da341114 Updated initial db structure for installation 2023-05-02 12:36:18 -04:00
johnnyq
3f2f663b7b Check to see if args is set 2023-05-01 16:56:29 -04:00
johnnyq
f7ee489293 BREAKING CRON CHANGES: must generate a cron key before using cron. Cron will need updated like so php /full/path/to/cron.php [KEY] and same with cron_ticket_parse.php 2023-05-01 16:51:20 -04:00
Johnny
8110b0ffa7 Merge pull request #668 from wrongecho/portal-rem-company
Remove reference to non-existent company_id field in contacts table
2023-05-01 11:52:33 -04:00
Johnny
07ac69a528 Merge pull request #667 from wrongecho/ticket-auto-close
Add auto close ticket feature
2023-05-01 11:52:20 -04:00
Johnny
fc1eb4cd69 Merge pull request #666 from wrongecho/email-invoice
Send invoices to all billing contacts + primary
2023-05-01 11:51:13 -04:00
Marcus Hill
bf45c58ed1 Remove reference to non-existent company_id field in contacts table 2023-05-01 14:01:23 +01:00
Marcus Hill
dc2293c8dd Add auto close ticket feature 2023-05-01 02:02:45 +01:00
Marcus Hill
588206d79d When sending invoices manually, send to all billing contacts instead of just primary contact 2023-05-01 00:06:11 +01:00
johnnyq
8cf1bd8911 Set Working directory of cron parser upon initializtion which fixes relative path issue when adding attachments to tickets 2023-04-30 13:28:00 -04:00
Johnny
c11b3d5987 Merge pull request #665 from wrongecho/email-ticket-attachments
Email ticket attachments
2023-04-30 12:43:42 -04:00
Marcus Hill
0a9af8f2e0 Ticket attachments (email)
Email to ticket parser: Add support for email attachments
2023-04-30 10:52:25 +01:00
Marcus Hill
a3d8f5ab48 Ticket attachments (email)
Email to ticket parser: Add support for email attachments
2023-04-30 10:52:15 +01:00
Johnny
ab1582fe3a Merge pull request #664 from wrongecho/csp-initial-test
CSP - Client Portal Test
2023-04-30 00:35:08 -04:00
Marcus Hill
0340b080ad CSP - Client Portal Test
Add initial content security policy trial/test to some client portal pages
2023-04-29 19:39:42 +01:00
Johnny
a3353593db Merge pull request #663 from wrongecho/ticket-edit-strip-html
Sanitize ticket details output in main edit modal
2023-04-29 11:30:33 -04:00
Marcus Hill
c5966961da Sanitize ticket details output in main edit modal 2023-04-29 12:34:14 +01:00
wrongecho
ca0024feb9 Merge pull request #661 from wrongecho/email-ticketing-updates
Update documentation links on cron tickets
2023-04-29 10:03:11 +01:00
Marcus Hill
8247362891 Update documentation links 2023-04-29 09:52:53 +01:00
johnnyq
c5c4813f47 Update Links referencing the new documentation URLs 2023-04-28 19:53:23 -04:00
johnnyq
e54de2bb73 Feature: Users can now be exported to a CSV file 2023-04-24 17:03:01 -04:00
johnnyq
53b7f7d1d5 Feature: Client CSV Exportation 2023-04-24 16:48:47 -04:00
johnnyq
7fed50eb73 Updated all Export CSV to Modals with export disclaimer 2023-04-23 16:12:18 -04:00
johnnyq
541d1dd667 Add precautionary warning when exporting CSV data, still need to add modals for client data 2023-04-23 14:27:45 -04:00
johnnyq
53092fe9ca Updated Ticket email / replies with ##- Please type your reply above this line -## 2023-04-17 16:15:22 -04:00
johnnyq
c20f19568d Update ticket to require the body field to mimic the same function as edit ticket 2023-04-16 10:49:15 -04:00
Johnny
d0dae015a6 Merge pull request #658 from itflow-org/wrongecho-email-rm-beta
Remove beta from email ticket parsing
2023-04-15 22:47:55 -04:00
wrongecho
a765459b43 Update settings_ticket.php 2023-04-15 20:15:24 +01:00
wrongecho
515ea739de Remove (beta) from email ticket parsing 2023-04-15 19:52:47 +01:00
johnnyq
b784c48120 Opps Fix 2023-04-12 16:48:35 -04:00
Johnny
880b2fccb5 Merge pull request #657 from wrongecho/client-tax-fix
Fix client_tax_id_number variable name in edit modal
2023-04-12 16:47:15 -04:00
Marcus Hill
bc4e744384 Fix client_tax_id_number variable name in edit modal 2023-04-12 21:21:56 +01:00
johnnyq
f127719cbe Added new Field Client Tax ID Number, currently only vieable on the client top head, and under edit. It is also searchable 2023-04-11 16:20:48 -04:00
johnnyq
d27c83ab66 Fix Mail Parser, inserting \r \n 2023-04-11 11:23:19 -04:00
johnnyq
ca6e3c229e Remove a lingering D under transfers 2023-04-10 17:32:21 -04:00
Johnny
eb49233d20 Merge pull request #656 from wrongecho/ticketing-0423
Ticketing Updates - Change client
2023-04-10 15:17:07 -04:00
Johnny
1c6ff4f4f6 Merge pull request #655 from wrongecho/api-multi-select
Add multi-select/bulk deletion for API keys
2023-04-10 15:16:50 -04:00
Marcus Hill
a26f3087fc Change client - fix code smell 2023-04-10 19:13:31 +01:00
Marcus Hill
c55d2a8cda Add ticket_source field for future use (agent/portal/email) 2023-04-10 18:58:06 +01:00
Marcus Hill
2f19967a0d Comment ticket_created_by 2023-04-10 18:55:42 +01:00
Marcus Hill
1aa33585a0 Ticketing - add ability to change client 2023-04-10 18:52:23 +01:00
Marcus Hill
8d97feeb54 Add ticket_source field for future use (agent/portal/email) 2023-04-10 16:37:03 +01:00
Marcus Hill
4db390d72b Add multi-select/bulk deletion for API keys 2023-04-10 12:32:05 +01:00
wrongecho
2373718be6 Bump 1.0 release from Mar/Apr to Apr/May 2023-04-10 11:52:38 +01:00
wrongecho
8e44518faa Update old broken docs link to DocuWiki homepage 2023-04-10 11:51:28 +01:00
Johnny
21fc20645b Merge pull request #654 from wrongecho/dynamic-modals
Convert quote edit modal to be dynamically populated
2023-04-09 23:35:23 -04:00
Marcus Hill
5f79931787 Dynamic modals: codesmell 2023-04-09 20:14:15 +01:00
Marcus Hill
bdf74e77ba Convert quote edit modal to be dynamically populated 2023-04-09 20:10:19 +01:00
Johnny
6287a7ce3d Merge pull request #653 from wrongecho/files-logging
Enhance logging for file uploads/deletes
2023-04-09 13:28:20 -04:00
Marcus Hill
0e0c06eebf File logging - codesmell fix 2023-04-09 13:18:14 +01:00
Marcus Hill
e66e896904 Enhance logging for file uploads/deletes 2023-04-09 13:14:46 +01:00
Johnny
f63cd120c6 Merge pull request #652 from wrongecho/confirm-file-delete
Client file deletion
2023-04-08 20:36:58 -04:00
Johnny
f07bff116b Merge pull request #651 from wrongecho/fix-file-upload-auto-name
Bufix: Fix client file uploads
2023-04-08 20:35:14 -04:00
Marcus Hill
04dad13ad3 Client file deletion
- Add file delete confirmation modal
- Change file deletes to POST not GET requests in post.php as they are state changing
- Require CSRF validation for file deletes
2023-04-08 21:59:54 +01:00
Marcus Hill
9f25b436d6 Fix client file upload not automatically naming files or showing image previews 2023-04-08 20:48:55 +01:00
johnnyq
c2b25cbf7d Fix Recurring Invoice syntax 2023-04-06 16:44:11 -04:00
johnnyq
a5d9bd7abe Convert CSS to nl2br() functions where nessesessaery to interept new lines into html code, Tidy Code remove depreciated <center> Tags 2023-04-05 15:20:07 -04:00
johnnyq
74768d6801 Transfer Notes now render new lines in the list view 2023-04-05 14:53:52 -04:00
johnnyq
d43c2f2d06 FEATURE: Added Transfer notes to the transfers list and also made notes searchable and sortable 2023-04-05 14:41:43 -04:00
johnnyq
26aa63917f Only select used fields on SQL Query for Edit Add Refund and copy queries to reduce the SQL Load on large expense tables 2023-04-03 19:18:32 -04:00
johnnyq
a3e45d632f Merge branch 'master' of github.com:itflow-org/itflow 2023-04-03 19:08:52 -04:00
johnnyq
230efc83dd Feature: Added Optional Client Field to Expenses to track your expenses to the client 2023-04-03 19:08:37 -04:00
Johnny
9f30de408c Merge pull request #650 from meltyness/totpfix
fixes #477
2023-03-28 21:47:54 -04:00
root
67c72400f8 Fixed logic incompatibility between AJAX handler and base32 object usage convention. 2023-03-28 17:30:19 -05:00
johnnyq
c544dc4a2a New Feature: Added Hourly Rate to Client 2023-03-28 15:29:54 -04:00
johnnyq
1e2535359a Update Global Search Documents to reference actual document 2023-03-23 16:57:06 -04:00
Johnny
36b6347b66 Merge pull request #649 from XVicarious/patch-1
Fix #648
2023-03-22 23:51:12 -04:00
Brian Maurer
341644ba01 Fix #648 2023-03-22 21:16:13 -04:00
johnnyq
201db36c24 Moved more edit add vars to models 2023-03-21 21:18:12 -04:00
johnnyq
3202bceddd Set File Size to 20MB 2023-03-21 13:00:50 -04:00
johnnyq
035be88e72 Moved the remaining upload logics to use the checkFileUpload() Function 2023-03-21 12:53:01 -04:00
Johnny
0f1f324162 Merge pull request #647 from wrongecho/ticket-colours
tickets.php - Rename unused ticket_status_display to ticket_status_color
2023-03-19 12:26:09 -04:00
johnnyq
899b38d84b Fix another 0000-00-00 to NULL 2023-03-19 12:21:13 -04:00
Marcus Hill
6ac7843ee9 Tidy spacing 2023-03-19 16:00:55 +00:00
Marcus Hill
3718987f50 tickets.php - Rename unused ticket_status_display to ticket_status_color 2023-03-19 15:53:10 +00:00
johnnyq
b7e59aa023 Revert the UI update on drop notifications didnt look right too much code 2023-03-18 16:29:32 -04:00
johnnyq
52faf2fac9 Spruce up the Dropdown Notifications UI 2023-03-18 16:22:43 -04:00
johnnyq
d05aa0b829 When clicking on a notificaiton on the dropdown instead of dismissing it takes you to the client page if specified otherwise its an empty click, updated some entity_id for notifications in cron.php 2023-03-18 15:36:19 -04:00
johnnyq
a9c90a0c6a Opps Add db.sql back 2023-03-18 15:21:45 -04:00
johnnyq
1dc52ecc4f Added new field to notifications called entity_id which will reference an item related to the notificaiton so it can be clicked on to go directly to the entity under notifications 2023-03-18 15:17:45 -04:00
johnnyq
427c51b728 Bump phpMailer from 6.7.1 to 6.8.0 2023-03-18 12:44:55 -04:00
johnnyq
4a2d76b056 Fix https://forum.itflow.org/d/111-umlauts-are-replaced-in-the-subjects - Removed array_map htmlentities which wasnt needed since we are passing AJAX data over which is already formated properly 2023-03-18 12:29:23 -04:00
johnnyq
99eaaa71c4 Fix #646 Thanks @Heart1010 2023-03-16 12:39:07 -04:00
johnnyq
3f028e8560 Fix Broken API due to incorrect named function https://forum.itflow.org/d/119-api-broken 2023-03-14 18:59:43 -04:00
johnnyq
37e21e963b Add summernote WYSIWYG function to Raising a ticket as we sanitize outout with HTMLPurify 2023-03-13 20:06:36 -04:00
johnnyq
748041cd5d Fix issue relating to forum post https://forum.itflow.org/d/118-users-cant-raise-tickets due to mis-spelled function 2023-03-13 19:51:52 -04:00
johnnyq
1c9461c075 Added client_id to both notifications and logging when send invoice emails 2023-03-13 16:30:02 -04:00
johnnyq
f7f9135428 Added entity_id to logging when sending invoice emails 2023-03-13 16:26:12 -04:00
johnnyq
924159dfcb Wrong var sent for logging email address during invoice sends 2023-03-13 16:23:39 -04:00
johnnyq
76f02c46a8 Use htmlpurify to show client shared document, Clean up some formatting in guest item view, fixed Invoice and Quote not logging the client who view them this was a regression from the company removal 2023-03-13 15:45:12 -04:00
johnnyq
9d053dcc91 Undo Query need to rethink this one 2023-03-12 15:49:01 -04:00
johnnyq
89c4811aa6 Combined balance, reccuring monthly and paid to date to the clients query so now they can be sortable with less queries 2023-03-12 15:39:22 -04:00
johnnyq
e1cbd12f2e Updated Git Ignore to ignore HTMLPurify cache Remove HTMLPurify generated Cruft 2023-03-12 11:31:10 -04:00
johnnyq
7543bfc8bc Remove HTMLPurify generated Cruft 2023-03-12 11:28:10 -04:00
johnnyq
6a660a5429 Removed Ticket created at as this is done automatically at the DB level 2023-03-12 11:26:47 -04:00
johnnyq
f5175ff6e7 Remove HTMLPurify generated Cruft 2023-03-12 11:02:35 -04:00
johnnyq
58d058e62c Added Summernote WYSIWYG to client portal 2023-03-12 11:02:09 -04:00
johnnyq
c9dfb1ef6a Remove HTMLPurify generated Cruft 2023-03-12 10:49:17 -04:00
johnnyq
d37c3f0251 Rework htmlpurify function in client portal to properly santizie the output instead of the input Fix broken client avatar in client portal 2023-03-12 10:48:45 -04:00
johnnyq
c9143ec3c0 Remove HTMLPurify generated Cruft 2023-03-12 10:13:56 -04:00
johnnyq
fd6a8284c4 Fixed padding under client scheduled tickets, Removed HTMLPurify under schedueld tickets post as it is not needed and seems to be taken care of by the javascript modal 2023-03-12 10:13:03 -04:00
Johnny
ef6e294acc Merge pull request #644 from wrongecho/small-fixes-post-company-edits
Small fixes post company edits
2023-03-12 09:55:52 -04:00
Marcus Hill
e9ac93085d Fix typo 2023-03-12 10:12:53 +00:00
Marcus Hill
e2d4552e6e Re-indent & remove a random 'h' 2023-03-12 09:30:07 +00:00
johnnyq
20dbe285e8 Remove HTML Entity Decode from the HTML Purifier as this is not needed now 2nd attempt in ticket replies 2023-03-11 21:48:30 -05:00
johnnyq
4eeb2fdffa Remove Cruft 2023-03-11 21:47:36 -05:00
johnnyq
16b20c0bfa Remove HTML Entity Decode from the HTML Purifier as this is not needed now 2023-03-11 21:47:11 -05:00
johnnyq
af46738427 Only use HTMLPurify Library on Output only and SQL sanitize for input 2023-03-11 21:42:47 -05:00
johnnyq
6ecca50541 Garbage Remove 2023-03-11 21:25:08 -05:00
johnnyq
b5ae7b3d86 Used HTMLPUrify to Purify the output of Tickets, Documents, Document Templates. Removed Redundant htmlentities in edit document edit ticket etc, Removed Company ID from Document Template Details 2023-03-11 21:24:35 -05:00
johnnyq
00b9391de4 Remove Company_id from Document_details.php 2023-03-11 20:57:58 -05:00
johnnyq
8fcc43d1fb Fixed broken Online Payments Settings Page due to a regression 2023-03-11 19:34:30 -05:00
johnnyq
6a92b132bf Missing } 2023-03-11 19:15:53 -05:00
johnnyq
6a435157c1 Another try to make sure config.php is written before going further 2023-03-11 19:11:34 -05:00
johnnyq
709516853a Remove company_id fields in Setup no longer used also rework writing the config file 2023-03-11 18:50:18 -05:00
johnnyq
8308b47295 Fix missing user_id var in Setup, removed sleep(2) as it did not fix the issues where config.php was not written instead used an if condition to check to see if config.php is written before going further 2023-03-11 18:35:15 -05:00
johnnyq
e2f2960830 Fix regression that caused company setup to break because of a no longer used DB table, also attempt to check if config.php exists before moving onto the user step as sometimes during setuo it does not write the config.php file 2023-03-11 18:23:20 -05:00
johnnyq
a889f7d879 Add back api/v1/assets/read.php somehow got wiped during the big update also added the ability to query asset by MAC address 2023-03-11 17:15:46 -05:00
johnnyq
0ad86ab053 Fix Company File Upload Regression 2023-03-11 17:02:53 -05:00
johnnyq
48fe49cf77 BREAKING CHANGES - MAKE FULL BACKUP BEFORE PROCEEDING - Requires Manual Intervention on files see Forum Post Make sure you run the Database update directly after update. This Removes Multi-Company Functionality. Fixes issues with Reponsive tables and bunch of other UI and small Fixes 2023-03-11 16:16:46 -05:00
wrongecho
75da31d991 Merge pull request #643 from wrongecho/master
Documents
2023-03-11 20:05:53 +00:00
Marcus Hill
90bba73aac Documents
- Properly escape HTML in the edit modal
- Tidy
2023-03-11 19:55:38 +00:00
wrongecho
4344a4fcca Update ticket_reply_edit_modal.php
Sanitize any potential HTML output in ticket reply edit modal to summernote editor
2023-03-06 21:12:58 +00:00
johnnyq
b9112ddded tidy 2023-03-05 20:33:05 -05:00
johnnyq
a711bed38c Add sme more htmlemtities for consistency 2023-03-05 20:06:42 -05:00
wrongecho
9a3266190c Merge pull request #642 from wrongecho/stricter-input-validation-theme-tags
Add stronger input validation/output escaping
2023-03-05 19:31:22 +00:00
Marcus Hill
2210ad9f3e Add stronger input validation/output escaping for theme, tags and categories vars 2023-03-05 19:25:24 +00:00
Marcus Hill
feb0267002 Add stronger input validation/output escaping for theme, tags and categories vars 2023-03-05 19:13:48 +00:00
Johnny
ff18e704c8 Merge pull request #641 from wrongecho/cert-multi-select
Add bulk actions (delete) for client certificates.
2023-03-05 11:58:09 -05:00
johnnyq
cdf97ec83b Fix clients being duplicated when multiple tags are assigned to them 2023-03-05 11:40:20 -05:00
Marcus Hill
1c18599372 Add bulk actions (delete) for client certificates. 2023-03-05 16:20:09 +00:00
johnnyq
5640a22c18 Remove some more log created at and updated at as the DB does this for us 2023-03-04 16:17:29 -05:00
johnnyq
c0af8e8eab Add '' to the date vars under API assets if not empty so they dont error out when inserted into the DB 2023-03-04 16:13:38 -05:00
johnnyq
e01dea2fd0 Fix Assets API Missing $ on var and use NULL instead of 0000-00-00 when inserting into the DB similar to POST 2023-03-04 15:58:34 -05:00
johnnyq
426b07a093 Fix issue with ulauts in the subject field of tickets opened using email parser. Removed htmlentities on subject replaced with the new inputSanitize See https://forum.itflow.org/d/111-umlauts-are-replaced-in-the-subjects 2023-03-03 12:14:29 -05:00
johnnyq
7228d8b6e6 Fix #640 2023-03-02 16:20:03 -05:00
johnnyq
7445cf1910 oops somehow dahsboard_technical got removed put it back 2023-03-01 16:28:11 -05:00
johnnyq
e42095a85e Tidy code 2023-03-01 16:26:41 -05:00
johnnyq
45b686dafc Fix issue with cron not sending recurring emails due to a misspelling 2023-03-01 14:09:58 -05:00
johnnyq
5114c1acc9 Fix possible Setup bug where it sometimes doesnt create the config.php and moves on. The hopeful fix is after creating config.php, sleep for 2 seconds which will wait for the file to be written fully to the filesystem before moving ahead. This issue could arrise with slow disks 2023-03-01 11:16:53 -05:00
johnnyq
b7c855a67d Fix #639 2023-03-01 11:07:56 -05:00
johnnyq
b2deebfa42 Reverted still causing issues with duplicate clients 2023-03-01 01:11:25 -05:00
johnnyq
58e08c1e60 Still getting dupes in clients with multiple tags redid the query 2023-03-01 01:09:14 -05:00
johnnyq
d50397f291 Add back additional Groupby in Client oops 2023-03-01 01:03:40 -05:00
johnnyq
373df5c4d1 Merge branch 'master' of github.com:itflow-org/itflow 2023-03-01 00:59:30 -05:00
johnnyq
3783fcfef6 Converting 0000-00-00 date values to NULL as this is best practice and compitible with MySQL 2023-03-01 00:59:14 -05:00
johnnyq
1a5bffd2e0 Updated the client inc to remove date 0000-00-00 format to fix issue with MySQL 2023-02-28 23:52:20 -05:00
johnnyq
99dc294145 rewrite income by client report SQL query to join as a single query instead of multiple
;
2023-02-28 23:04:25 -05:00
johnnyq
47dbd46bf3 rewrite the Recurring Incpome by Client report into 1 Query instead of multiple 2023-02-28 22:41:24 -05:00
johnnyq
94c020f689 Fix issue clients listing being broken with MySQL server due to not specifiying all non aggregate columns be in the GROUP BY Field, this was not an issue with mariaDB 2023-02-28 22:15:09 -05:00
johnnyq
e14fe2474c Updated Multi Action UI and some logic 2023-02-28 20:16:07 -05:00
johnnyq
cdfb61b294 Added a helper if no tags exist when attempting to add them to a client, Added some santizeInput tags to API 2023-02-28 11:58:08 -05:00
johnnyq
2acb5e0b7b Possible fix for MYSQL Date not handling 0000-00-00 2023-02-27 12:35:41 -05:00
johnnyq
a79e4b496c Fix regression in client listing which broke searching between dates 2023-02-27 12:26:46 -05:00
johnnyq
18a8122d4c Merge branch 'master' of github.com:itflow-org/itflow 2023-02-26 22:39:54 -05:00
johnnyq
fdb34b2613 Toyed with the idea of showing Which Column is being sorted and if its ASC or DESC in dismissed notifications 2023-02-26 22:39:34 -05:00
johnnyq
fbc30248de Toyed with the idea of showing Which Column is being sorted and if its ASC or DESC in dismissed notifications 2023-02-26 22:37:30 -05:00
johnnyq
0269f416a5 Toyed with the idea of showing Which Column is being sorted and if its ASC or DESC in dismissed notifications 2023-02-26 22:36:12 -05:00
Johnny
b9b383cbd2 Merge pull request #631 from wrongecho/532-remove-add-company
Remove ability to add new companies
2023-02-26 21:58:07 -05:00
Marcus Hill
8de76fdded Remove ability to add new companies
As part of the ongoing removal of the multi-company feature, this PR/commit removes the ability to add new companies in settings.
2023-02-25 21:53:20 +00:00
1935 changed files with 160895 additions and 59929 deletions

2
.github/FUNDING.yml vendored
View File

@@ -1 +1 @@
custom: ["https://www.paypal.com/donate/?business=QP4U384PMVBMU&no_recurring=0&item_name=Help+support+the+development+of+ITFlow&currency_code=USD"]
custom: ["https://donate.itflow.org"]

View File

@@ -1,32 +1,23 @@
---
name: Bug report
about: Something not working quite right? Create a report to help us improve!
title: ''
labels: ''
about: Please report bugs on the Forum @ https://forum.itflow.org/t/bug
title: 'Please report bugs on the Forum'
labels: Support
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
We're now using GitHub Issues exclusively for development.
-
**Can you reproduce this on the demo at demo.itflow.org**
Yes/No/NA
Going forward, GitHub Issues will be used to track confirmed bugs & planned features via Github Projects. This allows us to keep GitHub clean & tidy, whilst maintaining an active and relaxed community experience on the Forum.
**Are you on the latest available version of ITFlow, with an up-to-date database structure?**
Yes/No
Please raise bugs on the forum @ https://forum.itflow.org/t/bug. Make sure to mention whether you can replicate the bug on demo.itflow.org.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
4. See error
Thanks,
**Expected behavior**
A clear and concise description of what you expected to happen, if not obvious.
The ITFlow team :)
**Screenshots**
If applicable, add screenshots to help explain your problem.
--
**Additional context**
Add any other context about the problem here.
To privately discuss a security issue, please see https://github.com/itflow-org/itflow/security

View File

@@ -1,16 +1,25 @@
---
name: Feature request
about: Please discuss new features on the Forum @ https://forum.itflow.org/t/features
title: ''
title: 'Please discuss new features on the Forum'
labels: Support
assignees: ''
---
We're now using GitHub just to track features we're definitely planning to implement (and bugs!).
We're now using GitHub Issues exclusively for development.
-
Please discuss new feature requests on the forum @ https://forum.itflow.org/t/features. This allows us to gather interest & feedback on the features people feel are most important, whilst keeping GitHub cleaner and more about the code.
Going forward, GitHub Issues will be used to track confirmed bugs & planned features via Github Projects. This allows us to keep GitHub clean & tidy, whilst maintaining an active and relaxed community experience on the Forum.
New feature requests here will be closed.
Please discuss new feature requests on the forum @ https://forum.itflow.org/t/features. When creating discussions, try to imagine how your proposed feature would also benefit other users.
Thanks :)
All new feature requests raised here will be closed, unless agreed otherwise.
Thanks,
The ITFlow team :)
--
To privately discuss a security issue, please see https://github.com/itflow-org/itflow/security

View File

@@ -1,18 +1,25 @@
---
name: Support
about: Please visit the Forum or Discord for support
title: ''
about: Please request support on the Forum @ https://forum.itflow.org/t/support
title: 'Please visit the Forum for support'
labels: Support
assignees: ''
---
Please visit the Forum or Discord for support
We're now using GitHub Issues exclusively for development.
-
Forum - https://forum.itflow.org/
Going forward, GitHub Issues will be used to track confirmed bugs & planned features via Github Projects. This allows us to keep GitHub clean & tidy, whilst maintaining an active and relaxed community experience on the Forum.
Discord - https://discord.gg/ZjCcBzTUDr
Please use the forum for support queries/issues: https://forum.itflow.org/t/support
All new support requests raised here will be closed.
Thanks,
The ITFlow team :)
--
To discuss a security issue, please see: https://i.imgur.com/P03o0Sy.png
To privately discuss a security issue, please see https://github.com/itflow-org/itflow/security

37
.github/workflows/dbsql-lint.yml vendored Normal file
View File

@@ -0,0 +1,37 @@
name: SQL Syntax Check for db.sql
on:
pull_request:
paths:
- 'db.sql'
jobs:
syntax_check:
name: Check db.sql SQL Syntax
runs-on: ubuntu-latest
services:
mariadb:
image: mariadb:latest
ports:
- "3306:3306"
env:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MARIADB_USER: user
MARIADB_PASSWORD: password
MARIADB_DATABASE: itfsyntaxdb
options: >-
--health-cmd="healthcheck.sh --connect --innodb_initialized"
--health-interval=10s
--health-timeout=5s
--health-retries=3
steps:
- name: Checkout Repository
uses: actions/checkout@v3
- name: Import & Lint db.sql
run: mysql --host 127.0.0.1 -uuser -ppassword itfsyntaxdb < db.sql
- name: Show imported tables
run: mysql --host 127.0.0.1 -uuser -ppassword itfsyntaxdb -e "show tables;"

View File

@@ -10,18 +10,20 @@ jobs:
run:
runs-on: ubuntu-latest
steps:
- uses: actions/first-interaction@v1.1.1
- uses: actions/first-interaction@v1.2.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
issue-message: |
Hello & Welcome! :)
Thanks for taking the time to get in touch. We'll review this issue shortly.
Thanks for taking the time to get in touch.
Whilst you're waiting, please feel free to check out the [forum](https://forum.itflow.org).
We ask that all bugs/feature/support requests are raised via the [forum](https://forum.itflow.org). We'll be in touch shortly to confirm.
pr-message: |
Hello & Welcome! :)
Thanks for taking the time to help improve ITFlow. We're excited to review your contributions - we'll review this PR as soon as we can!
Whilst you're waiting, please feel free to check out the [forum](https://forum.itflow.org).
Just so you know, all contributions to ITFlow are licensed under the GNU GPL. By contributing you grant us a perpetual & irrevocable license to include your work in ITFlow.

View File

@@ -12,4 +12,4 @@ jobs:
- uses: actions/checkout@v2
- name: Check PHP syntax errors
uses: overtrue/phplint@4.1.0
uses: overtrue/phplint@9.4.1

19
.gitignore vendored
View File

@@ -1,6 +1,7 @@
node_modules
config.php
uploads/favicon.ico
uploads/clients/*
!uploads/clients/index.php
uploads/expenses/*
@@ -11,7 +12,17 @@ uploads/users/*
!uploads/users/index.php
uploads/tmp/*
!uploads/tmp/index.php
backups/*
!backups/index.php
!backups/.htaccess
.idea/*
uploads/tickets/*
!uploads/tickets/index.php
.idea/*
plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/HTML/*
!plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/HTML/.gitkeep
plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/URI/*
!plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/URI/.gitkeep
plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/CSS/*
!plugins/htmlpurifier/standalone/HTMLPurifier/DefinitionCache/Serializer/CSS/.gitkeep
.vscode/settings.json
xcustom/*
!xcustom/readme.php
post/xcustom
!post/xcustom/readme.php

2
.htaccess Normal file
View File

@@ -0,0 +1,2 @@
# Prevent access to .git, .github, and config.php
RedirectMatch 404 ^/(\.git|\.github|config\.php)

86
CHANGELOG.md Normal file
View File

@@ -0,0 +1,86 @@
# Changelog
This file documents all notable changes made to ITFlow.
## [25.01.2]
### Fixed
- Fixed app version.
## [25.01.1]
### Added / Changed
- Redesigned the Multi-Factor Authentication (MFA) Setup and Enforcement Flow UI/UX for a more intuitive user experience.
- Added a "Member" column in the user roles listing for improved visibility.
- General UI/UX improvements, along with minor performance optimizations and cleanups.
### Fixed
- Fixed an issue where Stripe was not appearing as a recurring payment option.
- Corrected inaccurate Quarter 2 Expense results in the Profit & Loss Report.
- Resolved TOTP code not displaying correctly on hover in the Contact or Asset Details sections.
- Archived contacts no longer appear in the Bulk Mail section.
- Fixed an issue where the Ticket Assign Modal was showing both ITFlow and client users.
- Fixed issue with login key redirecting to legacy client portal page.
## [25.01]
### Added / Changed
- Added support for saving cards in Stripe for automatic invoice payments.
- Page titles now display detailed information (e.g., page name, client selection, company name, ticket and invoice info) for easier multi-tab navigation.
- Reintroduced the new admin role-check for admin pages.
- Admin roles can now be archived.
- Debug mode now shows the current Git branch.
- The auto-acknowledgment email for email-parsed tickets now includes a guest link.
- Recurring tickets no longer require a contact.
- Stripe online payment setup now prompts you to set the income/expense account.
- New cron/CLI scripts have been moved to the `/scripts` subfolder — remember to update your cron configurations!
- Moved modal includes to `/modals` to tidy up the root directory.
- Moved most include files to `/includes` to improve directory structure.
- Moved guest pages to `/guest` for better organization.
- Renamed the include file `pagination.php` to `filter_footer.php`, as it is used in conjunction with `filter_header.php` for page filtering.
- Guest ticket feedback now shows the ticket prefix and number, not just the ID.
- Individual POST handler logic pages are no longer directly accessible.
- Added the ability to delete payments on the Payments and Client Payments pages.
- Implemented domain history tracking.
- Added Asset Interface Linking/Connections to show what interface is connected to which interface port of another asset.
- Added Force Recurring Ticket option in more locations, not just for recurring tickets.
- Implemented row spanning and centered devices that occupy multiple units in a rack.
- Added tooltips to main navigation badge counts to clarify what is being counted.
- Reduced max records per page from 500 to 100 to prevent performance issues.
- Updated several plugins:
- `stripe-php` from 10.5.0 to 16.4.0
- `Inputmask` from 5.0.8 to 5.0.9
- `DataTables` from 2.1.8 to 2.2.1
- `pdfmake` from 0.2.8 to 0.2.18
- `php-mime-mail-parser` to 9.0.1
- `TinyMCE` from 7.5.1 to 7.6.1
- Removed unused libraries from the vendor folder and moved Stripe to the plugins folder, eliminating the vendor folder.
- Merged the MFA TOTP functionality files `base32static.php` and `rfc6238.php` into a single file (`totp`) and moved it to the plugins folder.
- No longer need to pass the DB connection (`$mysqli`) to the `addToMailQueue` function.
- Disabled HTML Purifier caching.
- Replaced the `nullable_htmlentities` function with `htmlspecialchars`.
- Updated filter variable naming.
- Implemented other minor UI updates, performance optimizations, and directory cleanups.
### Fixed
- Fixed an issue where the ticket edit modal didn't show multi-client or no-client projects.
- Fixed asset interface losing DHCP settings.
- Fixed a 500 error when creating or editing recurring expenses due to an incorrect variable name.
- Fixed tickets created via the portal/email not being marked as billable.
- Fixed issues with editing recurring expenses.
- Resolved a regression where the TinyMCE editor didnt display when adding or editing ticket templates.
- Fixed a TinyMCE license issue.
### Removed / Deprecated
- Deprecated the cron scripts in the root directory. Cron jobs should now use the ones in the `/scripts` subfolder, which no longer require a cron key and must be run via CLI.
### BREAKING CHANGES
- The client portal has been moved from `/portal` to `/client`:
- Links in previous emails will be broken.
- The Azure Entra ID SSO Redirect URI needs to be updated to `/client`.
- You may need to update other links (e.g., website, support page).
- Guest links have been moved from `/` to `/guest`. Previous links will be broken.
## [24.12]
### Added / Changed
- Introduced versioned releases for the first time!

View File

@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at
the forums / Discord.
the forums.
All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the

View File

@@ -3,15 +3,10 @@
<!-- PROJECT SHIELDS -->
[![Contributors][contributors-shield]][contributors-url]
[![Stargazers][stars-shield]][stars-url]
[![Issues][issues-shield]][issues-url]
[![Commits][commit-shield]][commit-url]
[![GPL License][license-shield]][license-url]
<!-- PROJECT LOGO -->
<div align="center">
<!-- <a href="https://github.com/itflow-org/itflow">
<img src="images/logo.png" alt="Logo" width="80" height="80">
</a> -->
<h3 align="center">ITFlow</h3>
@@ -24,15 +19,17 @@
Username: <b>demo@demo</b> | Password: <b>demo</b>
<br />
<br />
<a href="https://itflow.org/index.php?page=About">About</a>
<a href="https://itflow.org/#about">About</a>
·
<a href="https://itflow.org/docs.php">Docs</a>
<a href="https://docs.itflow.org">Docs</a>
·
<a href="https://forum.itflow.org/">Forum</a>
·
<a href="https://github.com/itflow-org/itflow/issues">Report Bug</a>
<a href="https://forum.itflow.org/t/bug">Report Bug</a>
·
<a href="https://forum.itflow.org/t/features">Request Feature</a>
·
<a href="https://github.com/itflow-org/itflow/security/policy">Security</a>
</p>
</div>
@@ -45,58 +42,26 @@
### The Problem
- You're a busy MSP with 101 things to do.
- Information about your clients is unorganised and unstructured: scattered in random tickets or folders - when you do eventually find it, it's out of date.
- For some issues, you spend longer looking for the relevant documentation than actually working the ticket.
- You're a small but busy managed service provider with 101 things to do. Information about your clients is unorganised, unstructured and outdated.
- For some work, you seem to spend longer looking for the relevant documentation than actually working on the issue/project.
- On top of the technical day to day, you also have to take care of the financial side of the business - consistent pricing, quotes/invoicing, and accounting.
### The Solution: ITFlow
- ITFlow consolidates common MSP needs (documentation, ticketing, and accounting) into one system
### In Beta
* This project is in beta with many ongoing changes. Updates may unintentionally introduce bugs/security issues.
* Whilst we are confident the code is safe, nothing in life is 100% safe or risk-free. Use your best judgement before deciding to store highly confidential information in ITFlow.
* We are hoping to have a stable 1.0 release by April/May 2023.
<!-- BUILT WITH -->
### Built With
* Backend / PHP libs
* PHP
* MariaDB
* PHPMailer
* HTML Purifier
* PHP Mime Mail Parser
* CSS
* Bootstrap
* AdminLTE
* fontawesome
* JS Libraries
* chart.js
* moments.js
* jQuery
* pdfmake
* Select2
* SummerNote
* FullCalendar.io
- ITFlow consolidates common MSP needs (documentation, ticketing and billing) into one unified system.
<!-- GETTING STARTED -->
## Getting Started / Installation
## Getting Started
ITFlow is self-hosted. There is a full installation guide in the [docs](https://wiki.itflow.org/doku.php?id=wiki:installation), but the main steps are:
### Self Hosting
- The best installation method is to use the [install script](https://docs.itflow.org/installation_script) on Ubuntu/Debian. A video walk through is available [here](https://www.youtube.com/watch?v=kKz9NOU_1XE).
```
wget -O itflow_install.sh https://github.com/itflow-org/itflow-install-script/raw/main/itflow_install.sh
bash itflow_install.sh
```
- Other manual installation methods are available in the [docs](https://docs.itflow.org/installation).
1. Install a LAMP stack (Linux, Apache, MariaDB, PHP)
```sh
sudo apt install git apache2 php libapache2-mod-php php-intl php-imap php-mailparse php-mysqli php-curl mariadb-server
```
2. Clone the repo
```sh
git clone https://github.com/itflow-org/itflow.git /var/www/html
```
3. Create a MariaDB Database
4. Point your browser to your HTTPS web server to begin setup
### Managed Hosting
- If you'd prefer, we can [host ITFlow for you](https://services.itflow.org/hosting.php).
<!-- FEATURES -->
## Key Features
@@ -108,36 +73,34 @@ ITFlow is self-hosted. There is a full installation guide in the [docs](https://
<!-- ROADMAP -->
## Roadmap / Future to-do
* Comprehensive API to allow custom third party integration
* CalDAV to integrate with 3rd party calendars
* CardDAV to integrate with 3rd party Address books
* Recent caller toast alerts to click and bring up the clients account right away
* FIDO2 WebAuthn Support for passwordless auth (TPM Fingerprint), (USB Hardware keys such as Yubikey)
See the [forum](https://forum.itflow.org/d/11-road-map) and the [open issues](https://github.com/itflow-org/itflow/issues) for a full list of proposed features & known issues.
We track the implementation of confirmed features and bugs via [TaskFlow](https://tasks.dev.itflow.org/tasks.php). Use the [forum](https://forum.itflow.org) to request features or raise bug reports.
<!-- CONTRIBUTING -->
## Support & Contributions
### Forum
For help using ITFlow, feature requests, and general ideas / discussions please use the community [forum](https://forum.itflow.org).
For bugs, please raise an [issue](https://github.com/itflow-org/itflow/issues).
For help using ITFlow, bugs, feature requests, and general ideas / discussions please use the community [forum](https://forum.itflow.org).
### Contributing
If you are able to make a contribution that would make ITFlow better, please fork the repo and create a pull request. Please make sure you're following our [code standards](https://wiki.itflow.org/doku.php?id=wiki:code_standards).
For large changes / new features, please discuss the issue with other contributors first.
If you want to improve ITFlow, feel free to fork the repo and create a pull reques. Make sure to discuss significant changes or new features with fellow contributors on the forum first. This helps ensure that your contributions are aligned with project goals, and saves time for everyone. All contributions should follow our [code standards](https://docs.itflow.org/code_standards). See the [contributing guide](https://docs.itflow.org/contribute).
#### Contributors
<a href="https://github.com/itflow-org/itflow/graphs/contributors">
<img src="https://contrib.rocks/image?repo=itflow-org/itflow" />
</a>
<!-- LICENSE -->
## License
### Supporters
Were incredibly grateful to the organizations and individuals who support the project - a big thank you to:
- CompuMatter
- F1 for HELP
## 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.
## Security
* As of 2025, we now have a stable release of the project.
* Whilst we are confident in the safety of the code, no system is risk-free. Nearly all software has bugs. Use your best judgement before storing highly confidential information in ITFlow.
* If you have a security concern, privately report it [here](https://github.com/itflow-org/itflow/security/policy).
<!-- MARKDOWN LINKS & IMAGES -->
<!-- https://www.markdownguide.org/basic-syntax/#reference-style-links -->

View File

@@ -1,23 +1,26 @@
# Security Policy
## In Beta
## **Please do NOT report security concerns/vulnerabilities publicly (Issues/forum)**
ITFlow is currently in beta and is a work in progress.
**We take security seriously**
**We take security seriously.** Whilst we are confident the code is safe, nothing in life is 100% safe or risk-free. You should use your best judgment before entering confidential information into the app.
We attempt to follow security best practices where possible, including [automated code scanning](https://sonarcloud.io/component_measures?id=itflow-org_itflow&metric=security_rating&view=list).
- Whilst we are confident in the safety of the code, no system is risk-free. Nearly all software has bugs. Use your best judgement before storing highly confidential information in ITFlow.
- We attempt to follow security best practices where possible, including [automated code scanning](https://sonarcloud.io/component_measures?id=itflow-org_itflow&metric=security_rating&view=list).
- [![Security](https://sonarcloud.io/api/project_badges/measure?project=itflow-org_itflow&metric=security_rating)](https://sonarcloud.io/summary/new_code?id=itflow-org_itflow)
## Supported Versions
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 | :white_check_mark: |
| Beta | :x: |
| 24.12 | :white_check_mark: |
| 25.1 | :white_check_mark: (When released) |
## Reporting a Vulnerability
**<ins>Please do not report security vulnerabilities through public GitHub issues.</ins>**
If you have discovered a security issue, please [report it](https://github.com/itflow-org/itflow/security/advisories/new) to us in as much detail as possible, so we can fix it. You should expect to receive an initial acknowledgement within 72 hours.
## Reporting a Vulnerability via GitHub Security Advisories
**Security contact: [GitHub Security Advisories](https://github.com/itflow-org/itflow/security/advisories/new)**
If you have discovered a security issue, please **[report it](https://github.com/itflow-org/itflow/security/advisories/new)** to us in as much detail as possible, so we can fix it.
You should expect to receive an initial acknowledgement within 72 hours. If you don't receive any feedback, we may have missed the initial email from GitHub (we're human!). Please raise a forum discussion quoting ONLY the assigned GHSA ref.

View File

@@ -1,19 +1,23 @@
<?php
// Default Column Sortby Filter
$sb = "account_name";
$o = "ASC";
$sort = "account_name";
$order = "ASC";
require_once("inc_all.php");
require_once "includes/inc_all.php";
// Perms
enforceUserPermission('module_financial');
//Rebuild URL
$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o)));
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM accounts
WHERE account_name LIKE '%$q%' AND company_id = $session_company_id
ORDER BY $sb $o LIMIT $record_from, $record_to"
WHERE (account_name LIKE '%$q%')
AND account_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
@@ -30,19 +34,27 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="card-body">
<form autocomplete="off">
<div class="input-group">
<input type="search" class="form-control col-md-4" name="q" value="<?php if (isset($q)) { echo stripslashes(htmlentities($q)); } ?>" placeholder="Search Accounts">
<input type="search" class="form-control col-md-4" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Accounts">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
<hr>
<div class="table-responsive">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=account_name&o=<?php echo $disp; ?>">Name</a></th>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=account_currency_code&o=<?php echo $disp; ?>">Currency</a></th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=account_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'account_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=account_currency_code&order=<?php echo $disp; ?>">
Currency <?php if ($sort == 'account_currency_code') { echo $order_icon; } ?>
</a>
</th>
<th class="text-right">Balance</th>
<th class="text-center">Action</th>
</tr>
@@ -52,10 +64,10 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
while ($row = mysqli_fetch_array($sql)) {
$account_id = intval($row['account_id']);
$account_name = htmlentities($row['account_name']);
$account_name = nullable_htmlentities($row['account_name']);
$opening_balance = floatval($row['opening_balance']);
$account_currency_code = htmlentities($row['account_currency_code']);
$account_notes = htmlentities($row['account_notes']);
$account_currency_code = nullable_htmlentities($row['account_currency_code']);
$account_notes = nullable_htmlentities($row['account_notes']);
$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);
@@ -85,9 +97,9 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editAccountModal<?php echo $account_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<?php if ($balance == 0) { //Cannot Archive an Account until it reaches 0 Balance ?>
<?php if ($balance == 0 && $account_id != $config_stripe_account) { //Cannot Archive an Account until it reaches 0 Balance and cant be selected as an online account ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="post.php?archive_account=<?php echo $account_id; ?>">
<a class="dropdown-item text-danger" href="post.php?archive_account=<?php echo $account_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<?php } ?>
@@ -97,18 +109,18 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tr>
<?php
include("account_edit_modal.php");
require "modals/account_edit_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once("pagination.php"); ?>
<?php require_once "includes/filter_footer.php"; ?>
</div>
</div>
<?php
require_once("account_add_modal.php");
require_once("footer.php");
require_once "modals/account_add_modal.php";
require_once "includes/footer.php";

180
admin_api.php Normal file
View File

@@ -0,0 +1,180 @@
<?php
// Default Column Sortby Filter
$sort = "api_key_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 api_keys
LEFT JOIN clients on api_keys.api_key_client_id = clients.client_id
WHERE (api_key_name LIKE '%$q%')
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-key mr-2"></i>API Keys</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addApiKeyModal"><i class="fas fa-plus mr-2"></i>Create</button>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search keys">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-md-8">
<div class="btn-group float-right">
<div class="dropdown ml-2" id="bulkActionButton" hidden>
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
</button>
<div class="dropdown-menu">
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_api_keys">
<i class="fas fa-fw fa-trash mr-2"></i>Revoke
</button>
</div>
</div>
</div>
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<form id="bulkActions" action="post.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<td class="pr-0">
<div class="form-check">
<input class="form-check-input" type="checkbox" onclick="checkAll(this)">
</div>
</td>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'api_key_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_client_id&order=<?php echo $disp; ?>">
Client <?php if ($sort == 'api_key_client_id') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_secret&order=<?php echo $disp; ?>">
Secret <?php if ($sort == 'api_key_secret') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_created_at&order=<?php echo $disp; ?>">
Created <?php if ($sort == 'api_key_created_at') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=api_key_expire&order=<?php echo $disp; ?>">
Expires <?php if ($sort == 'api_key_expire') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$api_key_id = intval($row['api_key_id']);
$api_key_name = nullable_htmlentities($row['api_key_name']);
$api_key_secret = nullable_htmlentities("************" . substr($row['api_key_secret'], -4));
$api_key_created_at = nullable_htmlentities($row['api_key_created_at']);
$api_key_expire = nullable_htmlentities($row['api_key_expire']);
if ($api_key_expire < date("Y-m-d H:i:s")) {
$api_key_expire = $api_key_expire . " (Expired)";
}
if ($row['api_key_client_id'] == 0) {
$api_key_client = "<i>All Clients</i>";
} else {
$api_key_client = nullable_htmlentities($row['client_name']);
}
?>
<tr>
<td class="pr-0">
<div class="form-check">
<input class="form-check-input bulk-select" type="checkbox" name="api_key_ids[]" value="<?php echo $api_key_id ?>">
</div>
</td>
<td class="text-bold"><?php echo $api_key_name; ?></td>
<td><?php echo $api_key_client; ?></td>
<td><?php echo $api_key_secret; ?></td>
<td><?php echo $api_key_created_at; ?></td>
<td><?php echo $api_key_expire; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_api_key=<?php echo $api_key_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-times mr-2"></i>Revoke
</a>
</div>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</form>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<script src="js/bulk_actions.js"></script>
<?php
require_once "modals/admin_api_key_add_modal.php";
require_once "includes/footer.php";

193
admin_app_log.php Normal file
View File

@@ -0,0 +1,193 @@
<?php
// Default Column Sortby Filter
$sort = "app_log_id";
$order = "DESC";
require_once "includes/inc_all_admin.php";
// Log Type Filter
if (isset($_GET['type']) & !empty($_GET['type'])) {
$log_type_query = "AND (app_log_type = '" . sanitizeInput($_GET['type']) . "')";
$type_filter = nullable_htmlentities($_GET['type']);
} else {
// Default - any
$log_type_query = '';
$type_filter = '';
}
// Log Category Filter
if (isset($_GET['category']) & !empty($_GET['catergory'])) {
$log_category_query = "AND (app_log_category = '" . sanitizeInput($_GET['category']) . "')";
$category_filter = nullable_htmlentities($_GET['category']);
} else {
// Default - any
$log_category_query = '';
$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
WHERE (app_log_type LIKE '%$q%' OR app_log_category LIKE '%$q%' OR app_log_details LIKE '%$q%')
AND DATE(app_log_created_at) BETWEEN '$dtf' AND '$dtt'
$log_type_query
$log_category_query
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-3">
<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">
<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>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="type" onchange="this.form.submit()">
<option value="">- All Types -</option>
<?php
$sql_types_filter = mysqli_query($mysqli, "SELECT DISTINCT app_log_type FROM app_logs ORDER BY app_log_type ASC");
while ($row = mysqli_fetch_array($sql_types_filter)) {
$log_type = nullable_htmlentities($row['app_log_type']);
?>
<option <?php if ($type_filter == $log_type) { echo "selected"; } ?>><?php echo $log_type; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="category" onchange="this.form.submit()">
<option value="">- All Categories -</option>
<?php
$sql_categories_filter = mysqli_query($mysqli, "SELECT DISTINCT app_log_category FROM app_logs ORDER BY app_log_category ASC");
while ($row = mysqli_fetch_array($sql_categories_filter)) {
$log_category = nullable_htmlentities($row['app_log_category']);
?>
<option <?php if ($category_filter == $log_category) { echo "selected"; } ?>><?php echo $log_category; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label>Canned Date</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option>
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div>
</div>
</div>
</div>
</form>
<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"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=app_log_created_at&order=<?php echo $disp; ?>">
Timestamp <?php if ($sort == 'app_log_created_at') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=app_log_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'app_log_type') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=app_log_category&order=<?php echo $disp; ?>">
Category <?php if ($sort == 'app_log_category') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=app_log_details&order=<?php echo $disp; ?>">
Details <?php if ($sort == 'app_log_details') { echo $order_icon; } ?>
</a>
</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$log_id = intval($row['app_log_id']);
$log_type = nullable_htmlentities($row['app_log_type']);
$log_category = nullable_htmlentities($row['app_log_category']);
$log_details = nullable_htmlentities($row['app_log_details']);
$log_created_at = nullable_htmlentities($row['app_log_created_at']);
?>
<tr>
<td><?php echo $log_created_at; ?></td>
<td><?php echo $log_type; ?></td>
<td><?php echo $log_category; ?></td>
<td><?php echo $log_details; ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "includes/footer.php";

305
admin_audit_log.php Normal file
View File

@@ -0,0 +1,305 @@
<?php
// Default Column Sortby Filter
$sort = "log_id";
$order = "DESC";
require_once "includes/inc_all_admin.php";
// User Filter
if (isset($_GET['user']) & !empty($_GET['user'])) {
$user_query = 'AND (log_user_id = ' . intval($_GET['user']) . ')';
$user_filter = intval($_GET['user']);
} else {
// Default - any
$user_query = '';
$user_filter = '';
}
// Client Filter
if (isset($_GET['client']) & !empty($_GET['client'])) {
$client_query = 'AND (log_client_id = ' . intval($_GET['client']) . ')';
$client_filter = intval($_GET['client']);
} else {
// Default - any
$client_query = '';
$client_filter = '';
}
// Log Type Filter
if (isset($_GET['type']) & !empty($_GET['type'])) {
$log_type_query = "AND (log_type = '" . sanitizeInput($_GET['type']) . "')";
$type_filter = nullable_htmlentities($_GET['type']);
} else {
// Default - any
$log_type_query = '';
$type_filter = '';
}
// Log Action Filter
if (isset($_GET['action']) & !empty($_GET['action'])) {
$log_action_query = "AND (log_action = '" . sanitizeInput($_GET['action']) . "')";
$action_filter = nullable_htmlentities($_GET['action']);
} else {
// Default - any
$log_action_query = '';
$action_filter = '';
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM logs
LEFT JOIN users ON log_user_id = user_id
LEFT JOIN clients ON log_client_id = client_id
WHERE (log_type LIKE '%$q%' OR log_action LIKE '%$q%' OR log_description LIKE '%$q%' OR log_ip LIKE '%$q%' OR log_user_agent LIKE '%$q%' OR user_name LIKE '%$q%' OR client_name LIKE '%$q%')
AND DATE(log_created_at) BETWEEN '$dtf' AND '$dtt'
$user_query
$client_query
$log_type_query
$log_action_query
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-history mr-2"></i>Audit Logs</h3>
</div>
<div class="card-body">
<form class="mb-4" 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 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>
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="client" onchange="this.form.submit()">
<option value="">- All Clients -</option>
<?php
$sql_clients_filter = mysqli_query($mysqli, "SELECT * FROM clients 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_filter == $client_id) { echo "selected"; } ?> value="<?php echo $client_id; ?>"><?php echo $client_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="user" onchange="this.form.submit()">
<option value="">- All Users -</option>
<?php
$sql_users_filter = mysqli_query($mysqli, "SELECT * FROM users ORDER BY user_name ASC");
while ($row = mysqli_fetch_array($sql_users_filter)) {
$user_id = intval($row['user_id']);
$user_name = nullable_htmlentities($row['user_name']);
?>
<option <?php if ($user_filter == $user_id) { echo "selected"; } ?> value="<?php echo $user_id; ?>"><?php echo $user_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="type" onchange="this.form.submit()">
<option value="">- All Types -</option>
<?php
$sql_types_filter = mysqli_query($mysqli, "SELECT DISTINCT log_type FROM logs ORDER BY log_type ASC");
while ($row = mysqli_fetch_array($sql_types_filter)) {
$log_type = nullable_htmlentities($row['log_type']);
?>
<option <?php if ($type_filter == $log_type) { echo "selected"; } ?>><?php echo $log_type; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="col-sm-2">
<div class="form-group">
<select class="form-control select2" name="action" onchange="this.form.submit()">
<option value="">- All Actions -</option>
<?php
$sql_actions_filter = mysqli_query($mysqli, "SELECT DISTINCT log_action FROM logs ORDER BY log_action ASC");
while ($row = mysqli_fetch_array($sql_actions_filter)) {
$log_action = nullable_htmlentities($row['log_action']);
?>
<option <?php if ($action_filter == $log_action) { echo "selected"; } ?>><?php echo $log_action; ?></option>
<?php
}
?>
</select>
</div>
</div>
</div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label>Canned Date</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option>
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div>
</div>
</div>
</div>
</form>
<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"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_created_at&order=<?php echo $disp; ?>">
Timestamp <?php if ($sort == 'log_created_at') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_name&order=<?php echo $disp; ?>">
User <?php if ($sort == 'user_name') { echo $order_icon; } ?>
</a>
</th>
<?php if (empty($client)) { ?>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=client_name&order=<?php echo $disp; ?>">
Client <?php if ($sort == 'client_name') { echo $order_icon; } ?>
</a>
</th>
<?php } ?>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'log_type') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_action&order=<?php echo $disp; ?>">
Action <?php if ($sort == 'log_action') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_description&order=<?php echo $disp; ?>">
Description <?php if ($sort == 'log_description') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_ip&order=<?php echo $disp; ?>">
IP Address <?php if ($sort == 'log_ip') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=log_user_agent&order=<?php echo $disp; ?>">
User Agent <?php if ($sort == 'log_user_agent') { echo $order_icon; } ?>
</a>
</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$log_id = intval($row['log_id']);
$log_type = nullable_htmlentities($row['log_type']);
$log_action = nullable_htmlentities($row['log_action']);
$log_description = nullable_htmlentities($row['log_description']);
$log_ip = nullable_htmlentities($row['log_ip']);
$log_user_agent = nullable_htmlentities($row['log_user_agent']);
$log_user_os = getOS($log_user_agent);
$log_user_browser = getWebBrowser($log_user_agent);
$log_created_at = nullable_htmlentities($row['log_created_at']);
$user_id = intval($row['user_id']);
$user_name = nullable_htmlentities($row['user_name']);
if (empty($user_name)) {
$user_name_display = "-";
} else {
$user_name_display = $user_name;
}
$client_name = nullable_htmlentities($row['client_name']);
$client_id = intval($row['client_id']);
if (empty($client_name)) {
$client_name_display = "-";
} else {
$client_name_display = "<a href='client_overview.php?client_id=$client_id'>$client_name</a>";
}
$log_entity_id = intval($row['log_entity_id']);
?>
<tr>
<td><?php echo $log_created_at; ?></td>
<td><?php echo $user_name_display; ?></td>
<?php if(empty($client)) { ?>
<td><?php echo $client_name_display; ?></td>
<?php } ?>
<td><?php echo $log_type; ?></td>
<td><?php echo $log_action; ?></td>
<td><?php echo $log_description; ?></td>
<td><?php echo $log_ip; ?></td>
<td><?php echo "$log_user_os<div class='text-secondary'>$log_user_browser</div>"; ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "includes/footer.php";

38
admin_backup.php Normal file
View File

@@ -0,0 +1,38 @@
<?php
require_once "includes/inc_all_admin.php";
?>
<div class="card card-dark mb-3">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-database mr-2"></i>Download Database</h3>
</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>
</div>
</div>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-key mr-2"></i>Backup Master Encryption Key</h3>
</div>
<div class="card-body">
<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>
<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>
</div>
</div>
</div>
<?php
require_once "includes/footer.php";

153
admin_bulk_mail.php Normal file
View File

@@ -0,0 +1,153 @@
<?php
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli, "SELECT * FROM contacts
LEFT JOIN clients ON client_id = contact_client_id
WHERE client_archived_at IS NULL
AND contact_archived_at IS NULL
AND contact_email != ''
AND (contact_primary = 1 OR
contact_important = 1 OR
contact_billing = 1 OR
contact_technical = 1)
ORDER BY client_name ASC, contact_primary DESC,
contact_important DESC"
);
?>
<div class="card">
<div class="card-header">
<h3 class="card-title mt-2 mb-2"><i class="fa fa-fw fa-envelope-open mr-2"></i>Bulk Mail</h3>
<div class="card-tools">
<button id="bulkActionButton" hidden class="btn btn-primary" type="submit" form='bulkActions' name="send_bulk_mail_now">
<i class="fas fa-fw fa-paper-plane mr-2"></i>Send (<span id="selectedCount">0</span>)
</button>
</div>
</div>
<div class="card-body">
<form id="bulkActions" action="post.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="row">
<div class="col">
<h5>Email Message</h5>
<hr>
<div class="form-group">
<select type="text" class="form-control select2" name="mail_from">
<option value="<?php echo nullable_htmlentities($config_mail_from_email); ?>">
<?php echo nullable_htmlentities("$config_mail_from_name - $config_mail_from_email"); ?></option>
<option value="<?php echo nullable_htmlentities($config_invoice_from_email); ?>">
<?php echo nullable_htmlentities("$config_invoice_from_name - $config_invoice_from_email"); ?></option>
<option value="<?php echo nullable_htmlentities($config_quote_from_email); ?>">
<?php echo nullable_htmlentities("$config_quote_from_name - $config_quote_from_email"); ?></option>
<option value="<?php echo nullable_htmlentities($config_ticket_from_email); ?>">
<?php echo nullable_htmlentities("$config_ticket_from_name - $config_ticket_from_email"); ?></option>
</select>
</div>
<div class="form-group">
<input type="text" class="form-control" name="mail_from_name" placeholder="From Name" value="<?php echo nullable_htmlentities($config_mail_from_name); ?>" required>
</div>
<div class="form-group">
<input type="text" class="form-control" name="subject" placeholder="Subject" required>
</div>
<div class="form-group">
<textarea class="form-control tinymce" name="body" placeholder="Type an email in here"></textarea>
</div>
<div class="form-group">
<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="datetime-local" class="form-control" name="queued_at">
</div>
</div>
</div>
<div class="col">
<h5>Select Contacts</h5>
<hr>
<div class="card">
<div class="table-responsive">
<table class="table">
<thead>
<tr>
<td>
<div class="form-check">
<input type="checkbox" class="form-check-input" id="selectAllCheckbox" onclick="checkAll(this)">
</div>
</td>
<th>Client</th>
<th>Name</th>
<th>Title</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$contact_id = intval($row['contact_id']);
$contact_name = nullable_htmlentities($row['contact_name']);
$contact_title = nullable_htmlentities($row['contact_title']);
if (empty($contact_title)) {
$contact_title_display = "-";
} else {
$contact_title_display = "$contact_title";
}
$contact_email = nullable_htmlentities($row['contact_email']);
$contact_primary = intval($row['contact_primary']);
$contact_important = intval($row['contact_important']);
$contact_billing = intval($row['contact_billing']);
$contact_technical = intval($row['contact_technical']);
$contact_client_id = intval($row['contact_client_id']);
$client_name = nullable_htmlentities($row['client_name']);
?>
<tr>
<td>
<div class="form-check">
<input type="checkbox" class="form-check-input bulk-select" name="contact_ids[]" value="<?php echo $contact_id; ?>">
</div>
</td>
<td><?php echo $client_name; ?></td>
<td>
<a href="client_contact_details.php?client_id=<?php echo $contact_client_id; ?>&contact_id=<?php echo $contact_id; ?>" target="_blank">
<?php echo $contact_name; ?>
</a>
</td>
<td><?php echo $contact_title_display; ?></td>
<td><?php echo $contact_email; ?></td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</form>
</div>
</div>
<script src="js/bulk_actions.js"></script>
<?php
require_once "includes/footer.php";

197
admin_category.php Normal file
View File

@@ -0,0 +1,197 @@
<?php
// Default Column Sortby Filter
$sort = "category_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
if (isset($_GET['category'])) {
$category = sanitizeInput($_GET['category']);
} else {
$category = "Expense";
}
//Rebuild URL
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM categories
WHERE category_name LIKE '%$q%'
AND category_type = '$category'
AND category_$archive_query
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
if (isset($_GET['archived'])) {
$category = "Archived";
}
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-list-ul mr-2"></i>
<?php echo nullable_htmlentities($category); ?> Categories
</h3>
<?php
if (!isset($_GET['archived'])) {
?>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addCategoryModal"><i
class="fas fa-plus mr-2"></i>New <?php echo nullable_htmlentities($category); ?> Category</button>
</div>
<?php
}
?>
</div>
<div class="card-body">
<form autocomplete="off">
<input type="hidden" name="category" value="<?php echo nullable_htmlentities($category); ?>">
<div class="row">
<div class="col-sm-4 mb-2">
<div class="input-group">
<input type="search" class="form-control" name="q"
value="<?php if (isset($q)) {
echo stripslashes(nullable_htmlentities($q));
} ?>"
placeholder="Search <?php echo nullable_htmlentities($category); ?> Categories ">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="btn-group float-right">
<a href="?category=Expense"
class="btn <?php if ($category == 'Expense') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Expense</a>
<a href="?category=Income"
class="btn <?php if ($category == 'Income') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Income</a>
<a href="?category=Referral"
class="btn <?php if ($category == 'Referral') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Referral</a>
<a href="?category=Payment Method"
class="btn <?php if ($category == 'Payment Method') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Payment
Method</a>
<a href="?category=Ticket"
class="btn <?php if ($category == 'Ticket') {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>">Ticket</a>
<a href="?archived=1"
class="btn <?php if (isset($_GET['archived'])) {
echo 'btn-primary';
} else {
echo 'btn-default';
} ?>"><i
class="fas fa-fw fa-archive mr-2"></i>Archived</a>
</div>
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=category_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'category_name') { echo $order_icon; } ?>
</a>
</th>
<th>Color</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
$category_color = nullable_htmlentities($row['category_color']);
?>
<tr>
<td><a class="text-dark" href="#" data-toggle="modal"
data-target="#editCategoryModal<?php echo $category_id; ?>">
<?php echo $category_name; ?>
</a></td>
<td><i class="fa fa-3x fa-circle" style="color:<?php echo $category_color; ?>;"></i></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 ($category == "Archived") {
?>
<a class="dropdown-item text-success confirm-link"
href="post.php?unarchive_category=<?php echo $category_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Unarchive
</a>
<a class="dropdown-item text-danger confirm-link"
href="post.php?delete_category=<?php echo $category_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php
} else {
?>
<a class="dropdown-item" href="#" data-toggle="modal"
data-target="#editCategoryModal<?php echo $category_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<a class="dropdown-item text-danger confirm-link"
href="post.php?archive_category=<?php echo $category_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<?php
}
?>
</div>
</div>
</td>
</tr>
<?php
require "modals/admin_category_edit_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_category_add_modal.php";
require_once "includes/footer.php";

153
admin_custom_link.php Normal file
View File

@@ -0,0 +1,153 @@
<?php
// Default Column Sortby Filter
$sort = "custom_link_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 custom_links
WHERE custom_link_name LIKE '%$q%'
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-external-link-alt mr-2"></i>Custom Links</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addLinkModal"><i class="fas fa-plus mr-2"></i>New Link</button>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-sm-4 mb-2">
<form autocomplete="off">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Links">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
</div>
<div class="col-sm-8">
</div>
</div>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=custom_link_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'custom_link_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=custom_link_order&order=<?php echo $disp; ?>">
Order <?php if ($sort == 'custom_link_order') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=custom_link_uri&order=<?php echo $disp; ?>">
URI / <span class="text-secondary">New Tab</span> <?php if ($sort == 'custom_link_uri') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=custom_link_location&order=<?php echo $disp; ?>">
Location <?php if ($sort == 'custom_link_location') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$custom_link_id = intval($row['custom_link_id']);
$custom_link_name = nullable_htmlentities($row['custom_link_name']);
$custom_link_uri = nullable_htmlentities($row['custom_link_uri']);
$custom_link_icon = nullable_htmlentities($row['custom_link_icon']);
$custom_link_new_tab = intval($row['custom_link_new_tab']);
if ($custom_link_new_tab == 1 ) {
$custom_link_new_tab_display = "<i class='fas fa-fw fa-checkmark'></i>";
} else {
$custom_link_new_tab_display = "";
}
$custom_link_order = intval($row['custom_link_order']);
if ($custom_link_order == 0 ) {
$custom_link_order_display = "-";
} else {
$custom_link_order_display = $custom_link_order;
}
$custom_link_location = intval($row['custom_link_location']);
if ($custom_link_location == 1) {
$custom_link_location_display = "Main Side Nav";
} else {
$custom_link_location_display = "Top Nav";
}
?>
<tr>
<td>
<a href="#" data-toggle="modal" data-target="#editLinkModal<?php echo $custom_link_id; ?>">
<i class="fa fa-fw fa-<?php echo $custom_link_icon; ?> mr-2"></i>
<?php echo $custom_link_name;?>
</a>
</td>
<td><?php echo $custom_link_order_display; ?></td>
<td><?php echo "$custom_link_uri $custom_link_new_tab_display"; ?></td>
<td><?php echo $custom_link_location_display; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editLinkModal<?php echo $custom_link_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_custom_link=<?php echo $custom_link_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
require "modals/admin_custom_link_edit_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_custom_link_add_modal.php";
require_once "includes/footer.php";

757
admin_debug.php Normal file
View File

@@ -0,0 +1,757 @@
<?php
require_once "includes/inc_all_admin.php";
require_once "includes/database_version.php";
require_once "config.php";
$checks = [];
// Execute the git command to get the latest commit hash
$commitHash = shell_exec('git log -1 --format=%H');
// Get branch info
$gitBranch = shell_exec('git rev-parse --abbrev-ref HEAD');
// Section: System Information
$systemInfo = [];
// Operating System and Version
$os = php_uname();
$systemInfo[] = [
'name' => 'Operating System',
'value' => $os,
];
// Web Server and Version
$webServer = $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown';
$systemInfo[] = [
'name' => 'Web Server',
'value' => $webServer,
];
// Kernel and Version
$kernelVersion = php_uname('r');
$systemInfo[] = [
'name' => 'Kernel Version',
'value' => $kernelVersion,
];
// Database and Version
$dbVersion = $mysqli->server_info;
$systemInfo[] = [
'name' => 'Database Version',
'value' => $dbVersion,
];
// Section: PHP Extensions
$phpExtensions = [];
$extensions = [
'php-mailparse' => 'mailparse',
'php-imap' => 'imap',
'php-mysqli' => 'mysqli',
'php-intl' => 'intl',
'php-curl' => 'curl',
'php-mbstring' => 'mbstring',
'php-gd' => 'gd',
];
foreach ($extensions as $name => $ext) {
$loaded = extension_loaded($ext);
$phpExtensions[] = [
'name' => "$name installed",
'passed' => $loaded,
'value' => $loaded ? 'Installed' : 'Not Installed',
];
}
// Section: PHP Configuration
$phpConfig = [];
// Check if shell_exec is enabled
$disabled_functions = explode(',', ini_get('disable_functions'));
$disabled_functions = array_map('trim', $disabled_functions);
$shell_exec_enabled = !in_array('shell_exec', $disabled_functions);
$phpConfig[] = [
'name' => 'shell_exec is enabled',
'passed' => $shell_exec_enabled,
'value' => $shell_exec_enabled ? 'Enabled' : 'Disabled',
];
// Check upload_max_filesize and post_max_size >= 500M
function return_bytes($val) {
$val = trim($val);
$unit = strtolower(substr($val, -1));
$num = (float)$val;
switch ($unit) {
case 'g':
$num *= 1024;
case 'm':
$num *= 1024;
case 'k':
$num *= 1024;
}
return $num;
}
$required_bytes = 500 * 1024 * 1024; // 500M in bytes
$upload_max_filesize = ini_get('upload_max_filesize');
$post_max_size = ini_get('post_max_size');
$upload_passed = return_bytes($upload_max_filesize) >= $required_bytes;
$post_passed = return_bytes($post_max_size) >= $required_bytes;
$phpConfig[] = [
'name' => 'upload_max_filesize >= 500M',
'passed' => $upload_passed,
'value' => $upload_max_filesize,
];
$phpConfig[] = [
'name' => 'post_max_size >= 500M',
'passed' => $post_passed,
'value' => $post_max_size,
];
// PHP Memory Limit >= 128M
$memoryLimit = ini_get('memory_limit');
$memoryLimitBytes = return_bytes($memoryLimit);
$memoryLimitPassed = $memoryLimitBytes >= (128 * 1024 * 1024);
$phpConfig[] = [
'name' => 'PHP Memory Limit >= 128M',
'passed' => $memoryLimitPassed,
'value' => $memoryLimit,
];
// Max Execution Time >= 300 seconds
$maxExecutionTime = ini_get('max_execution_time');
$maxExecutionTimePassed = $maxExecutionTime >= 300;
$phpConfig[] = [
'name' => 'Max Execution Time >= 300 seconds',
'passed' => $maxExecutionTimePassed,
'value' => $maxExecutionTime . ' seconds',
];
// Check PHP version >= 8.2.0
$php_version = PHP_VERSION;
$php_passed = version_compare($php_version, '8.2.0', '>=');
$phpConfig[] = [
'name' => 'PHP version >= 8.2.0',
'passed' => $php_passed,
'value' => $php_version,
];
// Section: Shell Commands
$shellCommands = [];
if ($shell_exec_enabled) {
$commands = ['whois', 'dig', 'git'];
foreach ($commands as $command) {
$which = trim(shell_exec("which $command 2>/dev/null"));
$exists = !empty($which);
$shellCommands[] = [
'name' => "Command '$command' available",
'passed' => $exists,
'value' => $exists ? $which : 'Not Found',
];
}
} else {
// If shell_exec is disabled, mark commands as unavailable
foreach (['whois', 'dig', 'git'] as $command) {
$shellCommands[] = [
'name' => "Command '$command' available",
'passed' => false,
'value' => 'shell_exec Disabled',
];
}
}
// Section: SSL Checks
$sslChecks = [];
// Check if accessing via HTTPS
$https = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') || $_SERVER['SERVER_PORT'] == 443;
$sslChecks[] = [
'name' => 'Accessing via HTTPS',
'passed' => $https,
'value' => $https ? 'Yes' : 'No',
];
// SSL Certificate Validity Check
if ($https) {
$streamContext = stream_context_create(["ssl" => ["capture_peer_cert" => true]]);
$socket = @stream_socket_client("ssl://{$_SERVER['HTTP_HOST']}:443", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $streamContext);
if ($socket) {
$params = stream_context_get_params($socket);
$cert = $params['options']['ssl']['peer_certificate'];
$certInfo = openssl_x509_parse($cert);
$validFrom = $certInfo['validFrom_time_t'];
$validTo = $certInfo['validTo_time_t'];
$currentTime = time();
$certValid = ($currentTime >= $validFrom && $currentTime <= $validTo);
$sslChecks[] = [
'name' => 'SSL Certificate is valid',
'passed' => $certValid,
'value' => $certValid ? 'Valid' : 'Invalid or Expired',
];
} else {
$sslChecks[] = [
'name' => 'SSL Certificate is valid',
'passed' => false,
'value' => 'Unable to retrieve certificate',
];
}
} else {
$sslChecks[] = [
'name' => 'SSL Certificate is valid',
'passed' => false,
'value' => 'Not using HTTPS',
];
}
// Section: Domain Checks
$domainChecks = [];
// Check if the site has a valid FQDN
$fqdn = $_SERVER['HTTP_HOST'];
$isValidFqdn = (bool) filter_var('http://' . $fqdn, FILTER_VALIDATE_URL) && preg_match('/^[a-z0-9.-]+\.[a-z]{2,}$/i', $fqdn);
$domainChecks[] = [
'name' => 'Site has a valid FQDN',
'passed' => $isValidFqdn,
'value' => $fqdn,
];
// Section: File Permissions
$filePermissions = [];
// Check if web user has write access to webroot directory
$webroot = $_SERVER['DOCUMENT_ROOT'];
$writable = is_writable($webroot);
$filePermissions[] = [
'name' => 'Web user has write access to webroot directory',
'passed' => $writable,
'value' => $webroot,
];
// Section: Uploads Directory Stats
$uploadsStats = [];
// Define the uploads directory path
$uploadsDir = __DIR__ . '/uploads'; // Adjust the path if needed
if (is_dir($uploadsDir)) {
// Function to recursively count files and calculate total size
function getDirStats($dir) {
$files = 0;
$size = 0;
$iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir));
foreach ($iterator as $file) {
if ($file->isFile()) {
$files++;
$size += $file->getSize();
}
}
return ['files' => $files, 'size' => $size];
}
$stats = getDirStats($uploadsDir);
$sizeInMB = round($stats['size'] / (1024 * 1024), 2);
$uploadsStats[] = [
'name' => 'Number of files in uploads directory',
'value' => $stats['files'],
];
$uploadsStats[] = [
'name' => 'Total size of uploads directory (MB)',
'value' => $sizeInMB . ' MB',
];
} else {
$uploadsStats[] = [
'name' => 'Uploads directory exists',
'value' => 'Directory not found',
];
}
// Section: Database Stats
$databaseStats = [];
// Get list of tables
$tablesResult = $mysqli->query("SHOW TABLE STATUS");
if ($tablesResult) {
$totalTables = 0;
$totalFields = 0;
$totalRows = 0;
$totalSize = 0;
$tableDetails = [];
while ($table = $tablesResult->fetch_assoc()) {
$tableName = $table['Name'];
$tableRows = $table['Rows'];
$dataLength = $table['Data_length'];
$indexLength = $table['Index_length'];
$tableSize = ($dataLength + $indexLength) / (1024 * 1024); // Size in MB
// Get number of fields
$fieldsResult = $mysqli->query("SHOW COLUMNS FROM `$tableName`");
$numFields = $fieldsResult->num_rows;
$fieldsResult->free();
$totalTables++;
$totalFields += $numFields;
$totalRows += $tableRows;
$totalSize += $tableSize;
$tableDetails[] = [
'name' => $tableName,
'fields' => $numFields,
'rows' => $tableRows,
'size' => round($tableSize, 2),
];
}
$tablesResult->free();
$databaseStats[] = [
'name' => 'Total number of tables',
'value' => $totalTables,
];
$databaseStats[] = [
'name' => 'Total number of fields',
'value' => $totalFields,
];
$databaseStats[] = [
'name' => 'Total number of rows',
'value' => $totalRows,
];
$databaseStats[] = [
'name' => 'Total database size (MB)',
'value' => round($totalSize, 2) . ' MB',
];
} else {
$databaseStats[] = [
'name' => 'Database connection error',
'value' => $mysqli->error,
];
}
// Section: Database Structure Comparison
$dbComparison = [];
// Path to the db.sql file
$dbSqlFile = __DIR__ . '/db.sql';
if (file_exists($dbSqlFile)) {
// Read the db.sql file
$sqlContent = file_get_contents($dbSqlFile);
// Remove comments and empty lines
$lines = explode("\n", $sqlContent);
$sqlStatements = [];
$statement = '';
foreach ($lines as $line) {
// Remove single-line comments
$line = preg_replace('/--.*$/', '', $line);
$line = preg_replace('/\/\*.*?\*\//', '', $line);
// Skip empty lines
if (trim($line) == '') {
continue;
}
// Append line to the current statement
$statement .= $line . "\n";
// Check if the statement ends with a semicolon
if (preg_match('/;\s*$/', $line)) {
$sqlStatements[] = $statement;
$statement = '';
}
}
// Parse the CREATE TABLE statements
$sqlTables = [];
foreach ($sqlStatements as $sql) {
if (preg_match('/CREATE TABLE\s+`?([^` ]+)`?\s*\((.*)\)(.*?);/msi', $sql, $match)) {
$tableName = $match[1];
$columnsDefinition = $match[2];
// Extract column names and data types
$columns = [];
$columnLines = explode("\n", $columnsDefinition);
foreach ($columnLines as $line) {
$line = trim($line);
// Skip empty lines and lines that do not define columns
if ($line == '' || strpos($line, 'PRIMARY KEY') !== false || strpos($line, 'UNIQUE KEY') !== false || strpos($line, 'KEY') === 0 || strpos($line, 'CONSTRAINT') === 0 || strpos($line, ')') === 0) {
continue;
}
// Remove trailing comma if present
$line = rtrim($line, ',');
// Match column definition
if (preg_match('/^`([^`]+)`\s+(.+)/', $line, $colMatch)) {
$colName = $colMatch[1];
$colDefinition = $colMatch[2];
// Extract the data type from the column definition
$tokens = preg_split('/\s+/', $colDefinition);
$colType = $tokens[0];
// Handle data types with parentheses (e.g., varchar(255), decimal(15,2))
if (preg_match('/^([a-zA-Z]+)\(([^)]+)\)/', $colType, $typeMatch)) {
$colType = $typeMatch[1] . '(' . $typeMatch[2] . ')';
}
$columns[$colName] = $colType;
}
}
$sqlTables[$tableName] = $columns;
}
}
// Get current database table structures
$dbTables = [];
$tablesResult = $mysqli->query("SHOW TABLES");
while ($row = $tablesResult->fetch_row()) {
$tableName = $row[0];
$columnsResult = $mysqli->query("SHOW COLUMNS FROM `$tableName`");
$columns = [];
while ($col = $columnsResult->fetch_assoc()) {
$columns[$col['Field']] = $col['Type'];
}
$columnsResult->free();
$dbTables[$tableName] = $columns;
}
$tablesResult->free();
// Compare the structures
foreach ($sqlTables as $tableName => $sqlColumns) {
if (!isset($dbTables[$tableName])) {
$dbComparison[] = [
'name' => "Table `$tableName` missing in database",
'status' => 'Missing Table',
];
continue;
}
// Compare columns
$dbColumns = $dbTables[$tableName];
foreach ($sqlColumns as $colName => $colType) {
if (!isset($dbColumns[$colName])) {
$dbComparison[] = [
'name' => "Column `$colName` missing in table `$tableName`",
'status' => 'Missing Column',
];
} else {
// Normalize data types for comparison
$sqlColType = strtolower($colType);
$dbColType = strtolower($dbColumns[$colName]);
// Remove attributes and constraints
$sqlColType = preg_replace('/\s+.*$/', '', $sqlColType);
$dbColType = preg_replace('/\s+.*$/', '', $dbColType);
// Remove additional attributes like unsigned, zerofill, etc.
$sqlColType = preg_replace('/\s+unsigned|\s+zerofill|\s+binary/', '', $sqlColType);
$dbColType = preg_replace('/\s+unsigned|\s+zerofill|\s+binary/', '', $dbColType);
if ($sqlColType != $dbColType) {
$dbComparison[] = [
'name' => "Data type mismatch for `$colName` in table `$tableName`",
'status' => "Expected: $colType, Found: {$dbColumns[$colName]}",
];
}
}
}
// Check for extra columns in the database that are not in the SQL file
foreach ($dbColumns as $colName => $colType) {
if (!isset($sqlColumns[$colName])) {
$dbComparison[] = [
'name' => "Extra column `$colName` in table `$tableName` not present in db.sql",
'status' => 'Extra Column',
];
}
}
}
// Check for tables in the database not present in the db.sql file
foreach ($dbTables as $tableName => $dbColumns) {
if (!isset($sqlTables[$tableName])) {
$dbComparison[] = [
'name' => "Extra table `$tableName` in database not present in db.sql",
'status' => 'Extra Table',
];
}
}
} else {
$dbComparison[] = [
'name' => 'db.sql file not found',
'status' => 'File Missing',
];
}
$mysqli->close();
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-bug mr-2"></i>Debug</h3>
</div>
<div class="card-body">
<h2>Debugging</h2>
<ul>
<li>If you are experiencing a problem with ITFlow, this page should help you identify any configuration issues.</li>
<li>Note: You might also need to gather <a href="https://docs.itflow.org/gathering_logs#error_logs">error logs</a></li>
</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>
<!-- System Information Table -->
<h3>System Information</h3>
<table class="table table-sm table-bordered">
<tbody>
<?php foreach ($systemInfo as $info): ?>
<tr>
<td><?= htmlspecialchars($info['name']); ?></td>
<td><?= htmlspecialchars($info['value']); ?></td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- 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>
</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>
</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>
</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>
</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>
</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>
</tr>
<?php endforeach; ?>
</tbody>
</table>
<!-- 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): ?>
<tr>
<td><?= htmlspecialchars($issue['name']); ?></td>
<td colspan="2"><?= htmlspecialchars($issue['status']); ?></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>
<!-- 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>
<!-- 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>
<!-- 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): ?>
<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>
<?php
require_once "includes/footer.php";

170
admin_document_template.php Normal file
View File

@@ -0,0 +1,170 @@
<?php
// Default Column Sort by Filter
$sort = "document_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
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file mr-2"></i>Document Templates</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addDocumentTemplateModal">
<i class="fas fa-plus mr-2"></i>New Template
</button>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<div class="input-group">
<input type="search" class="form-control " name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search templates">
<div class="input-group-append">
<button class="btn btn-secondary"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<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>
</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>
</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>
</th>
<th class="text-center">
Action
</th>
</tr>
</thead>
<tbody>
<?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']);
?>
<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>
</td>
<td>
<?php echo $document_created_at; ?>
<div class="text-secondary"><?php echo $document_created_by_name; ?></div>
</td>
<td><?php echo $document_updated_at; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editDocumentTemplateModal<?php echo $document_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; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
require "modals/admin_document_template_edit_modal.php";
}
?>
</tbody>
</table>
<br>
</div>
<?php require_once "includes/filter_footer.php"; ?>
</div>
</div>
<?php require_once "modals/admin_document_template_add_modal.php"; ?>
<?php require_once "includes/footer.php"; ?>
<script>
$(document).ready(function(){
$('#generateAIContent').on('click', function(){
var prompt = $('#aiPrompt').val().trim();
if(prompt === '') {
alert('Please enter a prompt.');
return;
}
$('#generateAIContent').prop('disabled', true).html('<i class="fa fa-spinner fa-spin"></i> Generating...');
$.ajax({
url: 'post.php?ai_create_document_template', // The PHP script that calls the OpenAI API
method: 'POST',
data: { prompt: prompt },
dataType: 'html',
success: function(response) {
// Assuming you have exactly one TinyMCE instance on the page
// and it's targeting the .tinymce textarea:
tinymce.activeEditor.setContent(response);
},
error: function() {
alert('Error generating content. Please try again.');
},
complete: function() {
$('#generateAIContent').prop('disabled', false).html('<i class="fa fa-fw fa-magic mr-1"></i>Generate with AI');
}
});
});
});
</script>

View File

@@ -0,0 +1,66 @@
<?php
require_once "includes/inc_all_admin.php";
//Initialize the HTML Purifier to prevent XSS
require "plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
$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']);
}
$sql_document = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_template = 1 AND document_id = $document_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']);
?>
<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_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>
</ol>
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-file mr-2"></i><?php echo $document_name; ?></h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#editDocumentTemplateModal<?php echo $document_id; ?>">
<i class="fas fa-edit mr-2"></i>Edit
</button>
</div>
</div>
<div class="card-body prettyContent">
<?php echo $document_content; ?>
</div>
</div>
<script src="js/pretty_content.js"></script>
<?php
require_once "modals/admin_document_template_edit_modal.php";
require_once "includes/footer.php";

213
admin_mail_queue.php Normal file
View File

@@ -0,0 +1,213 @@
<?php
// Default Column Sortby Filter
$sort = "email_id";
$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
WHERE (email_id LIKE '%$q%' OR email_from LIKE '%$q%' OR email_from_name LIKE '%$q%' OR email_recipient LIKE '%$q%' OR email_recipient_name LIKE '%$q%' OR email_subject LIKE '%$q%')
AND DATE(email_queued_at) BETWEEN '$dtf' AND '$dtt'
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-mail-bulk mr-2"></i>Email Queue</h3>
</div>
<div class="card-body">
<form class="mb-4" 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 mail queue">
<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 class="col-sm-8">
<div class="dropdown float-right" id="bulkActionButton" hidden>
<button class="btn btn-secondary dropdown-toggle" type="button" data-toggle="dropdown">
<i class="fas fa-fw fa-layer-group mr-2"></i>Bulk Action (<span id="selectedCount">0</span>)
</button>
<div class="dropdown-menu">
<button class="dropdown-item"
type="submit" form="bulkActions" name="bulk_cancel_emails">
<i class="fas fa-fw fa-ban mr-2"></i>Cancel
</button>
<div class="dropdown-divider"></div>
<button class="dropdown-item text-danger text-bold"
type="submit" form="bulkActions" name="bulk_delete_emails">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</button>
</div>
</div>
</div>
</div>
<div class="collapse mt-3 <?php if (!empty($_GET['dtf']) || $_GET['canned_date'] !== "custom" ) { echo "show"; } ?>" id="advancedFilter">
<div class="row">
<div class="col-md-2">
<div class="form-group">
<label>Canned Date</label>
<select onchange="this.form.submit()" class="form-control select2" name="canned_date">
<option <?php if ($_GET['canned_date'] == "custom") { echo "selected"; } ?> value="">Custom</option>
<option <?php if ($_GET['canned_date'] == "today") { echo "selected"; } ?> value="today">Today</option>
<option <?php if ($_GET['canned_date'] == "yesterday") { echo "selected"; } ?> value="yesterday">Yesterday</option>
<option <?php if ($_GET['canned_date'] == "thisweek") { echo "selected"; } ?> value="thisweek">This Week</option>
<option <?php if ($_GET['canned_date'] == "lastweek") { echo "selected"; } ?> value="lastweek">Last Week</option>
<option <?php if ($_GET['canned_date'] == "thismonth") { echo "selected"; } ?> value="thismonth">This Month</option>
<option <?php if ($_GET['canned_date'] == "lastmonth") { echo "selected"; } ?> value="lastmonth">Last Month</option>
<option <?php if ($_GET['canned_date'] == "thisyear") { echo "selected"; } ?> value="thisyear">This Year</option>
<option <?php if ($_GET['canned_date'] == "lastyear") { echo "selected"; } ?> value="lastyear">Last Year</option>
</select>
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date From</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtf" max="2999-12-31" value="<?php echo nullable_htmlentities($dtf); ?>">
</div>
</div>
<div class="col-md-2">
<div class="form-group">
<label>Date To</label>
<input onchange="this.form.submit()" type="date" class="form-control" name="dtt" max="2999-12-31" value="<?php echo nullable_htmlentities($dtt); ?>">
</div>
</div>
</div>
</div>
</form>
<hr>
<form id="bulkActions" action="post.php" method="post">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="table-responsive-sm">
<table class="table table-sm table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<td class="bg-light pr-0">
<div class="form-check">
<input class="form-check-input" id="selectAllCheckbox" type="checkbox" onclick="checkAll(this)">
</div>
</td>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=email_queued_at&order=<?php echo $disp; ?>">
Queued <?php if ($sort == 'email_queued_at') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=email_from&order=<?php echo $disp; ?>">
From <?php if ($sort == 'email_from') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=email_recipient&order=<?php echo $disp; ?>">
To <?php if ($sort == 'email_recipient') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=email_subject&order=<?php echo $disp; ?>">
Subject <?php if ($sort == 'email_subject') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=email_status&order=<?php echo $disp; ?>">
Status <?php if ($sort == 'email_status') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=email_attempts&order=<?php echo $disp; ?>">
Attempts <?php if ($sort == 'email_attempts') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$email_id = intval($row['email_id']);
$email_from = nullable_htmlentities($row['email_from']);
$email_from_name = nullable_htmlentities($row['email_from_name']);
$email_recipient = nullable_htmlentities($row['email_recipient']);
$email_recipient_name = nullable_htmlentities($row['email_recipient_name']);
$email_subject = nullable_htmlentities($row['email_subject']);
$email_attempts = intval($row['email_attempts']);
$email_queued_at = nullable_htmlentities($row['email_queued_at']);
$email_failed_at = nullable_htmlentities($row['email_failed_at']);
$email_sent_at = nullable_htmlentities($row['email_sent_at']);
$email_status = intval($row['email_status']);
if ($email_status == 0) {
$email_status_display = "<div class='text-primary'>Queued</div>";
} elseif($email_status == 1) {
$email_status_display = "<div class='text-warning'>Sending</div>";
} elseif($email_status == 2) {
$email_status_display = "<div class='text-danger'>Failed</div><small class='text-secondary'>$email_failed_at</small>";
} else {
$email_status_display = "<div class='text-success'>Sent</div><small class='text-secondary'>$email_sent_at</small>";
}
?>
<tr>
<td class="pr-0 bg-light">
<?php if ($email_status !== 3) { ?>
<div class="form-check">
<input class="form-check-input bulk-select" type="checkbox" name="email_ids[]" value="<?php echo $email_id ?>">
</div>
<?php } ?>
</td>
<td><?php echo $email_queued_at; ?></td>
<td><?php echo "$email_from<br><small class='text-secondary'>$email_from_name</small>"?></td>
<td><?php echo "$email_recipient<br><small class='text-secondary'>$email_recipient_name</small>"?></td>
<td><?php echo $email_subject; ?></td>
<td><?php echo $email_status_display; ?></td>
<td><?php echo $email_attempts; ?></td>
<td class="text-center">
<a class="btn btn-sm btn-secondary" href="admin_mail_queue_message_view.php?email_id=<?php echo $email_id; ?>">
<i class="fas fa-fw fa-eye"></i>
</a>
<!-- Show force resend if all retries have failed -->
<?php if ($email_status == 2 && $email_attempts > 3) { ?>
<a class="btn btn-sm btn-success" href="post.php?send_failed_mail=<?php echo $email_id; ?>"><i class="fas fa-fw fa-paper-plane"></i></a>
<?php } ?>
<!-- Allow cancelling a message if it hasn't yet been picked up (e.g. stuck/bugged) -->
<?php if ($email_status !== 3) { ?>
<a class="btn btn-sm btn-danger confirm-link" href="post.php?cancel_mail=<?php echo $email_id; ?>"><i class="fas fa-fw fa-trash"></i></a>
<?php } ?>
</td>
</tr>
<?php
}
?>
</tbody>
</table>
</div>
</form>
<?php require_once "includes/filter_footer.php"; ?>
</div>
</div>
<script src="js/bulk_actions.js"></script>
<?php
require_once "includes/footer.php";

View File

@@ -0,0 +1,78 @@
<?php
require_once "includes/inc_all_admin.php";
//Initialize the HTML Purifier to prevent XSS
require "plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
$purifier_config->set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]);
$purifier = new HTMLPurifier($purifier_config);
if (isset($_GET['email_id'])) {
$email_id = intval($_GET['email_id']);
} else {
echo "You dont belong here";
exit();
}
$sql = mysqli_query($mysqli, "SELECT * FROM email_queue WHERE email_id = $email_id");
$row = mysqli_fetch_array($sql);
$email_from = nullable_htmlentities($row['email_from']);
$email_from_name = nullable_htmlentities($row['email_from_name']);
$email_recipient = nullable_htmlentities($row['email_recipient']);
$email_recipient_name = nullable_htmlentities($row['email_recipient_name']);
$email_subject = nullable_htmlentities($row['email_subject']);
$email_content = $purifier->purify($row['email_content']);
$email_attempts = intval($row['email_attempts']);
$email_queued_at = nullable_htmlentities($row['email_queued_at']);
$email_failed_at = nullable_htmlentities($row['email_failed_at']);
$email_sent_at = nullable_htmlentities($row['email_sent_at']);
$email_status = intval($row['email_status']);
if ($email_status == 0) {
$email_status_display = "<div class='text-primary'>Queued</div>";
} elseif($email_status == 1) {
$email_status_display = "<div class='text-warning'>Sending</div>";
} elseif($email_status == 2) {
$email_status_display = "<div class='text-danger'>Failed</div><small class='text-secondary'>$email_failed_at</small>";
} else {
$email_status_display = "<div class='text-success'>Sent</div><small class='text-secondary'>$email_sent_at</small>";
}
?>
<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="admin_user.php"><i class="fas fa-fw fa-user-shield mr-2"></i>Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_mail_queue.php"><i class="fas fa-fw fa-mail-bulk mr-2"></i>Mail Queue</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-fw fa-envelope-open mr-2"></i><?php echo $email_subject; ?></li>
</ol>
<div class="row">
<div class="col-md-12">
<div class="card">
<div class="card-header bg-dark">
<div>From: <?php echo "$email_from_name <small>($email_from)</small>"; ?></div>
<div>To: <?php echo "$email_recipient_name <small>($email_recipient)</small>"; ?></div>
<div>Subject: <?php echo $email_subject; ?></div>
</div>
<div class="card-body prettyContent">
<?php echo $email_content; ?>
</div>
</div>
</div>
</div>
<script src="js/pretty_content.js"></script>
<?php
require_once "includes/footer.php";

149
admin_project_template.php Normal file
View File

@@ -0,0 +1,149 @@
<?php
// Default Column Sortby Filter
$sort = "project_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 project_templates
WHERE (project_template_name LIKE '%$q%' OR project_template_description LIKE '%$q%')
AND project_template_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-project-diagram mr-2"></i>Project Templates</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addProjectTemplateModal"><i class="fas fa-plus mr-2"></i>New Project Template</button>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if(isset($q)){ echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Project Templates">
<div class="input-group-append">
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-md-8">
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if($num_rows[0] == 0){ echo "d-none"; } ?>">
<tr>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=project_template_name&order=<?php echo $disp; ?>">
Template <?php if ($sort == 'project_template_name') { echo $order_icon; } ?>
</a>
</th>
<th>Tickets</th>
<th>Tasks</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while($row = mysqli_fetch_array($sql)){
$project_template_id = intval($row['project_template_id']);
$project_template_name = nullable_htmlentities($row['project_template_name']);
$project_template_description = nullable_htmlentities($row['project_template_description']);
$project_template_created_at = nullable_htmlentities($row['project_template_created_at']);
// Get Ticket Template Count
$sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates, project_template_ticket_templates
WHERE ticket_templates.ticket_template_id = project_template_ticket_templates.ticket_template_id
AND project_template_ticket_templates.project_template_id = $project_template_id
ORDER BY ticket_template_order ASC, ticket_template_name ASC");
$ticket_template_count = mysqli_num_rows($sql_ticket_templates);
// Get Tasks Template Count
$sql_task_templates = mysqli_query($mysqli,
"SELECT * FROM ticket_templates, task_templates, project_template_ticket_templates
WHERE ticket_templates.ticket_template_id = project_template_ticket_templates.ticket_template_id
AND project_template_ticket_templates.project_template_id = $project_template_id
AND ticket_templates.ticket_template_id = task_template_ticket_template_id
ORDER BY task_template_created_at ASC"
);
$task_template_count = mysqli_num_rows($sql_task_templates);
?>
<tr>
<td>
<a class="text-dark" href="#" data-toggle="modal" data-target="#editProjectTemplateModal<?php echo $project_template_id; ?>">
<div class="media">
<i class="fa fa-fw fa-2x fa-project-diagram mr-3"></i>
<div class="media-body">
<div>
<a href="admin_project_template_details.php?project_template_id=<?php echo $project_template_id; ?>">
<?php echo $project_template_name; ?>
</a>
</div>
<div><small class="text-secondary"><?php echo $project_template_description; ?></small></div>
</div>
</div>
</a>
</td>
<td><?php echo $ticket_template_count; ?></td>
<td><?php echo $task_template_count; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editProjectTemplateModal<?php echo $project_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_project_template=<?php echo $project_template_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
</div>
</div>
</td>
</tr>
<?php
require "modals/admin_project_template_edit_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_project_template_add_modal.php";
require_once "includes/footer.php";

View File

@@ -0,0 +1,234 @@
<?php
require_once "includes/inc_all_admin.php";
if (isset($_GET['project_template_id'])) {
$project_template_id = intval($_GET['project_template_id']);
$sql_project_templates = mysqli_query(
$mysqli,
"SELECT * FROM project_templates
WHERE project_template_id = $project_template_id LIMIT 1"
);
if (mysqli_num_rows($sql_project_templates) == 0) {
echo "<center><h1 class='text-secondary mt-5'>Nothing to see here</h1><a class='btn btn-lg btn-secondary mt-3' href='admin_project_template.php'><i class='fa fa-fw fa-arrow-left'></i> Go Back</a></center>";
include_once "footer.php";
exit;
}
$row = mysqli_fetch_array($sql_project_templates);
$project_template_name = nullable_htmlentities($row['project_template_name']);
$project_template_description = nullable_htmlentities($row['project_template_description']);
$project_template_created_at = date("Y-m-d", strtotime($row['project_template_created_at']));
$project_template_updated_at = nullable_htmlentities($row['project_template_updated_at']);
// Get Associated Ticket Templates
$sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates, project_template_ticket_templates
WHERE ticket_templates.ticket_template_id = project_template_ticket_templates.ticket_template_id
AND project_template_ticket_templates.project_template_id = $project_template_id
ORDER BY ticket_template_order ASC, ticket_template_name ASC");
$ticket_template_count = mysqli_num_rows($sql_ticket_templates);
// Get All Task Templates
$sql_task_templates = mysqli_query($mysqli,
"SELECT * FROM ticket_templates, task_templates, project_template_ticket_templates
WHERE ticket_templates.ticket_template_id = project_template_ticket_templates.ticket_template_id
AND project_template_ticket_templates.project_template_id = $project_template_id
AND ticket_templates.ticket_template_id = task_template_ticket_template_id
ORDER BY task_template_created_at ASC"
);
$task_template_count = mysqli_num_rows($sql_task_templates);
?>
<!-- Breadcrumbs-->
<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_project_template.php">Project Templates</a>
</li>
<li class="breadcrumb-item active">Project Template Details</li>
</ol>
<!-- Project Header -->
<div class="card card-body">
<div class="row">
<div class="col-sm-4">
<div class="media">
<i class="fa fa-fw fa-2x fa-project-diagram text-secondary mr-3"></i>
<div class="media-body">
<h3 class="mb-0"><?php echo $project_template_name; ?><span class='badge badge-pill badge-info ml-2'>Template</span></h3>
<div><small class="text-secondary"><?php echo $project_template_description; ?></small></div>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring text-secondary mr-3"></i>
<div class="media-body">
<div>Ticket Templates</div>
<h3 class="mb-0"><?php echo $ticket_template_count; ?></h3>
</div>
</div>
</div>
<div class="col-sm-3">
<div class="media">
<i class="fa fa-fw fa-2x fa-tasks text-secondary mr-3"></i>
<div class="media-body">
<div>Task Templates</div>
<h3 class="mb-0"><?php echo $task_template_count; ?></h3>
</div>
</div>
</div>
<div class="col-sm-2">
<div class="btn-group float-right">
<button type="button" class="btn btn-primary btn-sm" href="#" data-toggle="modal" data-target="#addProjectTemplateTicketTemplateModal">
<i class="fas fa-fw fa-plus mr-2"></i>Add Ticket Template
</button>
<div class="dropdown dropleft text-center ml-3">
<button class="btn btn-secondary btn-sm" type="button" id="dropdownMenuButton" data-toggle="dropdown">
<i class="fas fa-fw fa-ellipsis-v"></i>
</button>
<div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editProjectTemplateModal<?php echo $project_template_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit Template
</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?archive_project_template=<?php echo $project_template_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive (not yet implemented)
</a>
<?php } ?>
<?php if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?delete_project_template=<?php echo $project_template_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="row">
<div class="col-md-8">
<!-- Tickets card -->
<?php if (mysqli_num_rows($sql_ticket_templates) > 0) { ?>
<div class="card card-body card-outline card-dark mb-3">
<h5 class="text-secondary"><i class="fa fa-fw fa-life-ring mr-2"></i>Project Ticket Templates</h5>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark">
<tr>
<th>Order</th>
<th>Template Name</th>
<th>Description</th>
<th>Ticket Subject</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql_ticket_templates)) {
$ticket_template_id = intval($row['ticket_template_id']);
$ticket_template_order = intval($row['ticket_template_order']);
$ticket_template_name = nullable_htmlentities($row['ticket_template_name']);
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
$ticket_template_updated_at = nullable_htmlentities($row['ticket_template_updated_at']);
?>
<tr>
<td class="pr-0">
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="edit_ticket_template_order">
<input type="hidden" name="project_template_id" value="<?php echo $project_template_id; ?>">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<input type="text" class="form-control pr-0" onchange="this.form.submit()" name="order" value="<?php echo $ticket_template_order; ?>">
</form>
</td>
<td>
<a href="admin_ticket_template_details.php?ticket_template_id=<?php echo $ticket_template_id; ?>">
<?php echo $ticket_template_name; ?>
</a>
</td>
<td><?php echo $ticket_template_description; ?></td>
<td><?php echo $ticket_template_subject; ?></td>
<td>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="project_template_id" value="<?php echo $project_template_id; ?>">
<input type="hidden" name="ticket_template_id" value="<?php echo $ticket_template_id; ?>">
<button type="submit" class="btn btn-default btn-sm confirm-link"
name="remove_ticket_template_from_project_template">
<i class="fa fa-fw fa-times"></i>
</button>
</form>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
<?php } ?>
</div>
<div class="col-md-4">
<!-- Task Templates Card -->
<?php if (mysqli_num_rows($sql_task_templates) > 0) { ?>
<div class="card card-body card-outline card-dark">
<h5 class="text-secondary"><i class="fas fa-fw fa-tasks mr-2"></i>Project Task Templates</h5>
<table class="table">
<?php
while($row = mysqli_fetch_array($sql_task_templates)){
$task_template_id = intval($row['task_template_id']);
$task_template_name = nullable_htmlentities($row['task_template_name']);
$task_template_description = nullable_htmlentities($row['task_template_description']);
?>
<tr>
<td>
<i class="far fa-fw fa-check-square text-primary mr-3"></i>
<?php echo $task_template_name; ?>
</td>
</tr>
<?php } ?>
</table>
</div>
<?php } ?>
<!-- End Task TemplatesCard -->
</div> <!-- End col-3 -->
</div> <!-- End row -->
<?php
require_once "modals/admin_project_template_edit_modal.php";
require_once "modals/admin_project_template_ticket_template_add_modal.php";
}
require_once "includes/footer.php";
?>
<script src="js/pretty_content.js"></script>

156
admin_role.php Normal file
View File

@@ -0,0 +1,156 @@
<?php
// Default Column Sortby Filter
$sort = "user_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
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="alert alert-info text-center"><strong>Roles are still in development. Permissions may not be fully enforced.</strong></div>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-user-shield mr-2"></i>Roles</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addRoleModal">
<i class="fas fa-fw fa-user-plus mr-2"></i>New Role
</button>
</div>
</div>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {echo stripslashes(nullable_htmlentities($q));} ?>" placeholder="Search Roles">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<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>
</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>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?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']);
// 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");
$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");
// Initialize an empty array to hold user names
$user_names = [];
// Fetch each row and store the user_name in the array
while($row = mysqli_fetch_assoc($sql_users)) {
$user_names[] = nullable_htmlentities($row['user_name']);
}
// Convert the array of user names to a comma-separated string
$user_names_string = implode(",", $user_names) ;
if (empty($user_names_string)) {
$user_names_string = "-";
}
?>
<tr>
<td>
<a class="text-dark text-bold" href="#" data-toggle="modal" data-target="#editRoleModal<?php echo $role_id; ?>">
<?php echo $role_name; ?>
</a>
<div class="text-secondary"><?php echo $role_description; ?></div>
</td>
<td><?php echo $user_names_string; ?></td>
<td><?php echo $role_admin ? 'Yes' : 'No' ; ?></td>
<td>
<?php if ($role_id !== 3) { ?>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editRoleModal<?php echo $role_id; ?>">
<i class="fas fa-fw fa-user-edit mr-2"></i>Edit
</a>
<?php if (empty($role_archived_at) && $role_user_count == 0) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_role=<?php echo $role_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
<?php } ?>
</div>
</div>
<?php } ?>
</td>
</tr>
<?php
require "modals/admin_role_edit_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_role_add_modal.php";
require_once "includes/footer.php";

77
admin_settings_ai.php Normal file
View File

@@ -0,0 +1,77 @@
<?php
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-robot mr-2"></i>AI</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'] ?>">
<div class="form-group">
<label>AI Provider</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<select class="form-control select2" name="provider">
<option value="" <?php if($config_ai_enable == 0) { echo "selected"; } ?> >Disabled</option>
<option <?php if($config_ai_provider == "Ollama") { echo "selected"; } ?> >Ollama</option>
<option <?php if($config_ai_provider == "OpenAI") { echo "selected"; } ?> >OpenAI</option>
<option <?php if($config_ai_provider == "LocalAI") { echo "selected"; } ?> >LocalAI</option>
</select>
</div>
</div>
<div class="form-group">
<label>AI Model</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-robot"></i></span>
</div>
<input type="text" class="form-control" name="model" value="<?php echo nullable_htmlentities($config_ai_model); ?>" placeholder="ex gpt-4">
</div>
</div>
<div class="form-group">
<label>URL</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-globe"></i></span>
</div>
<input type="url" class="form-control" name="url" value="<?php echo nullable_htmlentities($config_ai_url); ?>" placeholder="ex https://ai.company.ext/api">
</div>
</div>
<div class="form-group">
<label>API Key</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="api_key" value="<?php echo nullable_htmlentities($config_ai_api_key); ?>" placeholder="Enter API key here">
</div>
</div>
<hr>
<button type="submit" name="edit_ai_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Save</button>
</form>
<div class="mt-5">
<h5>Test AI Rewording</h5>
<textarea id="textInput" class="form-control tinymceAI mb-3" rows="10"></textarea>
</div>
<script src="js/ai_reword.js"></script>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -1,38 +1,50 @@
<div class="modal" id="editCompanyModal<?php echo $company_id; ?>" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content bg-dark">
<div class="modal-header">
<h5 class="modal-title"><i class="fa fa-fw fa-building mr-2"></i>Editing company: <strong><?php echo $company_name; ?></strong></h5>
<button type="button" class="close text-white" data-dismiss="modal">
<span>&times;</span>
</button>
</div>
<?php
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli,"SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
$row = mysqli_fetch_array($sql);
$company_id = intval($row['company_id']);
$company_name = nullable_htmlentities($row['company_name']);
$company_country = nullable_htmlentities($row['company_country']);
$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_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_initials = nullable_htmlentities(initials($company_name));
?>
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title"><i class="fas fa-fw fa-briefcase mr-2"></i>Company Details</h3>
</div>
<div class="card-body">
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="company_id" value="<?php echo $company_id; ?>">
<input type="hidden" name="existing_file_name" value="<?php echo $company_logo; ?>">
<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 $company_id; ?>">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-address<?php echo $company_id; ?>">Address</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-contact<?php echo $company_id; ?>">Contact</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-locale<?php echo $company_id; ?>">Locale</a>
</li>
</ul>
<hr>
<div class="tab-content">
<div class="tab-pane fade show active" id="pills-details<?php echo $company_id; ?>">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="row">
<div class="col-md-3 text-center">
<?php if($company_logo) { ?>
<img class="img-thumbnail" src="<?php echo "uploads/settings/$company_logo"; ?>">
<a href="post.php?remove_company_logo" class="btn btn-outline-danger btn-block">Remove Logo</a>
<hr>
<?php } ?>
<div class="form-group">
<label>Upload company logo</label>
<input type="file" class="form-control-file" name="file" accept=".jpg, .jpeg, .png">
</div>
</div>
<div class="col-md-9">
<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
@@ -43,20 +55,6 @@
</div>
</div>
<div class="card col-md-2">
<div class="card-body">
<img class="img-fluid" src="<?php echo "uploads/settings/$company_id/$company_logo"; ?>">
</div>
</div>
<div class="form-group">
<input type="file" class="form-control-file" name="file">
</div>
</div>
<div class="tab-pane fade" id="pills-address<?php echo $company_id; ?>">
<div class="form-group">
<label>Address</label>
<div class="input-group">
@@ -88,7 +86,7 @@
</div>
<div class="form-group">
<label>Zip / Postal Code</label>
<label>Postal Code</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fab fa-fw fa-usps"></i></span>
@@ -101,7 +99,7 @@
<label>Country</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-flag"></i></span>
<span class="input-group-text"><i class="fa fa-fw fa-globe-americas"></i></span>
</div>
<select class="form-control select2" name="country">
<option value="">- Country -</option>
@@ -112,10 +110,6 @@
</div>
</div>
</div>
<div class="tab-pane fade" id="pills-contact<?php echo $company_id; ?>">
<div class="form-group">
<label>Phone</label>
<div class="input-group">
@@ -146,50 +140,16 @@
</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>
</div>
<div class="tab-pane fade" id="pills-locale<?php echo $company_id; ?>">
<div class="form-group">
<label>Locale <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-flag"></i></span>
</div>
<select class="form-control select2" name="locale" required>
<option value="">- Select a Locale -</option>
<?php foreach($locales_array as $locale_code => $locale_name) { ?>
<option <?php if ($company_locale == $locale_code) { echo "selected"; } ?> value="<?php echo $locale_code; ?>"><?php echo "$locale_code - $locale_name"; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Currency <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-bill"></i></span>
</div>
<select class="form-control select2" name="currency_code" required>
<option value="">- Currency -</option>
<?php foreach($currencies_array as $currency_code => $currency_name) { ?>
<option <?php if ($company_currency == $currency_code) { echo "selected"; } ?> value="<?php echo $currency_code; ?>"><?php echo "$currency_code - $currency_name"; ?></option>
<?php } ?>
</select>
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="edit_company" 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>
</div>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -0,0 +1,124 @@
<?php
// Default Column Sortby Filter
$sort = "custom_field_label";
$order = "ASC";
require_once "includes/inc_all_admin.php";
if (isset($_GET['table'])) {
$table = sanitizeInput($_GET['table']);
} else {
$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
WHERE custom_field_label LIKE '%$q%'
AND custom_field_table = '$table'
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-th-list mr-2"></i><?php echo nullable_htmlentities($table); ?> Fields</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#createCustomFieldModal"><i class="fas fa-plus mr-2"></i>Create</button>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<input type="hidden" name="table" value="<?php echo nullable_htmlentities($table); ?>">
<div class="row">
<div class="col-sm-4 mb-2">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="btn-group float-right">
<a href="?table=client_assets" class="btn <?php if ($table == 'client_assets') { echo 'btn-primary'; } else { echo 'btn-default'; } ?>">Assets</a>
<a href="?table=clients" class="btn <?php if ($table == 'clients') { echo 'btn-primary'; } else { echo 'btn-default'; } ?>">Clients</a>
</div>
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=custom_field_label&order=<?php echo $disp; ?>">Label</a></th>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=custom_field_type&order=<?php echo $disp; ?>">Type</a></th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$custom_field_id = intval($row['custom_field_id']);
$custom_field_label = nullable_htmlentities($row['custom_field_label']);
$custom_field_type = nullable_htmlentities($row['custom_field_type']);
$custom_field_location = intval($row['custom_field_location']);
$custom_field_order = intval($row['custom_field_order']);
?>
<tr>
<td><a class="text-dark" href="#" data-toggle="modal" data-target="#editCustomFieldModal<?php echo $custom_field_id; ?>"><?php echo $custom_field_label; ?></a></td>
<td><?php echo $custom_field_type; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editCustomFieldModal<?php echo $custom_field_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_custom_field=<?php echo $custom_field_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php
//$colors_diff = array_diff($colors_array,$colors_used_array);
include "custom_field_edit_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "custom_field_create_modal.php";
require_once "includes/footer.php";

252
admin_settings_default.php Normal file
View File

@@ -0,0 +1,252 @@
<?php
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-cogs mr-2"></i>Defaults</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'] ?>">
<div class="form-group">
<label>Start Page</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-home"></i></span>
</div>
<select class="form-control select2" name="start_page" data-tags="true" required>
<?php if (!in_array($config_start_page, array_keys($start_page_select_array))) { ?>
<option selected> <?php echo nullable_htmlentities($config_start_page); ?></option>
<?php } ?>
<?php foreach ($start_page_select_array as $start_page_value => $start_page_name) { ?>
<option <?php if ($start_page_value == $config_start_page) { echo "selected"; } ?>
value="<?php echo nullable_htmlentities($start_page_value); ?>">
<?php echo nullable_htmlentities($start_page_name); ?>
</option>
<?php }?>
</select>
</div>
</div>
<div class="form-group">
<label>Calendar</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>
<select class="form-control select2" name="calendar">
<option value="0">- None -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM calendars ORDER BY calendar_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$calendar_id = intval($row['calendar_id']);
$calendar_name = nullable_htmlentities($row['calendar_name']); ?>
<option <?php if ($config_default_calendar == $calendar_id) {
echo "selected";
} ?> value="<?php echo $calendar_id; ?>"><?php echo $calendar_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Transfer From Account</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-exchange-alt"></i></span>
</div>
<select class="form-control select2" name="transfer_from_account">
<option value="0">- None -</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']); ?>
<option <?php if ($config_default_transfer_from_account == $account_id) {
echo "selected";
} ?> value="<?php echo $account_id; ?>"><?php echo $account_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Transfer To Account</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-exchange-alt"></i></span>
</div>
<select class="form-control select2" name="transfer_to_account">
<option value="0">- None -</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']); ?>
<option <?php if ($config_default_transfer_to_account == $account_id) {
echo "selected";
} ?> value="<?php echo $account_id; ?>"><?php echo $account_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Payment Account</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-credit-card"></i></span>
</div>
<select class="form-control select2" name="payment_account">
<option value="0">- None -</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']); ?>
<option <?php if ($config_default_payment_account == $account_id) {
echo "selected";
} ?> value="<?php echo $account_id; ?>"><?php echo $account_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Expense Account</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>
<select class="form-control select2" name="expense_account">
<option value="0">- None -</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']); ?>
<option <?php if ($config_default_expense_account == $account_id) {
echo "selected";
} ?> value="<?php echo $account_id; ?>"><?php echo $account_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Payment Method</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-credit-card"></i></span>
</div>
<select class="form-control select2" name="payment_method">
<option value="">- None -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Payment Method' ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$payment_method = nullable_htmlentities($row['category_name']); ?>
<option <?php if ($config_default_payment_method == $payment_method) {
echo "selected";
} ?>><?php echo $payment_method; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Expense Payment Method</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-credit-card"></i></span>
</div>
<select class="form-control select2" name="expense_payment_method">
<option value="">- None -</option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM categories WHERE category_type = 'Payment Method' ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$payment_method = nullable_htmlentities($row['category_name']); ?>
<option <?php if ($config_default_expense_payment_method == $payment_method) {
echo "selected";
} ?>><?php echo $payment_method; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Net Terms</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
</div>
<select class="form-control select2" name="net_terms">
<?php foreach ($net_terms_array as $net_term_value => $net_term_name) { ?>
<option <?php if ($config_default_net_terms == $net_term_value) {
echo "selected";
} ?> value="<?php echo $net_term_value; ?>"><?php echo $net_term_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Client Hourly Rate</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="hourly_rate" value="<?php echo number_format($config_default_hourly_rate, 2, '.', ''); ?>" placeholder="0.00" required>
</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>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -0,0 +1,43 @@
<?php
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>
</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>MS Entra OAuth App (Client) ID</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<input type="text" class="form-control" name="azure_client_id" placeholder="e721e3b6-01d6-50e8-7f22-c84d951a52e7" value="<?php echo nullable_htmlentities($config_azure_client_id); ?>">
</div>
</div>
<div class="form-group">
<label>MS Entra OAuth Secret</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="password" class="form-control" name="azure_client_secret" placeholder="Auto-generated from App Registration" value="<?php echo nullable_htmlentities($config_azure_client_secret); ?>" autocomplete="new-password">
</div>
</div>
<hr>
<button type="submit" name="edit_integrations_settings" 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

@@ -1,14 +1,16 @@
<?php
require_once("inc_all_settings.php"); ?>
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-file mr-2"></i>Invoice Settings</h3>
<h3 class="card-title"><i class="fas fa-fw fa-file-invoice mr-2"></i>Invoice Settings</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'] ?>">
<legend>Invoice</legend>
<h4>Invoice</h4>
<div class="form-group">
<label>Invoice Prefix</label>
@@ -16,7 +18,7 @@ require_once("inc_all_settings.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_invoice_prefix" placeholder="Invoice Prefix" value="<?php echo htmlentities($config_invoice_prefix); ?>" required>
<input type="text" class="form-control" name="config_invoice_prefix" placeholder="Invoice Prefix" value="<?php echo nullable_htmlentities($config_invoice_prefix); ?>" required>
</div>
</div>
@@ -32,32 +34,42 @@ require_once("inc_all_settings.php"); ?>
<div class="form-group">
<label>Invoice Footer</label>
<textarea class="form-control" rows="4" name="config_invoice_footer"><?php echo htmlentities($config_invoice_footer); ?></textarea>
<textarea class="form-control" rows="4" name="config_invoice_footer"><?php echo nullable_htmlentities($config_invoice_footer); ?></textarea>
</div>
<div class="form-group">
<label>From Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="config_invoice_from_email" placeholder="From Email" value="<?php echo htmlentities($config_invoice_from_email); ?>">
<h5>Invoice Late Fees</h5>
<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>
</div>
</div>
<div class="form-group">
<label>From Name</label>
<label>Late Fee %</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
<span class="input-group-text"><i class="fa fa-fw fa-percent"></i></span>
</div>
<input type="text" class="form-control" name="config_invoice_from_name" placeholder="From Name" value="<?php echo htmlentities($config_invoice_from_name); ?>">
<input type="number" class="form-control" min="0" max="100" step="0.01" name="config_invoice_late_fee_percent" value="<?php echo $config_invoice_late_fee_percent; ?>">
</div>
<small class="text-secondary">We recommend updating the invoice footer to include policies on your late charges. This will be applied every 30 days after the invoice Due Date.</small>
</div>
<div class="form-group">
<label>Email address to notify when invoices are paid online <small class="text-secondary">(Ideally a distribution list/shared mailbox)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-bell"></i></span>
</div>
<input type="email" class="form-control" name="config_invoice_paid_notification_email" placeholder="Address to notify for paid invoices, leave blank for none" value="<?php echo nullable_htmlentities($config_invoice_paid_notification_email); ?>">
</div>
</div>
<hr>
<legend>Recurring Invoice</legend>
<h4>Recurring Invoice</h4>
<div class="form-group">
<label>Recurring Prefix</label>
@@ -65,7 +77,7 @@ require_once("inc_all_settings.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 htmlentities($config_recurring_prefix); ?>" required>
<input type="text" class="form-control" name="config_recurring_prefix" placeholder="Recurring Prefix" value="<?php echo nullable_htmlentities($config_recurring_prefix); ?>" required>
</div>
</div>
@@ -90,4 +102,5 @@ require_once("inc_all_settings.php"); ?>
</div>
<?php
require_once("footer.php");
require_once "includes/footer.php";

View File

@@ -0,0 +1,79 @@
<?php
require_once "includes/inc_all_admin.php";
$sql = mysqli_query($mysqli,"SELECT * FROM companies, settings WHERE companies.company_id = settings.company_id AND companies.company_id = 1");
$row = mysqli_fetch_array($sql);
$company_locale = nullable_htmlentities($row['company_locale']);
$company_currency = nullable_htmlentities($row['company_currency']);
// Get a list of all available timezones
$timezones = DateTimeZone::listIdentifiers();
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-globe mr-2"></i>Localization</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'] ?>">
<div class="form-group">
<label>Language <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-language"></i></span>
</div>
<select class="form-control select2" name="locale" required>
<option value="">- Select a Locale -</option>
<?php foreach($locales_array as $locale_code => $locale_name) { ?>
<option <?php if ($company_locale == $locale_code) { echo "selected"; } ?> value="<?php echo $locale_code; ?>"><?php echo $locale_name; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Currency <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-bill"></i></span>
</div>
<select class="form-control select2" name="currency_code" required>
<option value="">- Currency -</option>
<?php foreach($currencies_array as $currency_code => $currency_name) { ?>
<option <?php if ($company_currency == $currency_code) { echo "selected"; } ?> value="<?php echo $currency_code; ?>"><?php echo "$currency_code - $currency_name"; ?></option>
<?php } ?>
</select>
</div>
</div>
<div class="form-group">
<label>Timezone <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-business-time"></i></span>
</div>
<select class="form-control select2" name="timezone" required>
<option value="">- Select a Timezone -</option>
<?php foreach ($timezones as $tz) { ?>
<option <?php if ($config_timezone == $tz) { echo "selected"; } ?> value="<?php echo $tz; ?>"><?php echo $tz; ?></option>
<?php } ?>
</select>
</div>
</div>
<hr>
<button type="submit" name="edit_localization" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

331
admin_settings_mail.php Normal file
View File

@@ -0,0 +1,331 @@
<?php
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-envelope mr-2"></i>SMTP Mail Settings <small>(For Sending Email)</small></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'] ?>">
<div class="form-group">
<label>SMTP Host</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-server"></i></span>
</div>
<input type="text" class="form-control" name="config_smtp_host" placeholder="Mail Server Address" value="<?php echo nullable_htmlentities($config_smtp_host); ?>" required>
</div>
</div>
<div class="form-group">
<label>SMTP Port</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-plug"></i></span>
</div>
<input type="number" min="0" class="form-control" name="config_smtp_port" placeholder="Mail Server Port Number" value="<?php echo intval($config_smtp_port); ?>" required>
</div>
</div>
<div class="form-group">
<label>Encryption</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<select class="form-control" name="config_smtp_encryption">
<option value=''>None</option>
<option <?php if ($config_smtp_encryption == 'tls') { echo "selected"; } ?> value="tls">TLS</option>
<option <?php if ($config_smtp_encryption == 'ssl') { echo "selected"; } ?> value="ssl">SSL</option>
</select>
</div>
</div>
<div class="form-group">
<label>SMTP Username</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<input type="text" class="form-control" name="config_smtp_username" placeholder="Username (Leave blank if no auth is required)" value="<?php echo nullable_htmlentities($config_smtp_username); ?>">
</div>
</div>
<div class="form-group">
<label>SMTP Password</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="password" class="form-control" data-toggle="password" name="config_smtp_password" placeholder="Password (Leave blank if no auth is required)" value="<?php echo nullable_htmlentities($config_smtp_password); ?>" autocomplete="new-password">
<div class="input-group-append">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
</div>
</div>
<hr>
<button type="submit" name="edit_mail_smtp_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-envelope mr-2"></i>IMAP Mail Settings <small>(For Monitoring Ticket Inbox)</small></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'] ?>">
<div class="form-group">
<label>IMAP Host</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-server"></i></span>
</div>
<input type="text" class="form-control" name="config_imap_host" placeholder="Incoming Mail Server Address (for email to ticket parsing)" value="<?php echo nullable_htmlentities($config_imap_host); ?>">
</div>
</div>
<div class="form-group">
<label>IMAP Port</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-plug"></i></span>
</div>
<input type="number" min="0" class="form-control" name="config_imap_port" placeholder="Incoming Mail Server Port Number (993)" value="<?php echo intval($config_imap_port); ?>">
</div>
</div>
<div class="form-group">
<label>IMAP Encryption</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-lock"></i></span>
</div>
<select class="form-control" name="config_imap_encryption">
<option value=''>None</option>
<option <?php if ($config_imap_encryption == 'tls') { echo "selected"; } ?> value="tls">TLS</option>
<option <?php if ($config_imap_encryption == 'ssl') { echo "selected"; } ?> value="ssl">SSL</option>
</select>
</div>
</div>
<div class='form-group'>
<label>IMAP Username</label>
<div class='input-group'>
<div class='input-group-prepend'>
<span class='input-group-text'><i class='fa fa-fw fa-user'></i></span>
</div>
<input type='text' class='form-control' name='config_imap_username' placeholder='Username' value="<?php
echo nullable_htmlentities($config_imap_username); ?>" required>
</div>
</div>
<div class='form-group'>
<label>IMAP Password</label>
<div class='input-group'>
<div class='input-group-prepend'>
<span class='input-group-text'><i class='fa fa-fw fa-key'></i></span>
</div>
<input type='password' class='form-control' data-toggle='password' name='config_imap_password' placeholder='Password' value="<?php
echo nullable_htmlentities($config_imap_password); ?>" autocomplete='new-password' required>
<div class='input-group-append'>
<span class='input-group-text'><i class='fa fa-fw fa-eye'></i></span>
</div>
</div>
</div>
<hr>
<button type="submit" name="edit_mail_imap_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-paper-plane mr-2"></i>Mail From Configuration</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'] ?>">
<p>Each of the "From Email" Addresses need to be able to send email on behalf of the SMTP user configured above
<h5>System Default</h5>
<p class="text-secondary">(used for system tasks such as sending share links)</p>
<div class="form-group">
<label>From Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="config_mail_from_email" placeholder="Email Address (ex noreply@yourcompany.com)" value="<?php echo nullable_htmlentities($config_mail_from_email); ?>">
</div>
</div>
<div class="form-group">
<label>From Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="config_mail_from_name" placeholder="Name (ex YourCompany)" value="<?php echo nullable_htmlentities($config_mail_from_name); ?>">
</div>
</div>
<h5>Invoices</h5>
<p class="text-secondary">(used for when invoice emails are sent)</p>
<div class="form-group">
<label>From Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="config_invoice_from_email" placeholder="Email (ex billing@yourcompany.com)" value="<?php echo nullable_htmlentities($config_invoice_from_email); ?>">
</div>
</div>
<div class="form-group">
<label>From Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="config_invoice_from_name" placeholder="Name (ex CompanyName Billing)" value="<?php echo nullable_htmlentities($config_invoice_from_name); ?>">
</div>
</div>
<h5>Quotes</h5>
<p class="text-secondary">(used for when quote emails are sent)</p>
<div class="form-group">
<label>From Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="config_quote_from_email" placeholder="Email (ex sales@yourcompany.com)" value="<?php echo nullable_htmlentities($config_quote_from_email); ?>">
</div>
</div>
<div class="form-group">
<label>From Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="config_quote_from_name" placeholder="Name (ex YourCompany Sales)" value="<?php echo nullable_htmlentities($config_quote_from_name); ?>">
</div>
</div>
<h5>Tickets</h5>
<p class="text-secondary">(used for when tickets are created and emailed to a client)</p>
<div class="form-group">
<label>From Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="config_ticket_from_email" placeholder="Email (ex support@yourcompany.com)" value="<?php echo nullable_htmlentities($config_ticket_from_email); ?>">
</div>
</div>
<div class="form-group">
<label>From Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="config_ticket_from_name" placeholder="Name (ex YourCompany Support)" value="<?php echo nullable_htmlentities($config_ticket_from_name); ?>">
</div>
</div>
<hr>
<button type="submit" name="edit_mail_from_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php if (!empty($config_smtp_host) && !empty($config_smtp_port) && !empty($config_mail_from_email) && !empty($config_mail_from_name)) { ?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-paper-plane mr-2"></i>Test Email Sending</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'] ?>">
<div class="input-group">
<select class="form-control select2" name="test_email" required>
<option value="">- Select an Email Address to send from -</option>
<?php
if ($config_mail_from_email) {
?>
<option value="1"><?php echo nullable_htmlentities($config_mail_from_name); ?> (<?php echo nullable_htmlentities($config_mail_from_email); ?>)</option>
<?php } ?>
<?php
if ($config_invoice_from_email) {
?>
<option value="2"><?php echo nullable_htmlentities($config_invoice_from_name); ?> (<?php echo nullable_htmlentities($config_invoice_from_email); ?>)</option>
<?php } ?>
<?php
if ($config_quote_from_email) {
?>
<option value="3"><?php echo nullable_htmlentities($config_quote_from_name); ?> (<?php echo nullable_htmlentities($config_quote_from_email); ?>)</option>
<?php } ?>
<?php
if ($config_ticket_from_email) {
?>
<option value="4"><?php echo nullable_htmlentities($config_ticket_from_name); ?> (<?php echo nullable_htmlentities($config_ticket_from_email); ?>)</option>
<?php } ?>
</select>
<input type="email" class="form-control " name="email_to" placeholder="Email address to send to">
<div class="input-group-append">
<button type="submit" name="test_email_smtp" class="btn btn-success"><i class="fas fa-fw fa-paper-plane mr-2"></i>Send</button>
</div>
</div>
</form>
</div>
</div>
<?php } ?>
<?php if (!empty($config_imap_username) && !empty($config_imap_password) && !empty($config_imap_host) && !empty($config_imap_port)) { ?>
<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>Test IMAP Connection</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'] ?>">
<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>
</div>
</form>
</div>
</div>
<?php } ?>
<?php require_once "includes/footer.php";

82
admin_settings_module.php Normal file
View File

@@ -0,0 +1,82 @@
<?php
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-cube mr-2"></i>Modules</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'] ?>">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_module_enable_itdoc" <?php if ($config_module_enable_itdoc == 1) { echo "checked"; } ?> value="1" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Show IT Documentation</label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_module_enable_ticketing" <?php if ($config_module_enable_ticketing == 1) { echo "checked"; } ?> value="1" id="customSwitch2">
<label class="custom-control-label" for="customSwitch2">Show Ticketing</label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_module_enable_accounting" <?php if ($config_module_enable_accounting == 1) { echo "checked"; } ?> value="1" id="customSwitch3">
<label class="custom-control-label" for="customSwitch3">Show Invoicing / Accounting</label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_client_portal_enable" <?php if ($config_client_portal_enable == 1) { echo "checked"; } ?> value="1" id="customSwitch4">
<label class="custom-control-label" for="customSwitch4">Enable Client Portal</label>
</div>
</div>
<hr>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" disabled class="custom-control-input" name="config_whitelabel_enabled" <?php if ($config_whitelabel_enabled == 1) { echo "checked"; } ?> value="1" id="customSwitch5">
<label class="custom-control-label" for="customSwitch5">White-label <small class="text-secondary">(Hides 'Powered by ITFlow' banner)</small></label>
</div>
</div>
<div class="form-group">
<label>White-label key</label>
<textarea class="form-control" name="config_whitelabel_key" rows="2" placeholder="Enter a key to enable white-labelling the client portal"><?php echo nullable_htmlentities($config_whitelabel_key); ?></textarea>
</div>
<?php if ($config_whitelabel_enabled == 1 && validateWhitelabelKey($config_whitelabel_key)) {
$key_info = validateWhitelabelKey($config_whitelabel_key);
$key_desc = $key_info["description"];
$key_org = $key_info["organisation"];
$key_expires = $key_info["expires"];
?>
<div class="form-group">
<p>White-labelling is active - thank you for your support! :)</p>
<ul>
<li>Key: <?php echo $key_desc ?></li>
<li>Org: <?php echo $key_org ?></li>
<li>Expires: <?php echo $key_expires; if ($key_expires < date('Y-m-d H:i:s')) { echo " (expiring) "; } ?></li>
</ul>
</div>
<?php } ?>
<hr>
<button type="submit" name="edit_module_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

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

@@ -0,0 +1,154 @@
<?php
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-credit-card mr-2"></i>Online Payment</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'] ?>">
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_stripe_enable" <?php if ($config_stripe_enable == 1) { echo "checked"; } ?> value="1" id="enableStripeSwitch">
<label class="custom-control-label" for="enableStripeSwitch">Enable Stripe</label>
</div>
</div>
<div class="<?php if ($config_stripe_enable == 0) { echo "d-none"; } ?>">
<div class="form-group">
<label>Publishable key <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-eye"></i></span>
</div>
<input type="text" class="form-control" name="config_stripe_publishable" placeholder="Stripe Publishable API Key (pk_...)" value="<?php echo nullable_htmlentities($config_stripe_publishable); ?>">
</div>
</div>
<div class="form-group">
<label>Secret key <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="config_stripe_secret" placeholder="Stripe Secret API Key (sk_...)" value="<?php echo nullable_htmlentities($config_stripe_secret); ?>">
</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="fas fa-fw fa-piggy-bank"></i></span>
</div>
<select class="form-control select2" name="config_stripe_account">
<option value="">- Account -</option>
<?php
$sql_accounts = mysqli_query($mysqli, "SELECT * FROM accounts WHERE account_archived_at IS NULL ORDER BY account_name ASC");
while ($row = mysqli_fetch_array($sql_accounts)) {
$account_id = intval($row['account_id']);
$account_name = nullable_htmlentities($row['account_name']);
?>
<option value="<?php echo $account_id ?>" <?php if ($account_id == $config_stripe_account) { echo "selected"; } ?>><?php echo $account_name ?></option>
<?php
}
?>
</select>
</div>
</div>
<hr>
<div class="form-group">
<label>Expense Vendor</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-building"></i></span>
</div>
<select class="form-control select2" name="config_stripe_expense_vendor">
<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");
while ($row = mysqli_fetch_array($sql_select)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
?>
<option <?php if ($config_stripe_expense_vendor == $vendor_id) { ?> selected <?php } ?> value="<?php echo $vendor_id; ?>"><?php echo $vendor_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Expense Category</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-list"></i></span>
</div>
<select class="form-control select2" name="config_stripe_expense_category">
<option value="">- Do not expense Stripe fees -</option>
<?php
$sql_select = mysqli_query($mysqli, "SELECT category_id, category_name FROM categories WHERE category_type = 'Expense' AND category_archived_at IS NULL ORDER BY category_name ASC");
while ($row = mysqli_fetch_array($sql_select)) {
$category_id = intval($row['category_id']);
$category_name = nullable_htmlentities($row['category_name']);
?>
<option <?php if ($config_stripe_expense_category == $category_id) { ?> selected <?php } ?> value="<?php echo $category_id; ?>"><?php echo $category_name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="form-group">
<label>Percentage Fee to expense</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-percent"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="config_stripe_percentage_fee" placeholder="Enter Percentage" value="<?php echo $config_stripe_percentage_fee * 100; ?>">
</div>
<small class="form-text text-muted">See <a href="https://stripe.com/pricing" target="_blank">here <i class="fas fa-fw fa-external-link-alt"></i></a> for the latest Stripe Fees.</small>
</div>
<div class="form-group">
<label>Flat Fee to expense</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-shopping-cart"></i></span>
</div>
<input type="text" class="form-control" inputmode="numeric" pattern="[0-9]*\.?[0-9]{0,2}" name="config_stripe_flat_fee" placeholder="0.030" value="<?php echo number_format($config_stripe_flat_fee, 2, '.', ''); ?>">
</div>
<small class="form-text text-muted">See <a href="https://stripe.com/pricing" target="_blank">here <i class="fas fa-fw fa-external-link-alt"></i></a> for the latest Stripe Fees.</small>
</div>
</div>
<div class="alert alert-secondary">Currently, we only integrate with Stripe. Please see <a href="https://forum.itflow.org/d/439-payment-integrations-megathread" target="_blank">this forum post</a>.</div>
</div>
<hr>
<button type="submit" name="edit_online_payment_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -0,0 +1,70 @@
<?php
require_once "includes/inc_all_admin.php";
$stripe_clients_sql = mysqli_query($mysqli, "SELECT * FROM client_stripe LEFT JOIN clients ON client_stripe.client_id = clients.client_id");
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-credit-card mr-2"></i>Online Payment - Client info</h3>
</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']);
?>
<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>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -0,0 +1,44 @@
<?php
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-project-diagram mr-2"></i>Project Settings</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>Project</h4>
<div class="form-group">
<label>Project Prefix</label>
<div class="input-group">
<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_project_prefix" placeholder="Project Prefix" value="<?php echo nullable_htmlentities($config_project_prefix); ?>" required>
</div>
</div>
<div class="form-group">
<label>Next Number</label>
<div class="input-group">
<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_project_next_number" placeholder="Next Project Number" value="<?php echo intval($config_project_next_number); ?>" required>
</div>
</div>
<hr>
<button type="submit" name="edit_project_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -1,12 +1,14 @@
<?php
require_once("inc_all_settings.php"); ?>
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-file mr-2"></i>Quote Settings</h3>
<h3 class="card-title"><i class="fas fa-fw fa-comment-dollar mr-2"></i>Quote Settings</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'] ?>">
<div class="form-group">
<label>Quote Prefix</label>
@@ -14,7 +16,7 @@ require_once("inc_all_settings.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_quote_prefix" placeholder="Quote Prefix" value="<?php echo htmlentities($config_quote_prefix); ?>" required>
<input type="text" class="form-control" name="config_quote_prefix" placeholder="Quote Prefix" value="<?php echo nullable_htmlentities($config_quote_prefix); ?>" required>
</div>
</div>
@@ -30,26 +32,16 @@ require_once("inc_all_settings.php"); ?>
<div class="form-group">
<label>Quote Footer</label>
<textarea class="form-control" rows="4" name="config_quote_footer"><?php echo htmlentities($config_quote_footer); ?></textarea>
<textarea class="form-control" rows="4" name="config_quote_footer"><?php echo nullable_htmlentities($config_quote_footer); ?></textarea>
</div>
<div class="form-group">
<label>From Email</label>
<label>Email address to notify when quotes are accepted/declined <small class="text-secondary">(Ideally a distribution list/shared mailbox)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
<span class="input-group-text"><i class="fa fa-fw fa-bell"></i></span>
</div>
<input type="email" class="form-control" name="config_quote_from_email" placeholder="From Email" value="<?php echo htmlentities($config_quote_from_email); ?>">
</div>
</div>
<div class="form-group">
<label>From Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="config_quote_from_name" placeholder="Name" value="<?php echo htmlentities($config_quote_from_name); ?>">
<input type="email" class="form-control" name="config_quote_notification_email" placeholder="Address to notify for quote accept/declines, leave blank for none" value="<?php echo nullable_htmlentities($config_quote_notification_email); ?>">
</div>
</div>
@@ -62,4 +54,5 @@ require_once("inc_all_settings.php"); ?>
</div>
<?php
require_once("footer.php");
require_once "includes/footer.php";

View File

@@ -0,0 +1,66 @@
<?php
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-shield-alt mr-2"></i>Security</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'] ?>">
<div class="form-group">
<label>Login Message</label>
<textarea class="form-control" name="config_login_message" rows="5" placeholder="Enter a message to be displayed on the login screen"><?php echo nullable_htmlentities($config_login_message); ?></textarea>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_login_key_required" <?php if ($config_login_key_required == 1) { echo "checked"; } ?> value="1" id="customSwitch1">
<label class="custom-control-label" for="customSwitch1">Require a login key to access the technician login page?</label>
</div>
</div>
<div class="form-group">
<label>Login key secret value <small class="text-secondary">(This must be provided in the URL as /login.php?key=<?php echo nullable_htmlentities($config_login_key_secret)?>)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" name="config_login_key_secret" pattern="\w{3,99}" placeholder="Something really easy for techs to remember: e.g. MYSECRET" value="<?php echo nullable_htmlentities($config_login_key_secret); ?>">
</div>
</div>
<div class="form-group">
<label>2FA Remember Me Expire <small class="text-secondary">(The amount of days before a device 2FA remember me token will expire)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
</div>
<input type="number" class="form-control" name="config_login_remember_me_expire" placeholder="Enter Days to Expire" value="<?php echo intval($config_login_remember_me_expire); ?>">
</div>
</div>
<div class="form-group">
<label>Log retention <small class="text-secondary">(The amount of days before app/audit/auth logs are deleted during nightly cron)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
</div>
<input type="number" class="form-control" name="config_log_retention" placeholder="Enter days to retain" value="<?php echo intval($config_log_retention); ?>">
</div>
</div>
<hr>
<button type="submit" name="edit_security_settings" class="btn btn-primary text-bold"><i class="fas fa-check mr-2"></i>Save</button>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -1,18 +1,21 @@
<?php
require_once("inc_all_settings.php"); ?>
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-broadcast-tower mr-2"></i>Telemetry</h3>
<h3 class="card-title"><i class="fas fa-fw fa-satellite-dish mr-2"></i>Telemetry</h3>
</div>
<div class="card-body">
<p class="text-center">Installation ID: <strong><?php echo $installation_id; ?></strong></p>
<form action="post.php" method="post" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<div class="form-group">
<label>Telemery</label>
<label>Telemetry</label>
<p><i>If you can't measure it, you can't improve it. Please consider turning on telemetry data to provide valuable insights on how you're using ITFlow - so we can improve it for everyone. </i></p>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-broadcast-tower"></i></span>
@@ -23,18 +26,11 @@ require_once("inc_all_settings.php"); ?>
<option <?php if ($config_telemetry == "2") { echo "selected"; } ?> value = "2">Detailed</option>
</select>
</div>
</div>
<div class="form-group">
<label>Comments</label>
<textarea class="form-control" rows="4" name="comments" placeholder="Any Comments to send before hitting Send Telemetry Data?"></textarea>
<small class="form-text">We respect your privacy. <a href="https://docs.itflow.org/telemetry" target="_blank">Click here <i class="fas fa-external-link-alt"></i></a> for additional details regarding the information we gather. </small>
</div>
<hr>
<?php if ($config_telemetry > 0) { ?>
<button type="submit" name="send_telemetry_data" class="btn btn-success"><i class="fas fa-fw fa-paper-plane mr-2"></i>Send Telemetry Data</button>
<?php } ?>
<button type="submit" name="edit_telemetry_settings" class="btn btn-primary text-bold float-right"><i class="fas fa-check mr-2"></i>Save</button>
</form>
@@ -42,4 +38,5 @@ require_once("inc_all_settings.php"); ?>
</div>
<?php
require_once("footer.php");
require_once "includes/footer.php";

67
admin_settings_theme.php Normal file
View File

@@ -0,0 +1,67 @@
<?php
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-paint-brush mr-2"></i>Theme</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'] ?>">
<label>Select a Theme</label>
<div class="form-row">
<?php
foreach ($theme_colors_array as $theme_color) {
?>
<div class="col-3 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"; } ?>>
<label for="customRadio<?php echo $theme_color; ?>" class="custom-control-label">
<i class="fa fa-fw fa-6x fa-circle text-<?php echo $theme_color; ?>"></i>
<br>
<?php echo $theme_color; ?>
</label>
</div>
</div>
</div>
<?php } ?>
</div>
</form>
</div>
</div>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-image mr-2"></i>Favicon</h3>
</div>
<div class="card-body">
<form action="post.php" method="post" enctype="multipart/form-data" autocomplete="off">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<img class="mb-3" src="<?php if(file_exists("uploads/favicon.ico")) { echo "uploads/favicon.ico"; } else { echo "favicon.ico"; } ?>">
<div class="form-group">
<input type="file" class="form-control-file" name="file" accept=".ico">
</div>
<hr>
<button type="submit" name="edit_favicon_settings" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Upload Icon</button>
</form>
</div>
</div>
<?php
require_once "includes/footer.php";

View File

@@ -1,5 +1,6 @@
<?php
require_once("inc_all_settings.php"); ?>
require_once "includes/inc_all_admin.php";
?>
<div class="card card-dark">
<div class="card-header py-3">
@@ -7,6 +8,7 @@ require_once("inc_all_settings.php"); ?>
</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'] ?>">
<div class="form-group">
<label>Ticket Prefix</label>
@@ -14,7 +16,7 @@ require_once("inc_all_settings.php"); ?>
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-life-ring"></i></span>
</div>
<input type="text" class="form-control" name="config_ticket_prefix" placeholder="Ticket Prefix" value="<?php echo htmlentities($config_ticket_prefix); ?>">
<input type="text" class="form-control" name="config_ticket_prefix" placeholder="Ticket Prefix" value="<?php echo nullable_htmlentities($config_ticket_prefix); ?>" pattern="^[A-Za-z-]+$" title="Only letters and hyphens are allowed" required>
</div>
</div>
@@ -24,41 +26,50 @@ require_once("inc_all_settings.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_ticket_next_number" placeholder="Next Ticket Number" value="<?php echo intval($config_ticket_next_number); ?>" required>
</div>
</div>
<div class="form-group">
<label>From Email</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-envelope"></i></span>
</div>
<input type="email" class="form-control" name="config_ticket_from_email" placeholder="From Email" value="<?php echo htmlentities($config_ticket_from_email); ?>">
</div>
</div>
<div class="form-group">
<label>From Name</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-tag"></i></span>
</div>
<input type="text" class="form-control" name="config_ticket_from_name" placeholder="Name" value="<?php echo htmlentities($config_ticket_from_name); ?>">
<input type="number" min="<?php echo intval($config_ticket_next_number); ?>" class="form-control" name="config_ticket_next_number" placeholder="Next Ticket Number" value="<?php echo intval($config_ticket_next_number); ?>" required>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_email_parse" <?php if($config_ticket_email_parse == 1){ echo "checked"; } ?> value="1" id="emailToTicketParseSwitch">
<label class="custom-control-label" for="emailToTicketParseSwitch">Email-to-ticket parsing (Beta) <small>(cron_ticket_email_parser.php must also be added to cron and run every few mins)</small></label>
<label class="custom-control-label" for="emailToTicketParseSwitch">Email-to-ticket parsing <small class="text-secondary">(cron_ticket_email_parser.php must also be added to cron and run every few mins)</small></label>
</div>
</div>
<div class="form-group">
<div class="custom-control custom-switch">
<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">Send clients general notification emails <small>(Should clients receive automatic emails when tickets are raised/closed?)</small></label>
<input type="checkbox" class="custom-control-input" name="config_ticket_email_parse_unknown_senders" <?php if($config_ticket_email_parse_unknown_senders == 1){ echo "checked"; } ?> value="1" id="emailToTicketAnonParseSwitch" <?php if($config_ticket_email_parse == 0){ echo "disabled"; } ?>>
<label class="custom-control-label" for="emailToTicketAnonParseSwitch">Create tickets for emails from unknown senders/domains <small class="text-secondary">(Enable to ensure all emails automatically create tickets)</small></label>
</div>
</div>
<?php if ($config_module_enable_accounting) { ?>
<div class="form-group">
<div class="custom-control custom-switch">
<input type="checkbox" class="custom-control-input" name="config_ticket_default_billable" <?php if ($config_ticket_default_billable == 1) { echo "checked"; } ?> value="1" id="ticketBillableSwitch">
<label class="custom-control-label" for="ticketBillableSwitch">Default to Billable <small class="text-secondary">(This will check the billable box on all new tickets)</small></label>
</div>
</div>
<?php } ?>
<div class="form-group">
<label>Number of hours to auto close resolved tickets</label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-clock"></i></span>
</div>
<input type="number" min="72" class="form-control" name="config_ticket_autoclose_hours" placeholder="Delay in hours before a resolved ticket is fully closed" value="<?php echo intval($config_ticket_autoclose_hours); ?>">
</div>
</div>
<div class="form-group">
<label>Email address to notify when new tickets are raised <small class="text-secondary">(Ideally a distribution list/shared mailbox)</small></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-bell"></i></span>
</div>
<input type="email" class="form-control" name="config_ticket_new_ticket_notification_email" placeholder="Address to notify for new tickets, leave blank for none" value="<?php echo nullable_htmlentities($config_ticket_new_ticket_notification_email); ?>">
</div>
</div>
@@ -71,4 +82,5 @@ require_once("inc_all_settings.php"); ?>
</div>
<?php
require_once("footer.php");
require_once "includes/footer.php";

View File

@@ -1,21 +1,21 @@
<?php
// Default Column Sortby Filter
$sb = "software_name";
$o = "ASC";
$sort = "software_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
require_once("inc_all_settings.php");
//Rebuild URL
$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o)));
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM software
LEFT JOIN logins ON login_software_id = software_id
"SELECT SQL_CALC_FOUND_ROWS * FROM software
WHERE software_template = 1
AND (software_name LIKE '%$q%' OR software_type LIKE '%$q%' OR software_key LIKE '%$q%')
ORDER BY $sb $o LIMIT $record_from, $record_to"
AND (software_name LIKE '%$q%' OR software_type LIKE '%$q%')
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
@@ -35,7 +35,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if(isset($q)){ echo stripslashes(htmlentities($q)); } ?>" placeholder="Search Licenses">
<input type="search" class="form-control" name="q" value="<?php if(isset($q)){ echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search License Templates">
<div class="input-group-append">
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
</div>
@@ -48,14 +48,25 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</div>
</form>
<hr>
<div class="table-responsive">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if($num_rows[0] == 0){ echo "d-none"; } ?>">
<tr>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=software_name&o=<?php echo $disp; ?>">Template</a></th>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=software_type&o=<?php echo $disp; ?>">Type</a></th>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=software_license_type&o=<?php echo $disp; ?>">License Type</a></th>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=software_seats&o=<?php echo $disp; ?>">Seats</a></th>
<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>
</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>
</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>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
@@ -64,22 +75,28 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
while($row = mysqli_fetch_array($sql)){
$software_id = intval($row['software_id']);
$software_name = htmlentities($row['software_name']);
$software_version = htmlentities($row['software_version']);
$software_type = htmlentities($row['software_type']);
$software_license_type = htmlentities($row['software_license_type']);
$software_key = htmlentities($row['software_key']);
$software_seats = htmlentities($row['software_seats']);
$software_purchase = htmlentities($row['software_purchase']);
$software_expire = htmlentities($row['software_expire']);
$software_notes = htmlentities($row['software_notes']);
$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']);
?>
<tr>
<td><a class="text-dark text-bold" href="#" data-toggle="modal" data-target="#editSoftwareTemplateModal<?php echo $software_id; ?>"><?php echo "$software_name<br><span class='text-secondary'>$software_version</span>"; ?></a></td>
<td>
<a class="text-dark" href="#" data-toggle="modal" data-target="#editSoftwareTemplateModal<?php echo $software_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>
</div>
</a>
</td>
<td><?php echo $software_type; ?></td>
<td><?php echo $software_license_type; ?></td>
<td><?php echo $software_seats; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" data-toggle="dropdown">
@@ -91,7 +108,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</a>
<?php if($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold" href="post.php?delete_software=<?php echo $software_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_software=<?php echo $software_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
@@ -102,7 +119,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
require("settings_software_template_edit_modal.php");
require "modals/admin_software_template_edit_modal.php";
}
?>
@@ -110,10 +128,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody>
</table>
</div>
<?php require_once("pagination.php"); ?>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once("settings_software_template_add_modal.php");
require_once("footer.php");
require_once "modals/admin_software_template_add_modal.php";
require_once "includes/footer.php";

View File

@@ -1,47 +1,26 @@
<?php
// Default Column Sortby Filter
$sb = "tag_name";
$o = "ASC";
$sort = "tag_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
require_once("inc_all_settings.php");
//Rebuild URL
$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o)));
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM tags
WHERE tag_name LIKE '%$q%'
AND company_id = $session_company_id
ORDER BY $sb $o LIMIT $record_from, $record_to"
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$colors_used_array = [];
if ($num_rows > 0) {
//Colors Used
$sql_colors_used = mysqli_query(
$mysqli,
"SELECT tag_color FROM tags
WHERE tag_archived_at IS NULL
AND company_id = $session_company_id"
);
while ($color_used_row = mysqli_fetch_array($sql_colors_used)) {
$colors_used_array[] = $color_used_row['tag_color'];
}
$colors_diff = array_diff($colors_array, $colors_used_array);
} else {
$colors_diff = $colors_array;
}
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-tags mr-2"></i>Tags</h3>
@@ -55,7 +34,7 @@ if ($num_rows > 0) {
<div class="col-sm-4 mb-2">
<form autocomplete="off">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(htmlentities($q)); } ?>" placeholder="Search Tags">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Tags">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
@@ -67,13 +46,20 @@ if ($num_rows > 0) {
</div>
<hr>
<div class="table-responsive">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=tag_name&o=<?php echo $disp; ?>">Name</a></th>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=tag_type&o=<?php echo $disp; ?>">Type</a></th>
<th>Color</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tag_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'tag_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tag_type&order=<?php echo $disp; ?>">
Type <?php if ($sort == 'tag_type') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
@@ -82,16 +68,30 @@ if ($num_rows > 0) {
while ($row = mysqli_fetch_array($sql)) {
$tag_id = intval($row['tag_id']);
$tag_name = htmlentities($row['tag_name']);
$tag_type = htmlentities($row['tag_type']);
$tag_color = htmlentities($row['tag_color']);
$tag_icon = htmlentities($row['tag_icon']);
$tag_name = nullable_htmlentities($row['tag_name']);
$tag_type = intval($row['tag_type']);
if ( $tag_type == 1) {
$tag_type_display = "Client Tag";
} elseif ( $tag_type == 2) {
$tag_type_display = "Location Tag";
} elseif ( $tag_type == 3) {
$tag_type_display = "Contact Tag";
} elseif ( $tag_type == 4) {
$tag_type_display = "Credential Tag";
} else {
$tag_type_display = "Unknown Tag";
}
$tag_color = nullable_htmlentities($row['tag_color']);
$tag_icon = nullable_htmlentities($row['tag_icon']);
?>
<tr>
<td><?php echo "<i class='fas fa-fw fa-$tag_icon mr-2'></i>"; ?><a class="text-dark" href="#" data-toggle="modal" data-target="#editTagModal<?php echo $tag_id; ?>"><?php echo "$tag_name"; ?></a></td>
<td><?php echo $tag_type; ?></td>
<td><i class="fa fa-3x fa-circle" style="color:<?php echo $tag_color; ?>;"></i></td>
<td>
<a href="#" data-toggle="modal" data-target="#editTagModal<?php echo $tag_id; ?>">
<span class='badge text-light p-2 mr-1' style="background-color: <?php echo $tag_color; ?>"><i class="fa fa-fw fa-<?php echo $tag_icon; ?> mr-2"></i><?php echo $tag_name; ?></span>
</a>
</td>
<td><?php echo $tag_type_display; ?></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
@@ -102,7 +102,7 @@ if ($num_rows > 0) {
<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_tag=<?php echo $tag_id; ?>">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_tag=<?php echo $tag_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
@@ -112,7 +112,8 @@ if ($num_rows > 0) {
<?php
require("settings_tag_edit_modal.php");
require "modals/admin_tag_edit_modal.php";
}
@@ -121,10 +122,13 @@ if ($num_rows > 0) {
</tbody>
</table>
</div>
<?php require_once("pagination.php"); ?>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once("settings_tag_add_modal.php");
require_once("footer.php");
require_once "modals/admin_tag_add_modal.php";
require_once "includes/footer.php";

View File

@@ -1,20 +1,20 @@
<?php
// Default Column Sortby Filter
$sb = "tax_name";
$o = "ASC";
$sort = "tax_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
require_once("inc_all_settings.php");
//Rebuild URL
$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o)));
$url_query_strings_sort = http_build_query($get_copy);
$sql = mysqli_query(
$mysqli,
$mysqli,
"SELECT * FROM taxes
WHERE tax_archived_at IS NULL
AND company_id = $session_company_id
ORDER BY $sb $o"
ORDER BY $sort $order"
);
$num_rows = mysqli_num_rows($sql);
@@ -29,12 +29,20 @@ $num_rows = mysqli_num_rows($sql);
</div>
</div>
<div class="card-body">
<div class="table-responsive">
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows == 0) { echo "d-none"; } ?>">
<tr>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=tax_name&o=<?php echo $disp; ?>">Name</a></th>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=tax_percent&o=<?php echo $disp; ?>">Percent</a></th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tax_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'tax_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=tax_percent&order=<?php echo $disp; ?>">
Percent <?php if ($sort == 'tax_percent') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
@@ -43,7 +51,7 @@ $num_rows = mysqli_num_rows($sql);
while ($row = mysqli_fetch_array($sql)) {
$tax_id = intval($row['tax_id']);
$tax_name = htmlentities($row['tax_name']);
$tax_name = nullable_htmlentities($row['tax_name']);
$tax_percent = floatval($row['tax_percent']);
?>
@@ -60,7 +68,7 @@ $num_rows = mysqli_num_rows($sql);
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="post.php?archive_tax=<?php echo $tax_id; ?>">
<a class="dropdown-item text-danger confirm-link" href="post.php?archive_tax=<?php echo $tax_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
</div>
@@ -70,7 +78,8 @@ $num_rows = mysqli_num_rows($sql);
<?php
require("settings_tax_edit_modal.php");
require "modals/admin_tax_edit_modal.php";
}
if ($num_rows == 0) {
@@ -87,5 +96,7 @@ $num_rows = mysqli_num_rows($sql);
</div>
<?php
require_once("settings_tax_add_modal.php");
require_once("footer.php");
require_once "modals/admin_tax_add_modal.php";
require_once "includes/footer.php";

135
admin_ticket_status.php Normal file
View File

@@ -0,0 +1,135 @@
<?php
// Default Column Sortby Filter
$sort = "ticket_status_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 ticket_statuses
WHERE ticket_status_name LIKE '%$q%'
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-info-circle mr-2"></i>Tickets Statuses</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addTicketStatusModal"><i class="fas fa-plus mr-2"></i>New Ticket Status</button>
</div>
</div>
<div class="card-body">
<div class="row">
<div class="col-sm-4 mb-2">
<form autocomplete="off">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Ticket Statuses">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</form>
</div>
<div class="col-sm-8">
</div>
</div>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_status_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'ticket_status_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_status_color&order=<?php echo $disp; ?>">
Color <?php if ($sort == 'ticket_status_color') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_status_active&order=<?php echo $disp; ?>">
Status <?php if ($sort == 'ticket_status_active') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$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_status_active = intval($row['ticket_status_active']);
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>";
}
?>
<tr>
<td>
<a href="#" data-toggle="modal" data-target="#editTicketStatusModal<?php echo $ticket_status_id; ?>">
<?php echo $ticket_status_name; ?>
</a>
</td>
<td>
<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>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editTicketStatusModal<?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>
</div>
</div>
<?php } ?>
</td>
</tr>
<?php
if ( $ticket_status_id > 5 ) {
require "modals/admin_ticket_status_edit_modal.php";
}
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_ticket_status_add_modal.php";
require_once "includes/footer.php";

119
admin_ticket_template.php Normal file
View File

@@ -0,0 +1,119 @@
<?php
// Default Column Sortby Filter
$sort = "ticket_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 ticket_templates
WHERE (ticket_template_name LIKE '%$q%' OR ticket_template_description LIKE '%$q%')
AND ticket_template_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-life-ring mr-2"></i>Ticket Templates</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addTicketTemplateModal"><i class="fas fa-plus mr-2"></i>New Ticket Template</button>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if(isset($q)){ echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Ticket Templates">
<div class="input-group-append">
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-md-8">
</div>
</div>
</form>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if($num_rows[0] == 0){ echo "d-none"; } ?>">
<tr>
<th>
<a class="text-secondary" href="?<?php echo $url_query_strings_sort; ?>&sort=ticket_template_name&order=<?php echo $disp; ?>">
Template <?php if ($sort == 'ticket_template_name') { echo $order_icon; } ?>
</a>
</th>
<th>Tasks</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while($row = mysqli_fetch_array($sql)){
$ticket_template_id = intval($row['ticket_template_id']);
$ticket_template_name = nullable_htmlentities($row['ticket_template_name']);
$ticket_template_description = nullable_htmlentities($row['ticket_template_description']);
$ticket_template_subject = nullable_htmlentities($row['ticket_template_subject']);
$ticket_template_created_at = nullable_htmlentities($row['ticket_template_created_at']);
?>
<tr>
<td>
<a class="text-dark">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body">
<div>
<a href="admin_ticket_template_details.php?ticket_template_id=<?php echo $ticket_template_id; ?>">
<?php echo $ticket_template_name; ?>
</a>
</div>
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
</div>
</div>
</a>
</td>
<td>0</td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item text-danger text-bold confirm-link" href="post.php?delete_ticket_template=<?php echo $ticket_template_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
</div>
</div>
</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once "modals/admin_ticket_template_add_modal.php";
require_once "includes/footer.php";

View File

@@ -0,0 +1,144 @@
<?php
require_once "includes/inc_all_admin.php";
//Initialize the HTML Purifier to prevent XSS
require "plugins/htmlpurifier/HTMLPurifier.standalone.php";
$purifier_config = HTMLPurifier_Config::createDefault();
$purifier_config->set('Cache.DefinitionImpl', null); // Disable cache by setting a non-existent directory or an invalid one
$purifier_config->set('URI.AllowedSchemes', ['data' => true, 'src' => true, 'http' => true, 'https' => true]);
$purifier = new HTMLPurifier($purifier_config);
if (isset($_GET['ticket_template_id'])) {
$ticket_template_id = intval($_GET['ticket_template_id']);
}
$sql_ticket_templates = mysqli_query($mysqli, "SELECT * FROM ticket_templates WHERE ticket_template_id = $ticket_template_id");
$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_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']);
$ticket_template_updated_at = nullable_htmlentities($row['ticket_template_updated_at']);
// Get Task Templates
$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");
?>
<ol class="breadcrumb d-print-none">
<li class="breadcrumb-item">
<a href="clients.php">Home</a>
</li>
<li class="breadcrumb-item">
<a href="admin_user.php">Admin</a>
</li>
<li class="breadcrumb-item">
<a href="admin_ticket_template.php">Ticket Templates</a>
</li>
<li class="breadcrumb-item active"><i class="fas fa-life-ring mr-2"></i><?php echo $ticket_template_name; ?></li>
</ol>
<div class="row">
<div class="col-8">
<div class="card card-dark">
<div class="card-header">
<h3 class="card-title mt-2">
<div class="media">
<i class="fa fa-fw fa-2x fa-life-ring mr-3"></i>
<div class="media-body">
<h3 class="mb-0"><?php echo $ticket_template_name; ?></h3>
<div><small class="text-secondary"><?php echo $ticket_template_description; ?></small></div>
</div>
</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; ?>
</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_order = intval($row['task_template_order']);
$task_completion_estimate = intval($row['task_template_completion_estimate']);
$task_description = nullable_htmlentities($row['task_template_description']);
?>
<tr>
<td><i class="far fa-fw fa-square text-secondary"></i></td>
<td><span class="text-secondary"><?php echo $task_completion_estimate; ?>m</span> - <?php echo $task_name; ?></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="modal" data-target="#editTaskModal<?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
require "modals/task_edit_modal.php";
}
?>
</table>
</div>
</div>
</div>
</div>
<script src="js/pretty_content.js"></script>
<?php
require_once "modals/admin_ticket_template_edit_modal.php";
require_once "includes/footer.php";

88
admin_update.php Normal file
View File

@@ -0,0 +1,88 @@
<?php
require_once "includes/inc_all_admin.php";
require_once "includes/database_version.php";
$updates = fetchUpdates();
$latest_version = $updates->latest_version;
$current_version = $updates->current_version;
$result = $updates->result;
$git_log = shell_exec("git log $repo_branch..origin/$repo_branch --pretty=format:'<tr><td>%h</td><td>%ar</td><td>%s</td></tr>'");
?>
<div class="card card-dark">
<div class="card-header py-3">
<h3 class="card-title"><i class="fas fa-fw fa-download mr-2"></i>Update</h3>
</div>
<div class="card-body" style="text-align: center;">
<!-- Check if git fetch result was successful (0), if not show a warning -->
<?php if ($result !== 0) { ?>
<div class="alert alert-danger">
<strong>WARNING: Could not find execute 'git fetch'.</strong>
<br><br>
<i>Error details:- <?php echo shell_exec("git fetch 2>&1"); ?></i>
<br>
<br>Things to check: Is Git installed? Is the Git origin/remote correct? Are web server file permissions too strict?
<br>Seek support on the <a href="https://forum.itflow.org">Forum</a> if required - include relevant PHP error logs & ITFlow debug output
</div>
<?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>
<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>
<br>
<small class="text-secondary">Current DB Version: <?php echo CURRENT_DATABASE_VERSION; ?></small>
<br>
<small class="text-secondary">Latest DB Version: <?php echo LATEST_DATABASE_VERSION; ?></small>
<br>
<hr>
<?php } else {
if (!empty($git_log)) { ?>
<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>
<?php } else { ?>
<p><strong>Application Release Version:<br><strong class="text-dark"><?php echo APP_VERSION; ?></strong></p>
<p class="text-secondary">Database Version:<br><strong class="text-dark"><?php echo CURRENT_DATABASE_VERSION; ?></strong></p>
<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 (!empty($git_log)) { ?>
<table class="table ">
<thead>
<tr>
<th>Commit</th>
<th>When</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<?php
echo $git_log;
?>
</tbody>
</table>
<?php
}
?>
</div>
</div>
<?php
require_once "includes/footer.php";

243
admin_user.php Normal file
View File

@@ -0,0 +1,243 @@
<?php
// Default Column Sortby Filter
$sort = "user_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 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%')
AND user_archived_at IS NULL
ORDER BY $sort $order LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-users mr-2"></i>Users</h3>
<div class="card-tools">
<div class="btn-group">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addUserModal">
<i class="fas fa-fw fa-user-plus mr-2"></i>New User
</button>
<button type="button" class="btn btn-primary dropdown-toggle dropdown-toggle-split" data-toggle="dropdown"></button>
<div class="dropdown-menu">
<!--<a class="dropdown-item text-dark" href="#" data-toggle="modal" data-target="#userInviteModal"><i class="fas fa-paper-plane mr-2"></i>Invite User</a>-->
<?php if ($num_rows[0] > 1) { ?>
<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 } ?>
</div>
</div>
</div>
</div>
<div class="card-body">
<form class="mb-4" autocomplete="off">
<div class="row">
<div class="col-md-4">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) {echo stripslashes(nullable_htmlentities($q));} ?>" placeholder="Search Users">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-md-8">
<div class="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>
<hr>
<div class="table-responsive-sm">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th class="text-center">
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_name&order=<?php echo $disp; ?>">
Name <?php if ($sort == 'user_name') { echo $order_icon; } ?>
</a>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_email&order=<?php echo $disp; ?>">
Email <?php if ($sort == 'user_email') { echo $order_icon; } ?>
</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>
</th>
<th>
<a class="text-dark" href="?<?php echo $url_query_strings_sort; ?>&sort=user_status&order=<?php echo $disp; ?>">
Status <?php if ($sort == 'user_status') { echo $order_icon; } ?>
</a>
</th>
<th class="text-center">MFA</th>
<th>
Last Login
</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$user_id = intval($row['user_id']);
$user_name = nullable_htmlentities($row['user_name']);
$user_email = nullable_htmlentities($row['user_email']);
$user_status = intval($row['user_status']);
if ($user_status == 2) {
$user_status_display = "<span class='text-info'>Invited</span>";
} elseif ($user_status == 1) {
$user_status_display = "<span class='text-success'>Active</span>";
} else{
$user_status_display = "<span class='text-danger'>Disabled</span>";
}
$user_avatar = nullable_htmlentities($row['user_avatar']);
$user_token = nullable_htmlentities($row['user_token']);
if(empty($user_token)) {
$mfa_status_display = "<i class='fas fa-fw fa-unlock text-danger'></i>";
} else {
$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_initials = nullable_htmlentities(initials($user_name));
$sql_last_login = mysqli_query(
$mysqli,
"SELECT * FROM logs
WHERE log_user_id = $user_id AND log_type = 'Login'
ORDER BY log_id DESC LIMIT 1"
);
if (mysqli_num_rows($sql_last_login) == 0) {
$last_login = "<span class='text-bold'>Never logged in</span>";
} else {
$row = mysqli_fetch_array($sql_last_login);
$log_created_at = nullable_htmlentities($row['log_created_at']);
$log_ip = nullable_htmlentities($row['log_ip']);
$log_user_agent = nullable_htmlentities($row['log_user_agent']);
$log_user_os = getOS($log_user_agent);
$log_user_browser = getWebBrowser($log_user_agent);
$last_login = "$log_created_at<small class='text-secondary'><div class='mt-1'>$log_user_os</div><div class='mt-1'>$log_user_browser</div><div class='mt-1'><i class='fa fa-fw fa-globe'></i> $log_ip</div></small>";
}
// Get User Client Access Permissions
$user_client_access_sql = mysqli_query($mysqli,"SELECT client_id FROM user_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']);
}
$sql_remember_tokens = mysqli_query($mysqli, "SELECT * FROM remember_tokens WHERE remember_token_user_id = $user_id");
$remember_token_count = mysqli_num_rows($sql_remember_tokens);
?>
<tr>
<td class="text-center">
<a class="text-dark" href="#" <?php if ($user_id !== $session_user_id) { // Prevent modifying self ?> data-toggle="modal" data-target="#editUserModal<?php echo $user_id; ?>" <?php } ?>>
<?php if (!empty($user_avatar)) { ?>
<img class="img-size-50 img-circle" src="<?php echo "uploads/users/$user_id/$user_avatar"; ?>">
<?php } else { ?>
<span class="fa-stack fa-2x">
<i class="fa fa-circle fa-stack-2x text-secondary"></i>
<span class="fa fa-stack-1x text-white"><?php echo $user_initials; ?></span>
</span>
<br>
<?php } ?>
<div class="text-secondary"><?php echo $user_name; ?></div>
</a>
</td>
<td><a href="mailto:<?php echo $user_email; ?>"><?php echo $user_email; ?></a></td>
<td><?php echo $user_role_display; ?></td>
<td><?php echo $user_status_display; ?></td>
<td class="text-center"><?php echo $mfa_status_display; ?></td>
<td><?php echo $last_login; ?></td>
<td>
<?php if ($user_id !== $session_user_id) { // Prevent modifying self ?>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editUserModal<?php echo $user_id; ?>">
<i class="fas fa-fw fa-user-edit mr-2"></i>Edit
</a>
<?php if ($remember_token_count > 0) { ?>
<a class="dropdown-item" href="post.php?revoke_remember_me=<?php echo $user_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>"><i class="fas fa-fw fa-ban mr-2"></i>Revoke <?php echo $remember_token_count; ?> Remember Tokens
</a>
<?php } ?>
<?php if ($user_status == 0) { ?>
<a class="dropdown-item text-success" href="post.php?activate_user=<?php echo $user_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-user-check mr-2"></i>Activate
</a>
<?php }elseif ($user_status == 1) { ?>
<a class="dropdown-item text-danger" href="post.php?disable_user=<?php echo $user_id; ?>&csrf_token=<?php echo $_SESSION['csrf_token'] ?>">
<i class="fas fa-fw fa-user-slash mr-2"></i>Disable
</a>
<?php } ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="#" data-toggle="modal" data-target="#archiveUserModal<?php echo $user_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
</div>
</div>
<?php } ?>
</td>
</tr>
<?php
require "modals/admin_user_edit_modal.php";
require "modals/admin_user_archive_modal.php";
}
?>
</tbody>
</table>
</div>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<script>
function generatePassword() {
document.getElementById("password").value = "<?php echo randomString() ?>"
}
</script>
<?php
require_once "modals/admin_user_add_modal.php";
require_once "modals/admin_user_invite_modal.php";
require_once "modals/admin_user_export_modal.php";
require_once "modals/admin_user_all_reset_password_modal.php";
require_once "includes/footer.php";

View File

@@ -1,19 +1,20 @@
<?php
// Default Column Sortby Filter
$sb = "vendor_name";
$o = "ASC";
$sort = "vendor_name";
$order = "ASC";
require_once "includes/inc_all_admin.php";
require_once("inc_all_settings.php");
//Rebuild URL
$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o)));
$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 $sb $o LIMIT $record_from, $record_to"
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"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
@@ -37,7 +38,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<div class="col-md-4">
<div class="input-group mb-3 mb-md-0">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(htmlentities($q)); } ?>" placeholder="Search Vendors Templates">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(nullable_htmlentities($q)); } ?>" placeholder="Search Vendors Templates">
<div class="input-group-append">
<button class="btn btn-dark"><i class="fa fa-search"></i></button>
</div>
@@ -51,8 +52,16 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=vendor_name&o=<?php echo $disp; ?>">Vendor</a></th>
<th><a class="text-secondary" href="?<?php echo $url_query_strings_sb; ?>&sb=vendor_description&o=<?php echo $disp; ?>">Description</a></th>
<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>
</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>
</th>
<th>Contact</th>
<th class="text-center">Action</th>
</tr>
@@ -62,28 +71,28 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
while ($row = mysqli_fetch_array($sql)) {
$vendor_id = intval($row['vendor_id']);
$vendor_name = htmlentities($row['vendor_name']);
$vendor_description = htmlentities($row['vendor_description']);
$vendor_name = nullable_htmlentities($row['vendor_name']);
$vendor_description = nullable_htmlentities($row['vendor_description']);
if (empty($vendor_description)) {
$vendor_description_display = "-";
} else {
$vendor_description_display = $vendor_description;
}
$vendor_account_number = htmlentities($row['vendor_account_number']);
$vendor_contact_name = htmlentities($row['vendor_contact_name']);
$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 = "-";
} else {
$vendor_contact_name_display = $vendor_contact_name;
}
$vendor_phone = formatPhoneNumber($row['vendor_phone']);
$vendor_extension = htmlentities($row['vendor_extension']);
$vendor_email = htmlentities($row['vendor_email']);
$vendor_website = htmlentities($row['vendor_website']);
$vendor_hours = htmlentities($row['vendor_hours']);
$vendor_sla = htmlentities($row['vendor_sla']);
$vendor_code = htmlentities($row['vendor_code']);
$vendor_notes = htmlentities($row['vendor_notes']);
$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']);
?>
@@ -135,7 +144,7 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</a>
<?php if ($session_user_role == 3) { ?>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger text-bold" 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_id; ?>">
<i class="fas fa-fw fa-trash mr-2"></i>Delete
</a>
<?php } ?>
@@ -146,7 +155,8 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
<?php
require("vendor_template_edit_modal.php");
require "modals/admin_vendor_template_edit_modal.php";
}
?>
@@ -154,10 +164,13 @@ $num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
</tbody>
</table>
</div>
<?php require_once("pagination.php"); ?>
<?php require_once "includes/filter_footer.php";
?>
</div>
</div>
<?php
require_once("vendor_template_add_modal.php");
require_once("footer.php");
require_once "modals/admin_vendor_template_add_modal.php";
require_once "includes/footer.php";

328
ajax.php
View File

@@ -6,46 +6,31 @@
* Always returns data in JSON format, unless otherwise specified
*/
require_once("config.php");
require_once("functions.php");
require_once("check_login.php");
require_once("rfc6238.php");
require_once "config.php";
require_once "functions.php";
require_once "check_login.php";
require_once "plugins/totp/totp.php";
/*
* Fetches SSL certificates from remote hosts & returns the relevant info (issuer, expiry, public key)
*/
if (isset($_GET['certificate_fetch_parse_json_details'])) {
// PHP doesn't appreciate attempting SSL sockets to non-existent domains
if (empty($_GET['domain'])) {
exit();
}
$domain = $_GET['domain'];
// FQDNs in database shouldn't have a URL scheme, adding one
$domain = "https://".$domain;
$name = $_GET['domain'];
// Parse host and port
$url = parse_url($domain, PHP_URL_HOST);
$port = parse_url($domain, PHP_URL_PORT);
// Default port
if (!$port) {
$port = "443";
}
// Get SSL cert for domain (if exists)
$certificate = getSSL($name);
// Get certificate (using verify peer false to allow for self-signed certs)
$socket = "ssl://$url:$port";
$get = stream_context_create(array("ssl" => array("capture_peer_cert" => true, "verify_peer" => false,)));
$read = stream_socket_client($socket, $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $get);
$cert = stream_context_get_params($read);
$cert_public_key_obj = openssl_x509_parse($cert['options']['ssl']['peer_certificate']);
openssl_x509_export($cert['options']['ssl']['peer_certificate'], $export);
// Process data
if ($cert_public_key_obj) {
if ($certificate['success'] == "TRUE") {
$response['success'] = "TRUE";
$response['expire'] = date('Y-m-d', $cert_public_key_obj['validTo_time_t']);
$response['issued_by'] = strip_tags($cert_public_key_obj['issuer']['O']);
$response['public_key'] = $export; //nl2br
$response['expire'] = $certificate['expire'];
$response['issued_by'] = $certificate['issued_by'];
$response['public_key'] = $certificate['public_key'];
} else {
$response['success'] = "FALSE";
}
@@ -70,7 +55,7 @@ if (isset($_GET['certificate_get_json_details'])) {
}
// Get all domains for this client that could be linked to this certificate
$domains_sql = mysqli_query($mysqli, "SELECT domain_id, domain_name FROM domains WHERE domain_client_id = '$client_id' AND company_id = '$session_company_id'");
$domains_sql = mysqli_query($mysqli, "SELECT domain_id, domain_name FROM domains WHERE domain_client_id = $client_id");
while ($row = mysqli_fetch_array($domains_sql)) {
$response['domains'][] = $row;
}
@@ -82,7 +67,7 @@ if (isset($_GET['certificate_get_json_details'])) {
* Looks up info for a given domain ID from the database, used to dynamically populate modal fields
*/
if (isset($_GET['domain_get_json_details'])) {
validateTechRole();
enforceUserPermission('module_support');
$domain_id = intval($_GET['domain_id']);
$client_id = intval($_GET['client_id']);
@@ -94,11 +79,29 @@ if (isset($_GET['domain_get_json_details'])) {
}
// Get all registrars/webhosts (vendors) for this client that could be linked to this domain
$vendor_sql = mysqli_query($mysqli, "SELECT vendor_id, vendor_name FROM vendors WHERE vendor_client_id = $client_id");
$vendor_sql = 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($vendor_sql)) {
$response['vendors'][] = $row;
}
// Get domain history
$history_sql = mysqli_query($mysqli, "SELECT * FROM domain_history WHERE domain_history_domain_id = $domain_id");
$history_html = "<table class='table table-sm table-striped border table-hover'>";
$history_html .= "<thead class='thead-dark'><tr><th>Date</th><th>Field</th><th>Before</th><th>After</th></tr></thead><tbody>";
while ($row = mysqli_fetch_array($history_sql)) {
// Fetch data from the query and create table rows
$history_html .= "<tr>";
$history_html .= "<td>" . htmlspecialchars(date('Y-m-d', strtotime($row['domain_history_modified_at']))) . "</td>";
$history_html .= "<td>" . htmlspecialchars($row['domain_history_column']) . "</td>";
$history_html .= "<td>" . htmlspecialchars($row['domain_history_old_value']) . "</td>";
$history_html .= "<td>" . htmlspecialchars($row['domain_history_new_value']) . "</td>";
$history_html .= "</tr>";
}
$history_html .= "</tbody></table>";
// Return the HTML content to JavaScript
$response['history'] = $history_html;
echo json_encode($response);
}
@@ -110,17 +113,19 @@ if (isset($_GET['merge_ticket_get_json_details'])) {
$merge_into_ticket_number = intval($_GET['merge_into_ticket_number']);
$sql = mysqli_query($mysqli, "SELECT ticket_id, ticket_number, ticket_prefix, ticket_subject, ticket_priority, ticket_status, client_name, contact_name FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
WHERE ticket_number = '$merge_into_ticket_number' AND tickets.company_id = '$session_company_id'");
$sql = mysqli_query($mysqli, "SELECT ticket_id, ticket_number, ticket_prefix, ticket_subject, ticket_priority, ticket_status, ticket_status_name, client_name, contact_name FROM tickets
LEFT JOIN clients ON ticket_client_id = client_id
LEFT JOIN contacts ON ticket_contact_id = contact_id
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
WHERE ticket_number = $merge_into_ticket_number");
if (mysqli_num_rows($sql) == 0) {
//Do nothing.
echo "No ticket found!";
} else {
//Return ticket, client and contact details for the given ticket number
$response = mysqli_fetch_array($sql);
$response = array_map('htmlentities', $response);
echo json_encode($response);
}
}
@@ -143,8 +148,8 @@ if (isset($_GET['network_get_json_details'])) {
// Lookup all client locations, as networks can be associated with any client location
$locations_sql = mysqli_query(
$mysqli,
"SELECT location_id, location_name FROM locations
WHERE location_client_id = '$client_id' AND company_id = '$session_company_id'"
"SELECT location_id, location_name FROM locations
WHERE location_client_id = '$client_id'"
);
while ($row = mysqli_fetch_array($locations_sql)) {
$response['locations'][] = $row;
@@ -158,10 +163,10 @@ if (isset($_POST['client_set_notes'])) {
$notes = sanitizeInput($_POST['notes']);
// Update notes
mysqli_query($mysqli, "UPDATE clients SET client_notes = '$notes' WHERE client_id = '$client_id'");
mysqli_query($mysqli, "UPDATE clients SET client_notes = '$notes' WHERE client_id = $client_id");
// Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Client', log_action = 'Modify', log_description = '$session_name modified client notes', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_created_at = NOW(), log_client_id = $client_id, log_user_id = $session_user_id, company_id = $session_company_id");
logAction("Client", "Edit", "$session_name edited client notes", $client_id);
}
@@ -169,11 +174,39 @@ if (isset($_POST['contact_set_notes'])) {
$contact_id = intval($_POST['contact_id']);
$notes = sanitizeInput($_POST['notes']);
// Get Contact Details and Client ID for Logging
$sql = mysqli_query($mysqli,"SELECT contact_name, contact_client_id
FROM contacts WHERE contact_id = $contact_id"
);
$row = mysqli_fetch_array($sql);
$contact_name = sanitizeInput($row['contact_name']);
$client_id = intval($row['contact_client_id']);
// Update notes
mysqli_query($mysqli, "UPDATE contacts SET contact_notes = '$notes' WHERE contact_id = $contact_id");
// Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Contact', log_action = 'Modify', log_description = '$session_name modified contact notes', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id, company_id = $session_company_id");
logAction("Contact", "Edit", "$session_name edited contact notes for $contact_name", $client_id, $contact_id);
}
if (isset($_POST['asset_set_notes'])) {
$asset_id = intval($_POST['asset_id']);
$notes = sanitizeInput($_POST['notes']);
// Get Asset Details and Client ID for Logging
$sql = mysqli_query($mysqli,"SELECT asset_name, asset_client_id
FROM assets WHERE asset_id = $asset_id"
);
$row = mysqli_fetch_array($sql);
$asset_name = sanitizeInput($row['asset_name']);
$client_id = intval($row['asset_client_id']);
// Update notes
mysqli_query($mysqli, "UPDATE assets SET asset_notes = '$notes' WHERE asset_id = $asset_id");
// Logging
logAction("Asset", "Edit", "$session_name edited asset notes for $asset_name", $client_id, $asset_id);
}
@@ -185,7 +218,7 @@ if (isset($_POST['contact_set_notes'])) {
if (isset($_GET['ticket_add_view'])) {
$ticket_id = intval($_GET['ticket_id']);
mysqli_query($mysqli, "INSERT INTO ticket_views SET view_ticket_id = '$ticket_id', view_user_id = '$session_user_id', view_timestamp = NOW()");
mysqli_query($mysqli, "INSERT INTO ticket_views SET view_ticket_id = $ticket_id, view_user_id = $session_user_id, view_timestamp = NOW()");
}
/*
@@ -196,7 +229,7 @@ if (isset($_GET['ticket_add_view'])) {
if (isset($_GET['ticket_query_views'])) {
$ticket_id = intval($_GET['ticket_id']);
$query = mysqli_query($mysqli, "SELECT user_name FROM ticket_views LEFT JOIN users ON view_user_id = user_id WHERE view_ticket_id = '$ticket_id' AND view_user_id != '$session_user_id' AND view_timestamp > DATE_SUB(NOW(), INTERVAL 2 MINUTE)");
$query = mysqli_query($mysqli, "SELECT user_name FROM ticket_views LEFT JOIN users ON view_user_id = user_id WHERE view_ticket_id = $ticket_id AND view_user_id != $session_user_id AND view_timestamp > DATE_SUB(NOW(), INTERVAL 2 MINUTE)");
while ($row = mysqli_fetch_array($query)) {
$users[] = $row['user_name'];
}
@@ -205,10 +238,10 @@ if (isset($_GET['ticket_query_views'])) {
$users = array_unique($users);
if (count($users) > 1) {
// Multiple viewers
$response['message'] = htmlentities(implode(", ", $users) . " are viewing this ticket.");
$response['message'] = "<i class='fas fa-fw fa-eye mr-2'></i>" . nullable_htmlentities(implode(", ", $users) . " are viewing this ticket.");
} else {
// Single viewer
$response['message'] = htmlentities(implode("", $users) . " is viewing this ticket.");
$response['message'] = "<i class='fas fa-fw fa-eye mr-2'></i>" . nullable_htmlentities(implode("", $users) . " is viewing this ticket.");
}
} else {
// No viewers
@@ -230,23 +263,39 @@ if (isset($_GET['share_generate_link'])) {
$client_id = intval($_GET['client_id']);
$item_type = sanitizeInput($_GET['type']);
$item_id = intval($_GET['id']);
$item_email = sanitizeInput($_GET['contact_email']);
$item_note = sanitizeInput($_GET['note']);
$item_view_limit = intval($_GET['views']);
$item_view_limit_wording = "";
if ($item_view_limit == 1) {
$item_view_limit_wording = " and may only be viewed <strong>once</strong>, before the link is destroyed.";
}
$item_expires = sanitizeInput($_GET['expires']);
$item_expires_friendly = "never"; // default never
if ($item_expires == "1 HOUR") {
$item_expires_friendly = "1 hour";
} elseif ($item_expires == "24 HOUR") {
$item_expires_friendly = "1 day";
} elseif ($item_expires == "168 HOUR") {
$item_expires_friendly = "1 week";
} elseif ($item_expires == "730 HOUR") {
$item_expires_friendly = "1 month";
}
$item_key = randomString(156);
if ($item_type == "Document") {
$row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT document_name FROM documents WHERE document_id = '$item_id' AND document_client_id = '$client_id' LIMIT 1"));
$row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT document_name FROM documents WHERE document_id = $item_id AND document_client_id = $client_id LIMIT 1"));
$item_name = sanitizeInput($row['document_name']);
}
if ($item_type == "File") {
$row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT file_name FROM files WHERE file_id = '$item_id' AND file_client_id = '$client_id' LIMIT 1"));
$row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT file_name FROM files WHERE file_id = $item_id AND file_client_id = $client_id LIMIT 1"));
$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");
$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);
$item_name = sanitizeInput($row['login_name']);
@@ -266,32 +315,82 @@ if (isset($_GET['share_generate_link'])) {
}
// Insert entry into DB
$sql = mysqli_query($mysqli, "INSERT INTO shared_items SET item_active = '1', item_key = '$item_key', item_type = '$item_type', item_related_id = '$item_id', item_encrypted_username = '$item_encrypted_username', item_encrypted_credential = '$item_encrypted_credential', item_note = '$item_note', item_views = 0, item_view_limit = '$item_view_limit', item_created_at = NOW(), item_expire_at = '$item_expires', item_client_id = '$client_id'");
$sql = mysqli_query($mysqli, "INSERT INTO shared_items SET item_active = 1, item_key = '$item_key', item_type = '$item_type', item_related_id = $item_id, item_encrypted_username = '$item_encrypted_username', item_encrypted_credential = '$item_encrypted_credential', item_note = '$item_note', item_recipient = '$item_email', item_views = 0, item_view_limit = $item_view_limit, item_expire_at = NOW() + INTERVAL + $item_expires, item_client_id = $client_id");
$share_id = $mysqli->insert_id;
// Return URL
if ($item_type == "Login") {
$url = "$config_base_url/guest_view_item.php?id=$share_id&key=$item_key&ek=$login_encryption_key";
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key&ek=$login_encryption_key";
}
else {
$url = "$config_base_url/guest_view_item.php?id=$share_id&key=$item_key";
$url = "https://$config_base_url/guest/guest_view_item.php?id=$share_id&key=$item_key";
}
$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']));
// Sanitize Config vars from get_settings.php
$config_ticket_from_name = sanitizeInput($config_ticket_from_name);
$config_ticket_from_email = sanitizeInput($config_ticket_from_email);
$config_mail_from_name = sanitizeInput($config_mail_from_name);
$config_mail_from_email = sanitizeInput($config_mail_from_email);
// Send user e-mail, if specified
if(!empty($config_smtp_host) && filter_var($item_email, FILTER_VALIDATE_EMAIL)){
$subject = "Time sensitive - $company_name secure link enclosed";
if ($item_expires_friendly == "never") {
$subject = "$company_name secure link enclosed";
}
$body = "Hello,<br><br>$session_name from $company_name sent you a time sensitive secure link regarding \"$item_name\".<br><br>The link will expire in <strong>$item_expires_friendly</strong>$item_view_limit_wording.<br><br><strong><a href=\'$url\'>Click here to access your secure content</a></strong><br><br>--<br>$company_name - Support<br>$config_ticket_from_email<br>$company_phone";
// Add the intended recipient disclosure
$body .= "<br><br><em>This email and any attachments are confidential and intended for the specified recipient(s) only. If you are not the intended recipient, please notify the sender and delete this email. Unauthorized use, disclosure, or distribution is prohibited.</em>";
$data = [
[
'from' => $config_mail_from_email,
'from_name' => $config_mail_from_name,
'recipient' => $item_email,
'recipient_name' => $item_email,
'subject' => $subject,
'body' => $body
]
];
addToMailQueue($data);
}
echo json_encode($url);
// Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Sharing', log_action = 'Create', log_description = '$session_name created shared link for $item_type - $item_name', log_client_id = '$client_id', log_ip = '$session_ip', log_user_agent = '$session_user_agent', log_user_id = $session_user_id, company_id = $session_company_id");
logAction("Share", "Create", "$session_name created shared link for $item_type - $item_name", $client_id, $item_id);
}
/*
* Looks up info for a given scheduled ticket ID from the database, used to dynamically populate modal edit fields
* Looks up info for a given recurring (was scheduled) ticket ID from the database, used to dynamically populate modal edit fields
*/
if (isset($_GET['scheduled_ticket_get_json_details'])) {
if (isset($_GET['recurring_ticket_get_json_details'])) {
validateTechRole();
$client_id = intval($_GET['client_id']);
$ticket_id = intval($_GET['ticket_id']);
// Get all contacts, to allow tickets to be raised under a specific contact
$contact_sql = mysqli_query($mysqli, "SELECT contact_id, contact_name FROM contacts
WHERE contact_client_id = $client_id
AND contact_archived_at IS NULL
ORDER BY contact_primary DESC, contact_technical DESC, contact_name ASC"
);
while ($row = mysqli_fetch_array($contact_sql)) {
$response['contacts'][] = $row;
}
// Get ticket details
$ticket_sql = mysqli_query($mysqli, "SELECT * FROM scheduled_tickets
WHERE scheduled_ticket_id = $ticket_id
AND scheduled_ticket_client_id = $client_id LIMIT 1");
@@ -299,21 +398,134 @@ if (isset($_GET['scheduled_ticket_get_json_details'])) {
$response['ticket'][] = $row;
}
// Get assets
$asset_sql = mysqli_query($mysqli, "SELECT asset_id, asset_name FROM assets WHERE asset_client_id = $client_id AND asset_archived_at IS NULL");
while ($row = mysqli_fetch_array($asset_sql)) {
$response['assets'][] = $row;
}
// Get technicians to auto assign the ticket to
$sql_agents = 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"
);
while ($row = mysqli_fetch_array($sql_agents)) {
$response['agents'][] = $row;
}
echo json_encode($response);
}
/*
* Dynamic TOTP for client login page
* When provided with a TOTP secret, returns a 6-digit code
* Looks up info for a given quote ID from the database, used to dynamically populate modal fields
*/
if (isset($_GET['get_totp_token'])) {
$otp = TokenAuth6238::getTokenCode($_GET['totp_secret']);
if (isset($_GET['quote_get_json_details'])) {
$quote_id = intval($_GET['quote_id']);
// Get quote details
$quote_sql = mysqli_query(
$mysqli,
"SELECT * FROM quotes
LEFT JOIN clients ON quote_client_id = client_id
WHERE quote_id = $quote_id LIMIT 1"
);
while ($row = mysqli_fetch_array($quote_sql)) {
$response['quote'][] = $row;
}
// Get all income-related categories for quoting
$quote_created_at = $response['quote'][0]['quote_created_at'];
$category_sql = mysqli_query(
$mysqli,
"SELECT category_id, category_name FROM categories
WHERE category_type = 'Income' AND (category_archived_at > '$quote_created_at' OR category_archived_at IS NULL)
ORDER BY category_name"
);
while ($row = mysqli_fetch_array($category_sql)) {
$response['categories'][] = $row;
}
echo json_encode($response);
echo json_encode($otp);
}
/*
* Returns sorted list of active clients
*/
if (isset($_GET['get_active_clients'])) {
$client_sql = mysqli_query(
$mysqli,
"SELECT client_id, client_name FROM clients
WHERE client_archived_at IS NULL
ORDER BY client_accessed_at DESC"
);
while ($row = mysqli_fetch_array($client_sql)) {
$response['clients'][] = $row;
}
echo json_encode($response);
}
/*
* Returns ordered list of active contacts for a specified client
*/
if (isset($_GET['get_client_contacts'])) {
$client_id = intval($_GET['client_id']);
$contact_sql = mysqli_query(
$mysqli,
"SELECT contact_id, contact_name, contact_primary, contact_important, contact_technical FROM contacts
WHERE contacts.contact_archived_at IS NULL AND contact_client_id = $client_id
ORDER BY contact_primary DESC, contact_technical DESC, contact_important DESC, contact_name"
);
while ($row = mysqli_fetch_array($contact_sql)) {
$response['contacts'][] = $row;
}
echo json_encode($response);
}
/*
* NEW TOTP getter for client login/passwords page
* When provided with a login ID, checks permissions and returns the 6-digit code
*/
if (isset($_GET['get_totp_token_via_id'])) {
validateTechRole();
$login_id = intval($_GET['login_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']);
$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)"));
$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);
}
}
if (isset($_GET['get_readable_pass'])) {
echo json_encode(GenerateReadablePassword(4));
}

View File

@@ -2,15 +2,23 @@
// Variable assignment from POST (or: blank/from DB is updating)
if (isset($_POST['asset_name'])) {
$name = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_name'])));
$name = sanitizeInput($_POST['asset_name']);
} elseif (isset($asset_row) && isset($asset_row['asset_name'])) {
$name = $asset_row['asset_name'];
} else {
$name = '';
}
if (isset($_POST['asset_description'])) {
$description = sanitizeInput($_POST['asset_description']);
} elseif (isset($asset_row) && isset($asset_row['asset_description'])) {
$description = $asset_row['asset_description'];
} else {
$description = '';
}
if (isset($_POST['asset_type'])) {
$type = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_type'])));
$type = sanitizeInput($_POST['asset_type']);
} elseif (isset($asset_row) && isset($asset_row['asset_type'])) {
$type = $asset_row['asset_type'];
} else {
@@ -18,14 +26,14 @@ if (isset($_POST['asset_type'])) {
}
if (isset($_POST['asset_make'])) {
$make = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_make'])));
$make = sanitizeInput($_POST['asset_make']);
} elseif (isset($asset_row) && isset($asset_row['asset_make'])) {
$make = $asset_row['asset_make'];
} else {
$make = '';
}
if (isset($_POST['asset_model'])) {
$model = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_model'])));
$model = sanitizeInput($_POST['asset_model']);
} elseif (isset($asset_row) && isset($asset_row['asset_model'])) {
$model = $asset_row['asset_model'];
} else {
@@ -33,7 +41,7 @@ if (isset($_POST['asset_model'])) {
}
if (isset($_POST['asset_serial'])) {
$serial = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_serial'])));
$serial = sanitizeInput($_POST['asset_serial']);
} elseif (isset($asset_row) && isset($asset_row['asset_serial'])) {
$serial = $asset_row['asset_serial'];
} else {
@@ -41,7 +49,7 @@ if (isset($_POST['asset_serial'])) {
}
if (isset($_POST['asset_os'])) {
$os = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_os'])));
$os = sanitizeInput($_POST['asset_os']);
} elseif (isset($asset_row) && isset($asset_row['asset_os'])) {
$os = $asset_row['asset_os'];
} else {
@@ -49,23 +57,31 @@ if (isset($_POST['asset_os'])) {
}
if (isset($_POST['asset_ip'])) {
$aip = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_ip'])));
} elseif (isset($asset_row) && isset($asset_row['asset_ip'])) {
$aip = $asset_row['asset_ip'];
$ip = sanitizeInput($_POST['asset_ip']);
} elseif (isset($asset_row) && isset($asset_row['interface_ip'])) {
$ip = $asset_row['interface_ip'];
} else {
$aip = '';
$ip = '';
}
if (isset($_POST['asset_mac'])) {
$mac = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_mac'])));
} elseif (isset($asset_row) && isset($asset_row['asset_mac'])) {
$mac = $asset_row['asset_mac'];
$mac = sanitizeInput($_POST['asset_mac']);
} elseif (isset($asset_row) && isset($asset_row['interface_mac'])) {
$mac = $asset_row['interface_mac'];
} else {
$mac = '';
}
if (isset($_POST['asset_uri'])) {
$uri = sanitizeInput($_POST['asset_uri']);
} elseif (isset($asset_row) && isset($asset_row['asset_uri'])) {
$uri = $asset_row['asset_uri'];
} else {
$uri = '';
}
if (isset($_POST['asset_status'])) {
$status = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_status'])));
$status = sanitizeInput($_POST['asset_status']);
} elseif (isset($asset_row) && isset($asset_row['asset_status'])) {
$status = $asset_row['asset_status'];
} else {
@@ -73,31 +89,31 @@ if (isset($_POST['asset_status'])) {
}
if (isset($_POST['asset_purchase_date']) && !empty($_POST['asset_purchase_date'])) {
$purchase_date = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_purchase_date'])));
$purchase_date = "'" . sanitizeInput($_POST['asset_purchase_date']) . "'";
} elseif (isset($asset_row) && isset($asset_row['asset_purchase_date'])) {
$purchase_date = $asset_row['asset_purchase_date'];
$purchase_date = "'" . $asset_row['asset_purchase_date'] . "'";
} else {
$purchase_date = "0000-00-00";
$purchase_date = "NULL";
}
if (isset($_POST['asset_warranty_expire']) && !empty($_POST['asset_warranty_expire'])) {
$warranty_expire = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_warranty_expire'])));
$warranty_expire = "'" . sanitizeInput($_POST['asset_warranty_expire']) . "'";
} elseif (isset($asset_row) && isset($asset_row['asset_warranty_expire'])) {
$warranty_expire = $asset_row['asset_warranty_expire'];
$warranty_expire = "'" . $asset_row['asset_warranty_expire'] . "'";
} else {
$warranty_expire = "0000-00-00";
$warranty_expire = "NULL";
}
if (isset($_POST['asset_install_date']) && !empty($_POST['asset_install_date'])) {
$install_date = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_install_date'])));
$install_date = "'" . sanitizeInput($_POST['asset_install_date']) . "'";
} elseif (isset($asset_row) && isset($asset_row['asset_install_date'])) {
$install_date = $asset_row['asset_install_date'];
$install_date = "'" . $asset_row['asset_install_date'] . "'";
} else {
$install_date = "0000-00-00";
$install_date = "NULL";
}
if (isset($_POST['asset_notes'])) {
$notes = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['asset_notes'])));
$notes = sanitizeInput($_POST['asset_notes']);
} elseif (isset($asset_row) && isset($asset_row['asset_notes'])) {
$notes = $asset_row['asset_notes'];
} else {
@@ -130,8 +146,8 @@ if (isset($_POST['asset_contact_id'])) {
if (isset($_POST['asset_network_id'])) {
$network = intval($_POST['asset_network_id']);
} elseif (isset($asset_row) && isset($asset_row['asset_network_id'])) {
$network = $asset_row['asset_network_id'];
} elseif (isset($asset_row) && isset($asset_row['interface_network_id'])) {
$network = $asset_row['interface_network_id'];
} else {
$network = '0';
}

View File

@@ -1,26 +1,33 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_post_method.php');
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse POST info
require_once('asset_model.php');
require_once 'asset_model.php';
// Default
$insert_id = false;
if (!empty($name) && !empty($client_id)) {
// Insert into Database
$insert_sql = mysqli_query($mysqli, "INSERT INTO assets SET asset_name = '$name', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_ip = '$aip', asset_mac = '$mac', asset_status = '$status', asset_location_id = $location, asset_vendor_id = $vendor, asset_contact_id = $contact, asset_purchase_date = '$purchase_date', asset_warranty_expire = '$warranty_expire', asset_install_date = '$install_date', asset_notes = '$notes', asset_created_at = NOW(), asset_network_id = $network, asset_client_id = $client_id, company_id = '$company_id'");
$insert_sql = mysqli_query($mysqli, "INSERT INTO assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_uri = '$uri', asset_status = '$status', asset_location_id = $location, asset_vendor_id = $vendor, asset_contact_id = $contact, asset_purchase_date = $purchase_date, asset_warranty_expire = $warranty_expire, asset_install_date = $install_date, asset_notes = '$notes', asset_client_id = $client_id");
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);
//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Asset', log_action = 'Created', log_description = '$name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_client_id = '$client_id', company_id = $company_id");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Success', log_description = 'Created asset $name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_client_id = '$client_id', company_id = $company_id");
// Add Primary Interface
mysqli_query($mysqli,"INSERT INTO asset_interfaces SET interface_name = 'Primary', interface_mac = '$mac', interface_ip = '$ip', interface_port = 'eth0', interface_primary = 1, interface_network_id = $network, interface_asset_id = $insert_id");
// Logging
logAction("Asset", "Create", "$name via API ($api_key_name)", $client_id, $insert_id);
logAction("API", "Success", "Created asset $name via API ($api_key_name)", $client_id);
}
}
// Output
require_once('../create_output.php');
require_once '../create_output.php';

View File

@@ -1,7 +1,9 @@
<?php
require_once('../validate_api_key.php');
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
require_once('../require_post_method.php');
// Parse ID
$asset_id = intval($_POST['asset_id']);
@@ -10,19 +12,23 @@ $asset_id = intval($_POST['asset_id']);
$delete_count = false;
if (!empty($asset_id)) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_id = $asset_id AND asset_client_id = $client_id AND company_id = '$company_id' LIMIT 1"));
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_id = $asset_id AND asset_client_id = $client_id LIMIT 1"));
$asset_name = $row['asset_name'];
$delete_sql = mysqli_query($mysqli, "DELETE FROM assets WHERE asset_id = $asset_id AND asset_client_id = $client_id AND company_id = '$company_id' LIMIT 1");
$delete_sql = mysqli_query($mysqli, "DELETE FROM assets WHERE asset_id = $asset_id AND asset_client_id = $client_id LIMIT 1");
// Delete Interfaces
mysqli_query($mysqli,"DELETE FROM asset_interfaces WHERE interface_asset_id = $asset_id");
// Check delete & get affected rows
if ($delete_sql && !empty($asset_name)) {
$delete_count = mysqli_affected_rows($mysqli);
//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Asset', log_action = 'Deleted', log_description = '$asset_name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client_id, company_id = $company_id");
// Logging
logAction("Asset", "Delete", "$asset_name via API ($api_key_name)", $client_id);
}
}
// Output
require_once('../delete_output.php');
require_once '../delete_output.php';

View File

@@ -1,41 +1,49 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Asset via ID (single)
if (isset($_GET['asset_id'])) {
$id = intval($_GET['asset_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_id = '$id' AND asset_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_id = $id AND asset_client_id LIKE '$client_id'");
} elseif (isset($_GET['asset_type'])) {
// Asset query via type
$type = mysqli_real_escape_string($mysqli, ucfirst($_GET['asset_type']));
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_type = '$type' AND asset_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_type = '$type' AND asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['asset_name'])) {
// Asset query via name
$name = mysqli_real_escape_string($mysqli, $_GET['asset_name']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_name = '$name' AND asset_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_name = '$name' AND asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['asset_serial'])) {
// Asset query via serial
$serial = mysqli_real_escape_string($mysqli, $_GET['asset_serial']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_serial = '$serial' AND asset_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_serial = '$serial' AND asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['client_id'])) {
// Asset query via client ID
} elseif (isset($_GET['asset_mac'])) {
// Asset query via mac
$mac = mysqli_real_escape_string($mysqli, $_GET['asset_mac']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1 WHERE interface_mac = '$mac' AND asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
}
} elseif (isset($_GET['asset_uri'])) {
// Asset query via uri
$uri = mysqli_real_escape_string($mysqli, $_GET['asset_uri']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_uri = '$uri' AND asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
// All assets
else {
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['asset_uri_2'])) {
// Asset query via uri2
$uri2 = mysqli_real_escape_string($mysqli, $_GET['asset_uri']);
$sql = mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_uri_2 = '$uri2' AND asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
}else {
// All assets (by client ID or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM assets LEFT JOIN asset_interfaces ON interface_asset_id = asset_id AND interface_primary = 1 WHERE asset_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,7 +1,9 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_post_method.php');
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse ID
$asset_id = intval($_POST['asset_id']);
@@ -11,22 +13,27 @@ $update_count = false;
if (!empty($asset_id)) {
$asset_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_id = '$asset_id' AND asset_client_id = $client_id AND company_id = '$company_id' LIMIT 1"));
$asset_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM assets WHERE asset_id = '$asset_id' AND asset_client_id = $client_id LIMIT 1"));
// Variable assignment from POST - assigning the current database value if a value is not provided
require_once('asset_model.php');
require_once 'asset_model.php';
$update_sql = mysqli_query($mysqli, "UPDATE assets SET asset_name = '$name', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_ip = '$aip', asset_mac = '$mac', asset_status = '$status', asset_location_id = $location, asset_vendor_id = $vendor, asset_contact_id = $contact, asset_purchase_date = '$purchase_date', asset_warranty_expire = '$warranty_expire', asset_install_date = '$install_date', asset_notes = '$notes', asset_updated_at = NOW(), asset_network_id = $network WHERE asset_id = $asset_id AND asset_client_id = $client_id AND company_id = '$company_id' LIMIT 1");
$update_sql = mysqli_query($mysqli, "UPDATE assets SET asset_name = '$name', asset_description = '$description', asset_type = '$type', asset_make = '$make', asset_model = '$model', asset_serial = '$serial', asset_os = '$os', asset_uri = '$uri', asset_status = '$status', asset_location_id = $location, asset_vendor_id = $vendor, asset_contact_id = $contact, asset_purchase_date = $purchase_date, asset_warranty_expire = $warranty_expire, asset_install_date = $install_date, asset_notes = '$notes' WHERE asset_id = $asset_id AND asset_client_id = $client_id LIMIT 1");
// Check insert & get insert ID
if ($update_sql) {
$update_count = mysqli_affected_rows($mysqli);
//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Asset', log_action = 'Updated', log_description = '$name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client_id, company_id = $company_id");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Success', log_description = 'Updated asset $name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client_id, company_id = $company_id");
// Update Primary Interface
mysqli_query($mysqli,"UPDATE asset_interfaces SET interface_mac = '$mac', interface_ip = '$ip', interface_network_id = $network WHERE interface_asset_id = $asset_id AND interface_primary = 1");
// Logging
logAction("Asset", "Edit", "$name via API ($api_key_name)", $client_id);
logAction("API", "Success", "Edited asset $name via API ($api_key_name)", $client_id);
}
}
// Output
require_once('../update_output.php');
require_once '../update_output.php';

View File

@@ -1,29 +1,25 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific certificate via ID (single)
if (isset($_GET['certificate_id'])) {
$id = intval($_GET['certificate_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_id = '$id' AND certificate_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_id = '$id' AND certificate_client_id LIKE '$client_id'");
} elseif (isset($_GET['certificate_name'])) {
// Certificate by name
$name = mysqli_real_escape_string($mysqli, $_GET['certificate_name']);
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_name = '$name' AND certificate_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY certificate_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['client_id'])) {
// Certificate via client ID
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_client_id = '$client_id' AND company_id = '$company_id' ORDER BY certificate_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_name = '$name' AND certificate_client_id LIKE '$client_id' ORDER BY certificate_id LIMIT $limit OFFSET $offset");
} else {
// All certificates
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY certificate_id LIMIT $limit OFFSET $offset");
// All certificates (by client ID or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM certificates WHERE certificate_client_id LIKE '$client_id' ORDER BY certificate_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -0,0 +1,83 @@
<?php
// Variable assignment from POST (or: blank/from DB is updating)
if (isset($_POST['client_name'])) {
$name = sanitizeInput($_POST['client_name']);
} elseif ($client_row) {
$name = $client_row['client_name'];
} else {
$name = '';
}
if (isset($_POST['client_type'])) {
$type = sanitizeInput($_POST['client_type']);
} elseif ($client_row) {
$type = $client_row['client_type'];
} else {
$type = '';
}
if (isset($_POST['client_website'])) {
$website = preg_replace("(^https?://)", "", sanitizeInput($_POST['client_website']));
} elseif ($client_row) {
$website = $client_row['client_website'];
} else {
$website = '';
}
if (isset($_POST['client_referral'])) {
$referral = sanitizeInput($_POST['client_referral']);
} elseif ($client_row) {
$referral = $client_row['client_referral'];
} else {
$referral = '';
}
if (isset($_POST['client_rate'])) {
$rate = floatval($_POST['client_rate']);
} elseif ($client_row) {
$rate = $client_row['client_rate'];
} else {
$rate = '';
}
if (isset($_POST['client_currency_code'])) {
$currency_code = sanitizeInput($_POST['client_currency_code']);
} elseif ($client_row) {
$currency_code = $client_row['client_currency_code'];
} else {
$currency_code = '';
}
if (isset($_POST['client_net_terms'])) {
$net_terms = intval($_POST['client_net_terms']);
} elseif ($client_row) {
$net_terms = $client_row['client_net_terms'];
} else {
$net_terms = '';
}
if (isset($_POST['client_tax_id_number'])) {
$tax_id_number = sanitizeInput($_POST['client_tax_id_number']);
} elseif ($client_row) {
$tax_id_number = $client_row['client_tax_id_number'];
} else {
$tax_id_number = '';
}
if (isset($_POST['client_is_lead'])) {
$lead = intval($_POST['client_is_lead']);
} elseif ($client_row) {
$lead = $client_row['client_is_lead'];
} else {
$lead = 0; // Default: Not a lead
}
if (isset($_POST['client_notes'])) {
$notes = sanitizeInput($_POST['client_notes']);
} elseif ($client_row) {
$notes = $client_row['client_notes'];
} else {
$notes = '';
}

32
api/v1/clients/create.php Normal file
View File

@@ -0,0 +1,32 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse Info
require_once 'client_model.php';
// Default
$insert_id = false;
// To add a client, we just need a name and an "ANY CLIENT" API key
if (!empty($name) && $client_id == 0) {
// Insert client
$insert_sql = mysqli_query($mysqli, "INSERT INTO clients SET client_name = '$name', client_type = '$type', client_website = '$website', client_referral = '$referral', client_rate = $rate, client_currency_code = '$currency_code', client_net_terms = $net_terms, client_tax_id_number = '$tax_id_number', client_lead = $lead, client_notes = '$notes', client_accessed_at = NOW()");
// Check insert & get insert ID
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);
// Logging
logAction("Client", "Create", "$name via API ($api_key_name)", $insert_id);
logAction("API", "Success", "Created client $name via API ($api_key_name)", $insert_id);
}
}
// Output
require_once '../create_output.php';

View File

@@ -1,24 +1,19 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
// Specific client via ID (single)
if (isset($_GET['client_id'])) {
$id = intval($_GET['client_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_id = '$id' AND client_id LIKE '$client_id' AND company_id = '$company_id'");
} elseif (isset($_GET['client_name'])) {
// Specific client via name (single)
require_once '../require_get_method.php';
// Specific client via name (single)
if (isset($_GET['client_name'])) {
$name = mysqli_real_escape_string($mysqli, $_GET['client_name']);
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_name = '$name' AND client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_name = '$name' AND client_id LIKE '$client_id'");
} else {
// All clients
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY client_id LIMIT $limit OFFSET $offset");
// All clients (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE client_id LIKE '$client_id' ORDER BY client_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -3,7 +3,7 @@ define('number_regex', '/[^0-9]/');
// Variable assignment from POST (or: blank/from DB is updating)
if (isset($_POST['contact_name'])) {
$name = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['contact_name'])));
$name = sanitizeInput($_POST['contact_name']);
} elseif ($contact_row) {
$name = $contact_row['contact_name'];
} else {
@@ -11,7 +11,7 @@ if (isset($_POST['contact_name'])) {
}
if (isset($_POST['contact_title'])) {
$title = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['contact_title'])));
$title = sanitizeInput($_POST['contact_title']);
} elseif ($contact_row) {
$title = $contact_row['contact_title'];
} else {
@@ -19,7 +19,7 @@ if (isset($_POST['contact_title'])) {
}
if (isset($_POST['contact_department'])) {
$department = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['contact_department'])));
$department = sanitizeInput($_POST['contact_department']);
} elseif ($contact_row) {
$department = $contact_row['contact_department'];
} else {
@@ -27,7 +27,7 @@ if (isset($_POST['contact_department'])) {
}
if (isset($_POST['contact_email'])) {
$email = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['contact_email'])));
$email = sanitizeInput($_POST['contact_email']);
} elseif ($contact_row) {
$email = $contact_row['contact_email'];
} else {
@@ -59,19 +59,19 @@ if (isset($_POST['contact_mobile'])) {
}
if (isset($_POST['contact_notes'])) {
$notes = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['contact_notes'])));
$notes = sanitizeInput($_POST['contact_notes']);
} elseif ($contact_row) {
$notes = $contact_row['contact_notes'];
} else {
$notes = '';
}
if (isset($_POST['contact_auth_method'])) {
$auth_method = trim(strip_tags(mysqli_real_escape_string($mysqli, $_POST['contact_auth_method'])));
if (isset($_POST['contact_primary'])) {
$primary = intval($_POST['contact_primary']);
} elseif ($contact_row) {
$auth_method = $contact_row['contact_auth_method'];
$primary = $contact_row['contact_primary'];
} else {
$auth_method = '';
$primary = '0';
}
if (isset($_POST['contact_important'])) {

View File

@@ -1,10 +1,13 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_post_method.php');
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse Info
require_once('contact_model.php');
require_once 'contact_model.php';
// Default
$insert_id = false;
@@ -17,18 +20,20 @@ if (!empty($name) && !empty($email) && !empty($client_id)) {
if (mysqli_num_rows($email_duplication_sql) == 0) {
// Insert contact
$insert_sql = mysqli_query($mysqli, "INSERT INTO contacts SET contact_name = '$name', contact_title = '$title', contact_department = '$department', contact_email = '$email', contact_phone = '$phone', contact_extension = '$extension', contact_mobile = '$mobile', contact_notes = '$notes', contact_auth_method = '$auth_method', contact_important = '$important', contact_billing = '$billing', contact_technical = '$technical', contact_created_at = NOW(), contact_location_id = $location_id, contact_client_id = $client_id, company_id = $company_id");
$insert_sql = mysqli_query($mysqli, "INSERT INTO contacts SET contact_name = '$name', contact_title = '$title', contact_department = '$department', contact_email = '$email', contact_phone = '$phone', contact_extension = '$extension', contact_mobile = '$mobile', contact_notes = '$notes', contact_primary = '$primary', contact_important = '$important', contact_billing = '$billing', contact_technical = '$technical', contact_location_id = $location_id, contact_client_id = $client_id");
// Check insert & get insert ID
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);
//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Contact', log_action = 'Created', log_description = '$name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_client_id = $client_id, company_id = $company_id");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Success', log_description = 'Created contact $name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_client_id = $client_id, company_id = $company_id");
// Logging
logAction("Contact", "Create", "$name via API ($api_key_name)", $client_id, $insert_id);
logAction("API", "Success", "Created contact $name via API ($api_key_name)", $client_id);
}
}
}
// Output
require_once('../create_output.php');
require_once '../create_output.php';

View File

@@ -1,7 +1,9 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_post_method.php');
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse ID
$contact_id = intval($_POST['contact_id']);
@@ -10,19 +12,20 @@ $contact_id = intval($_POST['contact_id']);
$delete_count = false;
if (!empty($contact_id)) {
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_id = $contact_id AND contact_client_id = $client_id AND company_id = '$company_id' LIMIT 1"));
$row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_id = $contact_id AND contact_client_id = $client_id LIMIT 1"));
$contact_name = $row['contact_name'];
$delete_sql = mysqli_query($mysqli, "DELETE FROM contacts WHERE contact_id = $contact_id AND contact_client_id = $client_id AND company_id = '$company_id' LIMIT 1");
$delete_sql = mysqli_query($mysqli, "DELETE FROM contacts WHERE contact_id = $contact_id AND contact_client_id = $client_id LIMIT 1");
// Check delete & get affected rows
if ($delete_sql && !empty($contact_name)) {
$delete_count = mysqli_affected_rows($mysqli);
//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Contact', log_action = 'Deleted', log_description = '$contact_name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client_id, company_id = $company_id");
// Logging
logAction("Contact", "Delete", "$contact_name via API ($api_key_name)", $client_id);
}
}
// Output
require_once('../delete_output.php');
require_once '../delete_output.php';

View File

@@ -1,24 +1,30 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific contact via ID (single)
if (isset($_GET['contact_id'])) {
$id = intval($_GET['contact_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_id = '$id' AND contact_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_id = '$id' AND contact_client_id LIKE '$client_id'");
} elseif (isset($_GET['contact_email'])) {
// Specific contact via email (single)
$email = mysqli_real_escape_string($mysqli, $_GET['contact_email']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$email' AND contact_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_email = '$email' AND contact_client_id LIKE '$client_id'");
} elseif (isset($_GET['contact_phone_or_mobile'])) {
// Specific contact via phone number or mobile (single)
$phone_or_mob = mysqli_real_escape_string($mysqli, $_GET['contact_phone_or_mobile']);
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_mobile = '$phone_or_mob' OR contact_phone = '$phone_or_mob' AND contact_client_id LIKE '$client_id' LIMIT 1");
} else {
// All contacts
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY contact_id LIMIT $limit OFFSET $offset");
// All contacts (by client ID, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_client_id LIKE '$client_id' ORDER BY contact_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,7 +1,9 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_post_method.php');
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse Info
$contact_id = intval($_POST['contact_id']);
@@ -11,22 +13,23 @@ $update_count = false;
if (!empty($contact_id)) {
$contact_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_id = '$contact_id' AND contact_client_id = $client_id AND company_id = '$company_id' LIMIT 1"));
$contact_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM contacts WHERE contact_id = '$contact_id' AND contact_client_id = $client_id LIMIT 1"));
// Variable assignment from POST - assigning the current database value if a value is not provided
require_once('contact_model.php');
require_once 'contact_model.php';
$update_sql = mysqli_query($mysqli, "UPDATE contacts SET contact_name = '$name', contact_title = '$title', contact_department = '$department', contact_email = '$email', contact_phone = '$phone', contact_extension = '$extension', contact_mobile = '$mobile', contact_notes = '$notes', contact_auth_method = '$auth_method', contact_important = '$important', contact_billing = '$billing', contact_technical = '$technical', contact_updated_at = NOW(), contact_location_id = $location_id, contact_client_id = $client_id, company_id = $company_id WHERE contact_id = $contact_id LIMIT 1");
$update_sql = mysqli_query($mysqli, "UPDATE contacts SET contact_name = '$name', contact_title = '$title', contact_department = '$department', contact_email = '$email', contact_phone = '$phone', contact_extension = '$extension', contact_mobile = '$mobile', contact_notes = '$notes', contact_primary = '$primary', contact_important = '$important', contact_billing = '$billing', contact_technical = '$technical', contact_location_id = $location_id, contact_client_id = $client_id WHERE contact_id = $contact_id LIMIT 1");
// Check insert & get insert ID
if ($update_sql) {
$update_count = mysqli_affected_rows($mysqli);
//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Contact', log_action = 'Updated', log_description = '$name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_client_id = $client_id, company_id = $company_id");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Success', log_description = 'Updated contact $name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW(), log_client_id = $client_id, company_id = $company_id");
// Logging
logAction("Contact", "Edit", "$name via API ($api_key_name)", $client_id, $contact_id);
logAction("API", "Success", "Edited contact $name via API ($api_key_name)", $client_id);
}
}
// Output
require_once('../update_output.php');
require_once '../update_output.php';

View File

@@ -0,0 +1,30 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse info
require_once 'credential_model.php';
// Default
$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");
// Check insert & get insert ID
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);
// Logging
logAction("Credential", "Create", "$name via API ($api_key_name)", $client_id, $insert_id);
logAction("API", "Success", "Created credential $name via API ($api_key_name)", $client_id);
}
}
// Output
require_once '../create_output.php';

View File

@@ -0,0 +1,120 @@
<?php
// Variable assignment from POST (or: blank/from DB is updating)
$api_key_decrypt_password = '';
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'];
} 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'];
} 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'];
} 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'];
} else {
$uri_2 = '';
}
if (isset($_POST['login_username'])) {
$username = $_POST['login_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'];
} else {
$username = '';
}
if (isset($_POST['login_password'])) {
$password = $_POST['login_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'];
$password_changed = false;
} else {
$password = '';
$password_changed = false;
}
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'];
} 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'];
} 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'];
} 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'];
} 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'];
} 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'];
} 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'];
} else {
$software_id = '';
}

View File

@@ -0,0 +1,59 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Defaults
$sql = false;
$api_key_decrypt_password = '';
if (isset($_GET['api_key_decrypt_password'])) {
$api_key_decrypt_password = $_GET['api_key_decrypt_password']; // No sanitization
}
// Specific credential/login via ID (single)
if (isset($_GET['login_id']) && !empty($api_key_decrypt_password)) {
$id = intval($_GET['login_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = '$id' AND login_client_id LIKE '$client_id' LIMIT 1");
} elseif (!empty($api_key_decrypt_password)) {
// All credentials ("logins")
$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_client_id LIKE '$client_id' ORDER BY login_id LIMIT $limit OFFSET $offset");
}
// Output - Not using the standard API read_output.php
// Usually we just output what is in the database, but credentials need to be decrypted first.
if ($sql && mysqli_num_rows($sql) > 0) {
$return_arr['success'] = "True";
$return_arr['count'] = mysqli_num_rows($sql);
$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);
$return_arr['data'][] = $row;
}
echo json_encode($return_arr);
exit();
}
else {
$return_arr['success'] = "False";
$return_arr['message'] = "No resource (for this client and company) with the specified parameter(s).";
// Log any database/schema related errors to the PHP Error log
if (mysqli_error($mysqli)) {
error_log("API Database Error: " . mysqli_error($mysqli));
}
echo json_encode($return_arr);
exit();
}

View File

@@ -0,0 +1,38 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse ID
$login_id = intval($_POST['login_id']);
// Default
$update_count = false;
if (!empty($_POST['api_key_decrypt_password']) && !empty($login_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"));
// 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");
// 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");
}
// Logging
logAction("Credential", "Edit", "$name via API ($api_key_name)", $client_id, $login_id);
logAction("API", "Success", "Updated credential $name via API ($api_key_name)", $client_id);
}
}
// Output
require_once '../update_output.php';

View File

@@ -0,0 +1,33 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse info
require_once 'document_model.php';
// Default
$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");
// 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);
}
}
// Output
require_once '../create_output.php';

View File

@@ -0,0 +1,43 @@
<?php
// Variable assignment from POST (or: blank/from DB is updating)
if (isset($_POST['document_name'])) {
$name = sanitizeInput($_POST['document_name']);
} elseif (isset($document_row) && isset($document_row['document_name'])) {
$name = $document_row['document_name'];
} else {
$name = '';
}
if (isset($_POST['document_description'])) {
$description = sanitizeInput($_POST['document_description']);
} elseif (isset($document_row) && isset($document_row['document_description'])) {
$description = $document_row['document_description'];
} else {
$description = '';
}
if (isset($_POST['document_content'])) {
$content = mysqli_real_escape_string($mysqli, $_POST['document_content']);
} elseif (isset($document_row) && isset($document_row['document_content'])) {
$content = $document_row['document_content'];
} else {
$content = '';
}
// Raw content (used for FULL INDEX searching)
if (isset($_POST['document_content'])) {
$content_raw = sanitizeInput($_POST['document_name'] . $_POST['document_description'] . " " . str_replace("<", " <", $_POST['document_content']));
} elseif (isset($document_row) && isset($document_row['document_content_raw'])) {
$content_raw = $document_row['document_content_raw'];
} else {
$content_raw = '';
}
if (isset($_POST['document_folder_id'])) {
$folder = intval($_POST['document_content']);
} elseif (isset($document_row) && isset($document_row['document_folder_id'])) {
$folder = intval($document_row['document_folder_id']);
} else {
$folder = 0;
}

View File

@@ -1,19 +1,20 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
if (isset($_GET['document_id'])) {
// Document via ID (single)
$id = intval($_GET['document_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_id = '$id' AND document_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_id = '$id' AND document_client_id LIKE '$client_id'");
} else {
// All documents
$sql = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY document_id LIMIT $limit OFFSET $offset");
// All documents (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM documents WHERE document_client_id LIKE '$client_id' ORDER BY document_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -0,0 +1,60 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Parse ID
$document_id = intval($_POST['document_id']);
// Default
$update_count = false;
if (!empty($document_id)) {
$document_row = mysqli_fetch_assoc(mysqli_query($mysqli, "SELECT * FROM documents WHERE document_id = '$document_id' AND document_client_id = $client_id LIMIT 1"));
// Variable assignment from POST - assigning the current database value if a value is not provided
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");
// 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);
// Override update count to 1 for API to report a success (as we inserted a document, not "updated" an existing row)
$update_count = 1;
}
}
// Output
require_once '../update_output.php';

View File

@@ -1,29 +1,25 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific domain via ID (single)
if (isset($_GET['domain_id'])) {
$id = intval($_GET['domain_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_id = '$id' AND domain_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_id = '$id' AND domain_client_id LIKE '$client_id'");
} elseif (isset($_GET['domain_name'])) {
// Domain by name
$name = mysqli_real_escape_string($mysqli, $_GET['domain_name']);
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$name' AND domain_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['client_id'])) {
// Domain via client ID
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY domain_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_name = '$name' AND domain_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} else {
// All domains
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY domain_id LIMIT $limit OFFSET $offset");
// All domains (by client ID or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM domains WHERE domain_client_id LIKE '$client_id' ORDER BY domain_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,7 +1,9 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Expenses aren't stored against client IDs, so we instead validate the API key is for All Clients
@@ -9,13 +11,14 @@ if (isset($_GET['expense_id']) && $client_id == "%") {
// Expense via ID (single)
$id = intval($_GET['expense_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM expenses WHERE expense_id = '$id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM expenses WHERE expense_id = '$id'");
} elseif ($client_id == "%") {
// All expenses
$sql = mysqli_query($mysqli, "SELECT * FROM expenses WHERE company_id = '$company_id' ORDER BY expense_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM expenses ORDER BY expense_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,19 +1,20 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
if (isset($_GET['invoice_id'])) {
// Invoice via ID (single)
$id = intval($_GET['invoice_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_id = '$id' AND invoice_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_id = '$id' AND invoice_client_id LIKE '$client_id'");
} else {
// All invoices
$sql = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY invoice_id LIMIT $limit OFFSET $offset");
// All invoices (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM invoices WHERE invoice_client_id LIKE '$client_id' ORDER BY invoice_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

20
api/v1/locations/read.php Normal file
View File

@@ -0,0 +1,20 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
if (isset($_GET['location_id'])) {
// Location via ID (single)
$id = intval($_GET['location_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_id = '$id' AND location_client_id LIKE '$client_id'");
} else {
// All locations (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM locations WHERE location_client_id LIKE '$client_id' ORDER BY location_id LIMIT $limit OFFSET $offset");
}
// Output
require_once "../read_output.php";

View File

@@ -1,29 +1,25 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific network via ID (single)
if (isset($_GET['network_id'])) {
$id = intval($_GET['network_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_id = '$id' AND network_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_id = '$id' AND network_client_id LIKE '$client_id'");
} elseif (isset($_GET['network_name'])) {
// Network by name
$name = mysqli_real_escape_string($mysqli, $_GET['network_name']);
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_name = '$name' AND network_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY network_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['client_id'])) {
// Network via client ID
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY network_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_name = '$name' AND network_client_id LIKE '$client_id' ORDER BY network_id LIMIT $limit OFFSET $offset");
} else {
// All networks
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY network_id LIMIT $limit OFFSET $offset");
// All networks (by client ID or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM networks WHERE network_client_id LIKE '$client_id' ORDER BY network_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,7 +1,9 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Payments aren't stored against client IDs, so we instead validate the API key is for All Clients
@@ -10,19 +12,20 @@ if (isset($_GET['payment_id']) && $client_id == "%") {
// Payment via ID (single)
$id = intval($_GET['payment_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM payments WHERE payment_id = '$id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM payments WHERE payment_id = '$id'");
} elseif (isset($_GET['payment_invoice_id']) && $client_id == "%") {
// Payments for an invoice
$id = intval($_GET['payment_invoice_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM payments WHERE payment_invoice_id = '$id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM payments WHERE payment_invoice_id = '$id'");
} elseif ($client_id == "%") {
// All payments
$sql = mysqli_query($mysqli, "SELECT * FROM payments WHERE company_id = '$company_id' ORDER BY payment_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM payments ORDER BY payment_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,21 +1,22 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Products aren't stored against client IDs, so we instead validate the API key is for All Clients
if (isset($_GET['product_id']) && $client_id == "%") {
// product via ID (single)
$id = intval($_GET['product_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM products WHERE product_id = '$id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM products WHERE product_id = '$id'");
} elseif ($client_id == "%") {
// All products
$sql = mysqli_query($mysqli, "SELECT * FROM products WHERE company_id = '$company_id' ORDER BY product_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM products ORDER BY product_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -1,19 +1,20 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
if (isset($_GET['quote_id'])) {
// quote via ID (single)
$id = intval($_GET['quote_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM quotes WHERE quote_id LIKE '$id' AND quote_client_id = '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM quotes WHERE quote_id LIKE '$id' AND quote_client_id = '$client_id'");
} else {
// All quotes
$sql = mysqli_query($mysqli, "SELECT * FROM quotes WHERE quote_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY quote_id LIMIT $limit OFFSET $offset");
// All quotes (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM quotes WHERE quote_client_id LIKE '$client_id' ORDER BY quote_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -9,6 +9,6 @@ if ($_SERVER['REQUEST_METHOD'] !== "POST") {
// Client ID must be specific for INSERT/UPDATE/DELETE queries
// If this API key allows any client, set $client_id to the one specified, else leave it
if ($client_id == 0) {
if ($client_id == 0 && isset($_POST['client_id'])) {
$client_id = intval($_POST['client_id']);
}
}

View File

@@ -1,41 +1,35 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific software via ID (single)
if (isset($_GET['software_id'])) {
$id = intval($_GET['software_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_id = '$id' AND software_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_id = '$id' AND software_client_id LIKE '$client_id'");
} elseif (isset($_GET['software_key'])) {
// Specific software via key
$key = mysqli_real_escape_string($mysqli, $_GET['software_license']);
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_key = '$key' AND software_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_key = '$key' AND software_client_id LIKE '$client_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['software_name'])) {
// Software by name
$name = mysqli_real_escape_string($mysqli, $_GET['software_name']);
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_name = '$name' AND software_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_name = '$name' AND software_client_id LIKE '$client_id' ORDER BY asset_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['software_type'])) {
// Software via type
$type = intval($_GET['software_type']);
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_type = '$type' AND software_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
} elseif (isset($_GET['client_id'])) {
// Software via client ID
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_type = '$type' AND software_client_id LIKE '$client_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
} else {
// All software(s)
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
// All software(s) (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM software WHERE software_client_id LIKE '$client_id' ORDER BY software_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

56
api/v1/tickets/create.php Normal file
View File

@@ -0,0 +1,56 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_post_method.php';
// Ticket-related settings
require_once "../../../get_settings.php";
$sql = mysqli_query($mysqli, "SELECT company_name, company_phone FROM companies WHERE company_id = 1");
$row = mysqli_fetch_array($sql);
$company_name = $row['company_name'];
$company_phone = formatPhoneNumber($row['company_phone']);
// Parse Info
$ticket_row = false; // Creation, not an update
require_once 'ticket_model.php';
// Default
$insert_id = false;
if (!empty($subject)) {
if (!is_int($client_id)) {
$client_id = 0;
}
// If no contact is selected automatically choose the primary contact for the client (if client set)
if ($contact == 0 && $client_id != 0) {
$sql = mysqli_query($mysqli,"SELECT contact_id FROM contacts WHERE contact_client_id = $client_id AND contact_primary = 1");
$row = mysqli_fetch_array($sql);
$contact = intval($row['contact_id']);
}
//Get the next Ticket Number and add 1 for the new ticket number
$ticket_number = $config_ticket_next_number;
$new_config_ticket_next_number = $config_ticket_next_number + 1;
mysqli_query($mysqli,"UPDATE settings SET config_ticket_next_number = $new_config_ticket_next_number WHERE company_id = 1");
// 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");
// Check insert & get insert ID
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);
// Logging
logAction("Ticket", "Create", "Created ticket $config_ticket_prefix$ticket_number $subject via API ($api_key_name)", $client_id, $insert_id);
logAction("API", "Success", "Created ticket $config_ticket_prefix$ticket_number $subject via API ($api_key_name)", $client_id);
}
}
// Output
require_once '../create_output.php';

View File

@@ -1,18 +1,25 @@
<?php
require_once('../validate_api_key.php');
require_once('../require_get_method.php');
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific ticket via ID (single)
if (isset($_GET['ticket_id'])) {
$id = intval($_GET['ticket_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_id = '$id' AND ticket_client_id LIKE '$client_id' AND company_id = '$company_id'");
$sql = mysqli_query(
$mysqli,
"SELECT * FROM tickets
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
WHERE ticket_id = '$id' AND ticket_client_id LIKE '$client_id'"
);
} else {
// All tickets
$sql = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_client_id LIKE '$client_id' AND company_id = '$company_id' ORDER BY ticket_id LIMIT $limit OFFSET $offset");
// All tickets (by client ID if given, or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM tickets WHERE ticket_client_id LIKE '$client_id' ORDER BY ticket_id LIMIT $limit OFFSET $offset");
}
// Output
require_once("../read_output.php");
require_once "../read_output.php";

View File

@@ -0,0 +1,61 @@
<?php
// Variable assignment from POST (or: blank/from DB is updating)
if (isset($_POST['ticket_contact_id'])) {
$contact = intval($_POST['ticket_contact_id']);
} elseif ($ticket_row) {
$contact = $ticket_row['ticket_contact_id'];
} else {
$contact = '0';
}
if (isset($_POST['ticket_subject'])) {
$subject = sanitizeInput($_POST['ticket_subject']);
} elseif ($ticket_row) {
$subject = $ticket_row['ticket_subject'];
} else {
$subject = '';
}
if (isset($_POST['ticket_priority'])) {
$priority = sanitizeInput($_POST['ticket_priority']);
} elseif ($ticket_row) {
$priority = $ticket_row['ticket_priority'];
} else {
$priority = 'Low';
}
if (isset($_POST['ticket_details'])) {
$details = sanitizeInput($_POST['ticket_details']) . "<br>";
} elseif ($ticket_row) {
$details = $ticket_row['ticket_details'];
} else {
$details = '< blank ><br>';
}
if (isset($_POST['ticket_vendor_id'])) {
$vendor_id = intval($_POST['ticket_vendor_id']);
} elseif ($ticket_row) {
$vendor_id = $ticket_row['ticket_vendor_id'];
} else {
$vendor_id = '0';
}
if (isset($_POST['ticket_vendor_ticket_id'])) {
$vendor_ticket_number = intval($_POST['ticket_vendor_ticket_id']);
} elseif ($ticket_row) {
$vendor_ticket_number = $ticket_row['ticket_vendor_ticket_id'];
} else {
$vendor_ticket_number = '0';
}
if (isset($_POST['ticket_assigned_to'])) {
$assigned_to = intval($_POST['ticket_assigned_to']);
} elseif ($ticket_row) {
$assigned_to = $ticket_row['ticket_assigned_to'];
} else {
$assigned_to = '0';
}

View File

@@ -7,8 +7,8 @@
*/
// Includes
require_once(__DIR__ . '../../../functions.php');
require_once(__DIR__ . "../../../config.php");
require_once __DIR__ . '../../../functions.php';
require_once __DIR__ . "../../../config.php";
// JSON header
header('Content-Type: application/json');
@@ -17,8 +17,12 @@ header('Content-Type: application/json');
$_POST = json_decode(file_get_contents('php://input'), true);
// Get IP & UA
$ip = strip_tags(mysqli_real_escape_string($mysqli, getIP()));
$user_agent = strip_tags(mysqli_real_escape_string($mysqli, $_SERVER['HTTP_USER_AGENT']));
$ip = sanitizeInput(getIP());
$user_agent = sanitizeInput($_SERVER['HTTP_USER_AGENT']);
// Temp Added this to work with the new logAction function
$session_ip = $ip;
$session_user_agent = $user_agent;
// Setup return array
$return_arr = array();
@@ -56,15 +60,15 @@ if (!isset($_GET['api_key']) && !isset($_POST['api_key'])) {
// Set API key variable
if (isset($_GET['api_key'])) {
$api_key = $_GET['api_key'];
$api_key = sanitizeInput($_GET['api_key']);
}
if (isset($_POST['api_key'])) {
$api_key = $_POST['api_key'];
$api_key = sanitizeInput($_POST['api_key']);
}
// Validate API key
if (isset($api_key)) {
$api_key = mysqli_real_escape_string($mysqli, $api_key);
$api_key = sanitizeInput($api_key);
$sql = mysqli_query($mysqli, "SELECT * FROM api_keys WHERE api_key_secret = '$api_key' AND api_key_expire > NOW() LIMIT 1");
@@ -72,7 +76,7 @@ if (isset($api_key)) {
if (mysqli_num_rows($sql) !== 1) {
// Invalid Key
header(WORDING_UNAUTHORIZED);
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Failed', log_description = 'Incorrect or expired key', log_ip = '$ip', log_user_agent = '$user_agent', log_created_at = NOW()");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Failed', log_description = 'Incorrect or expired key', log_ip = '$ip', log_user_agent = '$user_agent'");
$return_arr['success'] = "False";
$return_arr['message'] = "Authentication failed. API key is invalid or has expired.";
@@ -88,8 +92,8 @@ if (isset($api_key)) {
// Set client ID, company ID & key name
$row = mysqli_fetch_array($sql);
$api_key_name = htmlentities($row['api_key_name']);
$client_id = $row['api_key_client_id'];
$company_id = $row['company_id'];
$api_key_decrypt_hash = $row['api_key_decrypt_hash']; // No sanitization
$client_id = intval($row['api_key_client_id']);
// Set limit & offset for queries
if (isset($_GET['limit'])) {

19
api/v1/vendors/read.php vendored Normal file
View File

@@ -0,0 +1,19 @@
<?php
require_once '../validate_api_key.php';
require_once '../require_get_method.php';
// Specific vendor via their ID (single)
if (isset($_GET['vendor_id'])) {
$id = intval($_GET['vendor_id']);
$sql = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_id = '$id' AND vendor_client_id LIKE '$client_id'");
} else {
// All Vendors (by client ID or all in general if key permits)
$sql = mysqli_query($mysqli, "SELECT * FROM vendors WHERE vendor_client_id LIKE '$client_id' ORDER BY vendor_id LIMIT $limit OFFSET $offset");
}
// Output
require_once "../read_output.php";

View File

@@ -1,96 +0,0 @@
<?php
/**
* Encode in Base32 based on RFC 4648.
* Requires 20% more space than base64
* Great for case-insensitive filesystems like Windows and URL's (except for = char which can be excluded using the pad option for urls)
*
* @package default
* @author Bryan Ruiz
**/
class Base32Static {
private static $map = array(
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', // 7
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', // 15
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', // 23
'Y', 'Z', '2', '3', '4', '5', '6', '7', // 31
'=' // padding character
);
private static $flippedMap = array(
'A'=>'0', 'B'=>'1', 'C'=>'2', 'D'=>'3', 'E'=>'4', 'F'=>'5', 'G'=>'6', 'H'=>'7',
'I'=>'8', 'J'=>'9', 'K'=>'10', 'L'=>'11', 'M'=>'12', 'N'=>'13', 'O'=>'14', 'P'=>'15',
'Q'=>'16', 'R'=>'17', 'S'=>'18', 'T'=>'19', 'U'=>'20', 'V'=>'21', 'W'=>'22', 'X'=>'23',
'Y'=>'24', 'Z'=>'25', '2'=>'26', '3'=>'27', '4'=>'28', '5'=>'29', '6'=>'30', '7'=>'31'
);
/**
* Use padding false when encoding for urls
*
* @return base32 encoded string
* @author Bryan Ruiz
**/
public static function encode($input, $padding = true) {
if (empty($input)) return "";
$input = str_split($input);
$binaryString = "";
for ($i = 0; $i < count($input); $i++) {
$binaryString .= str_pad(base_convert(ord($input[$i]), 10, 2), 8, '0', STR_PAD_LEFT);
}
$fiveBitBinaryArray = str_split($binaryString, 5);
$base32 = "";
$i=0;
while($i < count($fiveBitBinaryArray)) {
$base32 .= self::$map[base_convert(str_pad($fiveBitBinaryArray[$i], 5, '0'), 2, 10)];
$i++;
}
if ($padding && ($x = strlen($binaryString) % 40) != 0) {
if ($x == 8) $base32 .= str_repeat(self::$map[32], 6);
else if ($x == 16) $base32 .= str_repeat(self::$map[32], 4);
else if ($x == 24) $base32 .= str_repeat(self::$map[32], 3);
else if ($x == 32) $base32 .= self::$map[32];
}
return $base32;
}
public static function decode($input) {
if (empty($input)) return;
$paddingCharCount = substr_count($input, self::$map[32]);
$allowedValues = array(6,4,3,1,0);
if (!in_array($paddingCharCount, $allowedValues)) return false;
for ($i=0; $i<4; $i++){
if ($paddingCharCount == $allowedValues[$i] &&
substr($input, -($allowedValues[$i])) != str_repeat(self::$map[32], $allowedValues[$i])) return false;
}
$input = str_replace('=', '', $input);
$input = str_split($input);
$binaryString = "";
for ($i=0; $i < count($input); $i = $i+8) {
$x = "";
if (!in_array($input[$i], self::$map)) return false;
for ($j=0; $j < 8; $j++) {
$x .= str_pad(base_convert(@self::$flippedMap[@$input[$i + $j]], 10, 2), 5, '0', STR_PAD_LEFT);
}
$eightBits = str_split($x, 8);
for ($z = 0; $z < count($eightBits); $z++) {
$binaryString .= (($y = chr(base_convert($eightBits[$z], 2, 10))) || ord($y) == 48) ? $y:"";
}
}
return $binaryString;
}
}

View File

@@ -1,35 +1,55 @@
<?php require_once("inc_all.php"); ?>
<?php require_once "includes/inc_all.php"; ?>
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="index.html">Dashboard</a>
</li>
<li class="breadcrumb-item active">Blank Page</li>
</ol>
<!-- Breadcrumbs-->
<ol class="breadcrumb">
<li class="breadcrumb-item">
<a href="index.html">Dashboard</a>
</li>
<li class="breadcrumb-item active">Blank Page</li>
</ol>
<!-- Page Content -->
<h1>Blank Page</h1>
<hr>
<p>This is a great starting point for new custom pages.</p>
<!-- Page Content -->
<h1>Blank Page</h1>
<hr>
<p>This is a great starting point for new custom pages.</p>
<?php echo CURRENT_DATABASE_VERSION; ?>
<br>
<?php echo randomString(100); ?>
<br>
<form>
<?php
$timezones = DateTimeZone::listIdentifiers();
echo '<select name="timezone">';
foreach ($timezones as $timezone) {
echo '<option value="' . $timezone . '">' . $timezone . '</option>';
}
echo '</select>';
$start_date = date('Y') . "-10-10";
echo "<H1>$start_date</H1>";
echo "<H2>User Agent</H2>";
echo getUserAgent();
?>
</form>
<br>
<dl>
<dt>Requester</dt>
<dd>Sam Adams</dd>
<dt>Created</dt>
<dd><time datetime="2024-04-11T17:52:30+00:00" title="2024-04-11 13:52" data-datetime="calendar">Today at 13:52</time></dd>
<dt>Last activity</dt>
<dd><time datetime="2024-04-11T18:08:55+00:00" title="2024-04-11 14:08" data-datetime="calendar">Today at 14:08</time></dd>
</dl>
<?php echo randomString(100); ?>
<br>
<textarea class="tinymceTest"></textarea>
<textarea class="tinymce"></textarea>
<textarea class="tinymceTicket"></textarea>
<?php
// show the current Date and Time
$date_time = date('Y-m-d H:i:s');
echo "Current Date and Time: <strong>$date_time</strong>";
?>
<script>toastr.success('Have Fun Wozz!!')</script>
<?php require_once("footer.php"); ?>
<?php require_once "includes/footer.php";

113
budget.php Normal file
View File

@@ -0,0 +1,113 @@
<?php
require_once "includes/inc_all.php";
// Perms
enforceUserPermission('module_financial');
// Fetch categories
$query = "SELECT category_id, category_name FROM categories WHERE category_type ='Expense' AND category_archived_at IS NULL";
$result = mysqli_query($mysqli, $query);
$categories = [];
while($row = mysqli_fetch_assoc($result)) {
$categories[] = $row;
}
// Fetch years with budget
$query = "SELECT DISTINCT budget_year FROM budget ORDER BY budget_year ASC";
$result = mysqli_query($mysqli, $query);
$years = [];
while ($row = mysqli_fetch_assoc($result)) {
$years[] = $row['budget_year'];
}
// Fetch current year budgets
$currentYear = date("Y");
if (isset($_GET['year'])) {
$currentYear = intval($_GET['year']);
}
$query = "SELECT * FROM budget WHERE budget_year = $currentYear";
$result = mysqli_query($mysqli, $query);
$budgets = [];
while ($row = mysqli_fetch_assoc($result)) {
$budgets[] = $row;
}
$months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
$columnTotals = array_fill(0, 12, 0);
$grandTotal = 0;
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-balance-scale mr-2"></i>Budget for <span id="currentYear"><?php echo $currentYear; ?></span></h3>
<div class="card-tools">
<a href="budget_edit.php" class="btn btn-primary">
<i class="fas fa-edit mr-2"></i>Edit Budget
</a>
</div>
</div>
<div class="card-body">
<form id="yearForm" method="GET" action="budget.php">
<div class="form-group">
<select class="form-control" name="year" id="yearSelect" onchange="submit();">
<?php foreach ($years as $year): ?>
<option value="<?php echo $year; ?>" <?php if ($year == $currentYear) { echo 'selected'; } ?>><?php echo $year; ?></option>
<?php endforeach; ?>
</select>
</div>
</form>
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Expense</th>
<?php foreach ($months as $month): ?>
<th><?php echo $month; ?></th>
<?php endforeach; ?>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($categories as $category): ?>
<tr>
<td><?php echo nullable_htmlentities($category['category_name']); ?></td>
<?php
$rowTotal = 0;
foreach ($months as $index => $month):
$amount = getBudgetAmount($budgets, $category['category_id'], $index + 1);
$rowTotal += $amount;
$columnTotals[$index] += $amount;
?>
<td><?php echo $amount; ?></td>
<?php endforeach; ?>
<td><?php echo $rowTotal; ?></td>
</tr>
<?php
$grandTotal += $rowTotal;
endforeach; ?>
</tbody>
<tfoot>
<tr>
<th>Total</th>
<?php foreach ($columnTotals as $total): ?>
<th><?php echo $total; ?></th>
<?php endforeach; ?>
<th><?php echo $grandTotal; ?></th>
</tr>
</tfoot>
</table>
</div>
<?php
function getBudgetAmount($budgets, $categoryId, $month) {
foreach ($budgets as $budget) {
if ($budget['budget_category_id'] == $categoryId && $budget['budget_month'] == $month) {
return intval($budget['budget_amount']);
}
}
return 0;
}
require_once "includes/footer.php";
?>

114
budget_edit.php Normal file
View File

@@ -0,0 +1,114 @@
<?php
require_once "includes/inc_all.php";
enforceUserPermission('module_financial', 2);
// Fetch categories
$query = "SELECT category_id, category_name FROM categories WHERE category_type ='Expense' AND category_archived_at IS NULL";
$result = mysqli_query($mysqli, $query);
$categories = [];
while($row = mysqli_fetch_assoc($result)) {
$categories[] = $row;
}
// Fetch current year budgets
$currentYear = date("Y");
if(isset($_GET['year'])) {
$currentYear = intval($_GET['year']);
}
$query = "SELECT * FROM budget WHERE budget_year = $currentYear";
$result = mysqli_query($mysqli, $query);
$budgets = [];
while($row = mysqli_fetch_assoc($result)) {
$budgets[] = $row;
}
$months = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
$columnTotals = array_fill(0, 12, 0);
$grandTotal = 0;
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fas fa-fw fa-balance-scale mr-2"></i>Editing Budget for <span id="currentYear"><?php echo $currentYear; ?></span></h3>
<div class="card-tools">
<a href="budget.php" class="btn btn-default text-dark">
<i class="fas fa-eye mr-2"></i>View Budget
</a>
<button type="submit" name="save_budget" form="budgetForm" class="btn btn-primary"><i class="fas fa-fw fa-check mr-2"></i>Save Budget</button>
<button type="submit" name="delete_budget" form="budgetForm" class="btn btn-danger"><i class="fas fa-fw fa-trash mr-2"></i>Delete Budget</button>
</div>
</div>
<div class="card-body">
<form id="yearForm" method="GET" action="budget.php">
<div class="form-group">
<select class="form-control" name="year" id="yearSelect" onchange="submit();">
<?php for ($i = $currentYear - 10; $i <= $currentYear + 5; $i++): ?>
<option value="<?php echo $i; ?>" <?php if ($i == $currentYear) echo 'selected'; ?>><?php echo $i; ?></option>
<?php endfor; ?>
</select>
</div>
</form>
<form id="budgetForm" method="POST" action="post.php">
<input type="hidden" name="year" value="<?php echo $currentYear; ?>">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<table class="table table-bordered table-striped">
<thead>
<tr>
<th>Expense</th>
<?php foreach ($months as $month): ?>
<th><?php echo $month; ?></th>
<?php endforeach; ?>
<th>Total</th>
</tr>
</thead>
<tbody>
<?php foreach ($categories as $category): ?>
<tr>
<td><?php echo nullable_htmlentities($category['category_name']); ?></td>
<?php
$rowTotal = 0;
foreach ($months as $index => $month):
$amount = getBudgetAmount($budgets, $category['category_id'], $index + 1);
$rowTotal += $amount;
$columnTotals[$index] += $amount;
?>
<td><input type='text' inputmode='numeric' pattern='[0-9]*' class="form-control" name="budget[<?php echo intval($category['category_id']); ?>][<?php echo $index + 1; ?>]" value="<?php echo $amount; ?>"></td>
<?php endforeach; ?>
<td><?php echo $rowTotal; ?></td>
</tr>
<?php
$grandTotal += $rowTotal;
endforeach; ?>
</tbody>
<tfoot>
<tr>
<th>Total</th>
<?php foreach ($columnTotals as $total): ?>
<th><?php echo $total; ?></th>
<?php endforeach; ?>
<th><?php echo $grandTotal; ?></th>
</tr>
</tfoot>
</table>
</form>
</div>
</div>
<?php
function getBudgetAmount($budgets, $categoryId, $month) {
foreach ($budgets as $budget) {
if ($budget['budget_category_id'] == $categoryId && $budget['budget_month'] == $month) {
return intval($budget['budget_amount']);
}
}
return 0;
}
require_once "includes/footer.php";
?>

View File

@@ -1,48 +1,105 @@
<?php
require_once("inc_all.php");
require_once "includes/inc_all.php";
if (isset($_GET['calendar_id'])) {
$calendar_selected_id = intval($_GET['calendar_id']);
}
?>
<link href='plugins/fullcalendar/main.min.css' rel='stylesheet' />
<div id='calendar'></div>
<!-- So that when hovering over a created event it turns into a hand instead of cursor -->
<style>
.fc-event {
cursor: pointer;
}
</style>
<div class="row">
<div class="col-md-3">
<div class="card">
<div class="card-header py-2">
<h3 class="card-title mt-1">Calendars</h3>
<div class="card-tools">
<button type="button" class="btn btn-dark btn-sm" data-toggle="modal" data-target="#addCalendarModal"><i class="fas fa-plus"></i></button>
</div>
</div>
<div class="card-body">
<form>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM calendars");
while ($row = mysqli_fetch_array($sql)) {
$calendar_id = intval($row['calendar_id']);
$calendar_name = nullable_htmlentities($row['calendar_name']);
$calendar_color = nullable_htmlentities($row['calendar_color']);
?>
<div class="form-group">
<i class="fas fa-fw fa-circle mr-2" style="color:<?php echo $calendar_color; ?>;"></i><?php echo $calendar_name; ?>
<button type="button" class="btn btn-link btn-sm float-right" data-toggle="modal" data-target="#editCalendarModal<?php echo $calendar_id; ?>"><i class="fas fa-fw fa-pencil-alt text-secondary"></i></button>
</div>
<?php
require "modals/calendar_edit_modal.php";
}
?>
</form>
</div>
</div>
<div class="card">
<div class="card-header py-2">
<h3 class="card-title mt-1">System Calendars</h3>
<div class="card-tools">
<button type="button" class="btn btn-dark btn-sm"><i class="fas fa-eye"></i></button>
</div>
</div>
<div class="card-body">
</div>
</div>
</div>
<div class="col-md-9">
<div class="card">
<div id='calendar'></div>
</div>
</div>
</div>
<?php
require_once("calendar_event_add_modal.php");
require_once("calendar_add_modal.php");
require_once("category_quick_add_modal.php");
require_once "modals/calendar_event_add_modal.php";
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 WHERE calendars.company_id = $session_company_id");
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = $row['event_id'];
$event_title = htmlentities($row['event_title']);
$event_description = htmlentities($row['event_description']);
$event_start = htmlentities($row['event_start']);
$event_end = htmlentities($row['event_end']);
$event_repeat = htmlentities($row['event_repeat']);
$calendar_id = $row['calendar_id'];
$calendar_name = htmlentities($row['calendar_name']);
$calendar_color = htmlentities($row['calendar_color']);
$client_id = $row['event_client_id'];
require("calendar_event_edit_modal.php");
$event_id = intval($row['event_id']);
$event_title = nullable_htmlentities($row['event_title']);
$event_description = nullable_htmlentities($row['event_description']);
$event_location = nullable_htmlentities($row['event_location']);
$event_start = nullable_htmlentities($row['event_start']);
$event_end = nullable_htmlentities($row['event_end']);
$event_repeat = nullable_htmlentities($row['event_repeat']);
$calendar_id = intval($row['calendar_id']);
$calendar_name = nullable_htmlentities($row['calendar_name']);
$calendar_color = nullable_htmlentities($row['calendar_color']);
$client_id = intval($row['event_client_id']);
require "modals/calendar_event_edit_modal.php";
}
?>
<?php require_once("footer.php"); ?>
<?php require_once "includes/footer.php";
?>
<script src='plugins/fullcalendar/main.min.js'></script>
<script src='plugins/fullcalendar/dist/index.global.js'></script>
<script>
document.addEventListener('DOMContentLoaded', function() {
var calendarEl = document.getElementById('calendar');
@@ -50,107 +107,217 @@ while ($row = mysqli_fetch_array($sql)) {
themeSystem: 'bootstrap',
defaultView: 'dayGridMonth',
customButtons: {
addEvent: {
bootstrapFontAwesome: 'fa fa-plus',
newEvent: {
text: 'New Event',
bootstrapFontAwesome: 'fas fa-plus',
click: function() {
$("#addCalendarEventModal").modal();
}
},
addCalendar: {
bootstrapFontAwesome: 'fa fa-calendar-plus',
click: function() {
$("#addCalendarModal").modal();
}
}
},
headerToolbar: {
left: 'prev,next today',
center: 'title',
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth addEvent addCalendar'
right: 'dayGridMonth,timeGridWeek,timeGridDay,listMonth newEvent'
},
events: [
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id WHERE calendars.company_id = $session_company_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['event_id']);
$event_title = json_encode($row['event_title']);
$event_start = json_encode($row['event_start']);
$event_end = json_encode($row['event_end']);
$calendar_id = intval($row['calendar_id']);
$calendar_name = json_encode($row['calendar_name']);
$calendar_color = json_encode($row['calendar_color']);
<?php if (!$session_mobile) {
?>aspectRatio: 2.5,
<?php } else { ?>
aspectRatio: 0.7,
<?php } ?>
navLinks: true, // can click day/week names to navigate views
selectable: true,
height: '90vh',
echo "{ id: $event_id, title: $event_title, start: $event_start, end: $event_end, color: $calendar_color },";
}
selectMirror: true,
eventClick: function(editEvent) {
$('#editEventModal' + editEvent.event.id).modal();
},
dayMaxEvents: true, // allow "more" link when too many events
views: {
timeGrid: {
dayMaxEventRows: 3, // adjust to 6 only for timeGridWeek/timeGridDay
expandRows: true,
nowIndicator: true,
eventMaxStack: 1,
},
dayGrid: {
dayMaxEvents: 3, // adjust to 6 only for timeGridWeek/timeGridDay
expandRows: true,
},
//Invoices Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN invoices ON client_id = invoice_client_id WHERE clients.company_id = $session_company_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['invoice_id']);
$event_title = json_encode($row['invoice_prefix'] . $row['invoice_number'] . " " . $row['invoice_scope']);
$event_start = json_encode($row['invoice_date']);
},
events: [
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM events LEFT JOIN calendars ON event_calendar_id = calendar_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['event_id']);
$event_title = json_encode($row['event_title']);
$event_start = json_encode($row['event_start']);
$event_end = json_encode($row['event_end']);
$calendar_id = intval($row['calendar_id']);
$calendar_name = json_encode($row['calendar_name']);
$calendar_color = json_encode($row['calendar_color']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'blue', url: 'invoice.php?invoice_id=$event_id' },";
}
//Quotes Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN quotes ON client_id = quote_client_id WHERE clients.company_id = $session_company_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['quote_id']);
$event_title = json_encode($row['quote_prefix'] . $row['quote_number'] . " " . $row['quote_scope']);
$event_start = json_encode($row['quote_date']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'purple', url: 'quote.php?quote_id=$event_id' },";
}
//Tickets Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN tickets ON client_id = ticket_client_id WHERE clients.company_id = $session_company_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['ticket_id']);
$event_title = json_encode($row['ticket_prefix'] . $row['ticket_number'] . " " . $row['ticket_subject']);
$event_start = json_encode($row['ticket_created_at']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'orange', url: 'ticket.php?ticket_id=$event_id' },";
}
//Vendors Added Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN vendors ON client_id = vendor_client_id WHERE vendor_template = 0 AND clients.company_id = $session_company_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['vendor_id']);
$client_id = intval($row['client_id']);
$event_title = json_encode($row['vendor_name']);
$event_start = json_encode($row['vendor_created_at']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'brown', url: 'client_vendors.php?client_id=$client_id' },";
}
//Clients Added
$sql = mysqli_query($mysqli, "SELECT * FROM clients WHERE clients.company_id = $session_company_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['client_id']);
$event_title = json_encode($row['client_name']);
$event_start = json_encode($row['client_created_at']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'green', url: 'client_overview.php?client_id=$event_id' },";
}
?>
],
eventClick: function(editEvent) {
$('#editEventModal'+editEvent.event.id).modal();
echo "{ id: $event_id, title: $event_title, start: $event_start, end: $event_end, color: $calendar_color },";
}
//Invoices Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN invoices ON client_id = invoice_client_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['invoice_id']);
$scope = strval($row['invoice_scope']);
if (empty($scope)) {
$scope = "Not Set";
}
$event_title = json_encode($row['invoice_prefix'] . $row['invoice_number'] . " created -scope: " . $scope);
$event_start = json_encode($row['invoice_date']);
echo "{ id: $event_id, title: $event_title, start: $event_start, display: 'list-item', color: 'blue', url: 'invoice.php?invoice_id=$event_id' },";
}
//Quotes Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN quotes ON client_id = quote_client_id");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['quote_id']);
$event_title = json_encode($row['quote_prefix'] . $row['quote_number'] . " " . $row['quote_scope']);
$event_start = json_encode($row['quote_date']);
echo "{ id: $event_id, title: $event_title, start: $event_start, display: 'list-item', color: 'purple', url: 'quote.php?quote_id=$event_id' },";
}
//Tickets Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients
LEFT JOIN tickets ON client_id = ticket_client_id
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
LEFT JOIN users ON ticket_assigned_to = user_id"
);
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['ticket_id']);
$ticket_status = intval($row['ticket_status']);
$ticket_status_name = strval($row['ticket_status_name']);
$username = $row['user_name'];
if (empty($username)) {
$username = "";
} else {
//Limit to characters and add ...
$username = "[". substr($row['user_name'], 0, 9) . "...]";
}
$event_title = json_encode($row['ticket_prefix'] . $row['ticket_number'] . " created - " . $row['ticket_subject'] . " " . $username . "{" . $ticket_status_name . "}");
$event_start = json_encode($row['ticket_created_at']);
if ($ticket_status == 1) {
$event_color = "red";
} elseif ($ticket_status == 2) {
$event_color = "blue";
} elseif ($ticket_status == 3) {
$event_color = "grey";
} else {
$event_color = "black";
}
echo "{ id: $event_id, title: $event_title, start: $event_start, color: '$event_color', url: 'ticket.php?ticket_id=$event_id' },";
}
// 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"
);
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['scheduled_ticket_id']);
$client_id = intval($row['client_id']);
$username = $row['user_name'];
$frequency = $row['scheduled_ticket_frequency'];
if (empty($username)) {
$username = "";
} else {
//Limit to characters and add ...
$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']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: '$event_color', url: 'client_recurring_tickets.php?client_id=$client_id' },";
}
//Tickets Scheduled
$sql = mysqli_query($mysqli, "SELECT * FROM clients
LEFT JOIN tickets ON client_id = ticket_client_id
LEFT JOIN ticket_statuses ON ticket_status = ticket_status_id
LEFT JOIN users ON ticket_assigned_to = user_id
WHERE ticket_schedule IS NOT NULL"
);
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['ticket_id']);
$username = $row['user_name'];
if (empty($username)) {
$username = "";
} else {
//Limit to characters and add ...
$username = substr($row['user_name'], 0, 9) . "...";
}
if (strtotime($row['ticket_schedule']) < time()) {
if (!empty($row['ticket_schedule'])) {
$event_color = "red";
} else {
$event_color = "green";
}
} else {
$event_color = "grey";
}
$ticket_status = strval($row['ticket_status_name']);
$event_title = json_encode($row['ticket_prefix'] . $row['ticket_number'] . " scheduled - " . $row['ticket_subject'] . " [" . $username . "]{" . $ticket_status . "}");
$event_start = json_encode($row['ticket_schedule']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: '$event_color', url: 'ticket.php?ticket_id=$event_id' },";
}
//Vendors Added Created
$sql = mysqli_query($mysqli, "SELECT * FROM clients LEFT JOIN vendors ON client_id = vendor_client_id WHERE vendor_template = 0");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['vendor_id']);
$client_id = intval($row['client_id']);
$event_title = json_encode("Vendor : '" . $row['vendor_name'] . "' created");
$event_start = json_encode($row['vendor_created_at']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'brown', url: 'client_vendors.php?client_id=$client_id' },";
}
//Clients Added
$sql = mysqli_query($mysqli, "SELECT * FROM clients");
while ($row = mysqli_fetch_array($sql)) {
$event_id = intval($row['client_id']);
$event_title = json_encode("Client: '" . $row['client_name'] . "' created");
$event_start = json_encode($row['client_created_at']);
echo "{ id: $event_id, title: $event_title, start: $event_start, color: 'brown', url: 'client_overview.php?client_id=$event_id' },";
}
?>
],
eventOrder: 'allDay,start,-duration,title',
<?php
// User preference for Calendar start day (Sunday/Monday)
// Fetch User Dashboard Settings
$row = mysqli_fetch_array(mysqli_query($mysqli, "SELECT user_config_calendar_first_day FROM user_settings WHERE user_id = $session_user_id"));
$user_config_calendar_first_day = intval($row['user_config_calendar_first_day']);
?>
firstDay: <?php echo $user_config_calendar_first_day ?>,
});
calendar.render();
});
</script>
<!-- Automatically set new event end date to 1 hr after start date -->
<script>
// Function - called when user leaves field (onblur)
function updateIncrementEndTime() {
@@ -160,15 +327,19 @@ while ($row = mysqli_fetch_array($sql)) {
// Create a date object
let new_end = new Date(start);
// Get the time zone offset in minutes, convert it to milliseconds
let offsetInMilliseconds = new_end.getTimezoneOffset() * 60 * 1000;
// Adjust the date by the time zone offset before adding an hour
new_end = new Date(new_end.getTime() - offsetInMilliseconds);
// Set the end date to 1 hr in the future
new_end.setHours(new_end.getHours() + 1)
new_end.setHours(new_end.getHours() + 1);
// Get the date back as a string, with the milliseconds trimmed off
new_end = new_end.toISOString().replace(/.\d+Z$/g, "");
// Update the end date field
document.getElementById("event_add_end").value = new_end;
}
</script>

View File

@@ -1,138 +0,0 @@
<?php
// Default Column Sortby Filter
$sb = "category_name";
$o = "ASC";
require_once("inc_all_settings.php");
if (isset($_GET['category'])) {
$category = sanitizeInput($_GET['category']);
} else {
$category = "Expense";
}
//Rebuild URL
$url_query_strings_sb = http_build_query(array_merge($_GET, array('sb' => $sb, 'o' => $o)));
$sql = mysqli_query(
$mysqli,
"SELECT SQL_CALC_FOUND_ROWS * FROM categories
WHERE category_name LIKE '%$q%'
AND category_type = '$category'
AND category_archived_at IS NULL
AND company_id = $session_company_id
ORDER BY $sb $o LIMIT $record_from, $record_to"
);
$num_rows = mysqli_fetch_row(mysqli_query($mysqli, "SELECT FOUND_ROWS()"));
$colors_used_array = [];
//Colors Used
$sql_colors_used = mysqli_query(
$mysqli,
"SELECT category_color FROM categories
WHERE category_type = '$category'
AND category_archived_at IS NULL
AND company_id = $session_company_id"
);
while ($color_used_row = mysqli_fetch_array($sql_colors_used)) {
$colors_used_array[] = $color_used_row['category_color'];
}
$colors_diff = array_diff($colors_array, $colors_used_array);
?>
<div class="card card-dark">
<div class="card-header py-2">
<h3 class="card-title mt-2"><i class="fa fa-fw fa-list mr-2"></i><?php echo htmlentities($category); ?> Categories</h3>
<div class="card-tools">
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#addCategoryModal"><i class="fas fa-plus mr-2"></i>New</button>
</div>
</div>
<div class="card-body">
<form autocomplete="off">
<input type="hidden" name="category" value="<?php echo htmlentities($category); ?>">
<div class="row">
<div class="col-sm-4 mb-2">
<div class="input-group">
<input type="search" class="form-control" name="q" value="<?php if (isset($q)) { echo stripslashes(htmlentities($q)); } ?>" placeholder="Search Categories">
<div class="input-group-append">
<button class="btn btn-primary"><i class="fa fa-search"></i></button>
</div>
</div>
</div>
<div class="col-sm-8">
<div class="btn-group float-right">
<a href="?category=Expense" class="btn <?php if ($category == 'Expense') { echo 'btn-primary'; } else { echo 'btn-default'; } ?>">Expense</a>
<a href="?category=Income" class="btn <?php if ($category == 'Income') { echo 'btn-primary'; } else { echo 'btn-default'; } ?>">Income</a>
<a href="?category=Referral" class="btn <?php if ($category == 'Referral') { echo 'btn-primary'; } else { echo 'btn-default'; } ?>">Referral</a>
<a href="?category=Payment Method" class="btn <?php if ($category == 'Payment Method') { echo 'btn-primary'; } else { echo 'btn-default'; } ?>">Payment Method</a>
</div>
</div>
</div>
</form>
<hr>
<div class="table-responsive">
<table class="table table-striped table-borderless table-hover">
<thead class="text-dark <?php if ($num_rows[0] == 0) { echo "d-none"; } ?>">
<tr>
<th><a class="text-dark" href="?<?php echo $url_query_strings_sb; ?>&sb=category_name&o=<?php echo $disp; ?>">Name</a></th>
<th>Color</th>
<th class="text-center">Action</th>
</tr>
</thead>
<tbody>
<?php
while ($row = mysqli_fetch_array($sql)) {
$category_id = intval($row['category_id']);
$category_name = htmlentities($row['category_name']);
$category_color = htmlentities($row['category_color']);
//$colors_used_array[] = $row['category_color'];
?>
<tr>
<td><a class="text-dark" href="#" data-toggle="modal" data-target="#editCategoryModal<?php echo $category_id; ?>"><?php echo $category_name; ?></a></td>
<td><i class="fa fa-3x fa-circle" style="color:<?php echo $category_color; ?>;"></i></td>
<td>
<div class="dropdown dropleft text-center">
<button class="btn btn-secondary btn-sm" type="button" data-toggle="dropdown">
<i class="fas fa-ellipsis-h"></i>
</button>
<div class="dropdown-menu">
<a class="dropdown-item" href="#" data-toggle="modal" data-target="#editCategoryModal<?php echo $category_id; ?>">
<i class="fas fa-fw fa-edit mr-2"></i>Edit
</a>
<div class="dropdown-divider"></div>
<a class="dropdown-item text-danger" href="post.php?archive_category=<?php echo $category_id; ?>">
<i class="fas fa-fw fa-archive mr-2"></i>Archive
</a>
</div>
</div>
</td>
</tr>
<?php
//$colors_diff = array_diff($colors_array,$colors_used_array);
include("category_edit_modal.php");
}
?>
</tbody>
</table>
</div>
<?php require_once("pagination.php"); ?>
</div>
</div>
<?php
require_once("category_add_modal.php");
require_once("footer.php");

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