Compare commits

...

303 Commits

Author SHA1 Message Date
snipe d990d753ce Switch to 660 2026-03-09 08:23:03 +00:00
snipe 425bab096d Added fix-permissions script to composer to handle #18601 2026-03-08 14:52:23 +00:00
snipe 338fc88095 Merge pull request #18647 from grokability/revert-18601-chore/security-upgrade-passport13-socialite-jwt7
Revert "Upgrade Passport to v13 and move php-jwt to v7 to remediate JWT advisory"
2026-03-08 12:32:31 +00:00
snipe 0a724cc49a Revert "Upgrade Passport to v13 and move php-jwt to v7 to remediate JWT advisory" 2026-03-08 12:29:56 +00:00
snipe a2efcf1ca9 Merge pull request #18601 from ubc-cpsc/chore/security-upgrade-passport13-socialite-jwt7
Upgrade Passport to v13 and move php-jwt to v7 to remediate JWT advisory
2026-03-08 11:51:15 +00:00
snipe c9d73e85e1 Fixed RB-4083 2026-03-08 11:37:19 +00:00
Joël Pittet a956676745 Move Passport 13 key permission normalization to upgrade.php to cover existing installs with incorrect permissions 2026-03-07 22:22:46 -08:00
Joël Pittet 5800d08202 normalize key permissions 2026-03-07 21:59:07 -08:00
Joël Pittet b8958bad72 Test failure fixes from 'Key Files Permissions Validation' from https://github.com/laravel/passport/blob/13.x/UPGRADE.md#key-files-permissions-validation 2026-03-07 21:59:00 -08:00
Joël Pittet 0508d7558e OAuth Client Table Changes (Optional) from https://github.com/laravel/passport/blob/13.x/UPGRADE.md#oauth-client-table-changes-optional 2026-03-07 21:59:00 -08:00
Joël Pittet 98c3192a13 Bump laravel/socialite to latest patch release, upgrade laravel/passport to 13 which is compatible with Laravel 11, and security release for firebase/php-jwt 2026-03-07 21:59:00 -08:00
snipe b886e11670 Fixed user API tests 2026-03-07 20:50:18 +00:00
snipe 92bb1df82e Removed error log in test 2026-03-07 11:05:33 +00:00
snipe 1c4549dd8e Added word break on history 2026-03-07 11:04:25 +00:00
snipe 83e61ec8cd Unset admin if auth user is not admin 2026-03-07 10:45:57 +00:00
snipe 7ea549df4a Added .journal to gitignore 2026-03-06 21:57:23 +00:00
snipe af1c55cd7e Small code re-org for clarity 2026-03-06 21:55:46 +00:00
snipe 7822c0bc3e Merge pull request #18644 from uberbrady/fix_location_observer
Re-add Location Observer with null-safe companyable check
2026-03-06 21:47:58 +00:00
Brady Wetherington 2b7ed1f7fa Re-add Location Observer with null-safe companyable check 2026-03-06 21:43:19 +00:00
snipe 45ddaf1b72 Temp comment out location observer 2026-03-06 20:14:56 +00:00
snipe 7595c922fa Fixed #18043 - added location logging 2026-03-06 14:03:37 +00:00
snipe 4d4513d936 Fixed #18642 - view-assets mobile 2026-03-06 13:40:01 +00:00
snipe e378c99923 Layout tweakas 2026-03-06 13:29:38 +00:00
snipe 078c870970 Merge pull request #18162 from Godmartinz/status_bulk_select_fix
Adds #17685 better warning for bulk status change to undeployable type
2026-03-06 09:58:41 +01:00
snipe 4a91d37423 Merge pull request #17666 from akemidx/xxdays-since-last-update
Feature: Added xx days since last update to Custom Report
2026-03-06 09:54:32 +01:00
snipe 96befb2aef Merge branch 'develop' into xxdays-since-last-update 2026-03-06 09:54:01 +01:00
snipe 925452e106 Merge pull request #18248 from iryadifarhan/fix/depreciation-report-displays-incorrect-monthly-depreciation-value
Fixes inaccurate monthly depreciation value displayed at depreciation report when using a floor value
2026-03-06 09:40:39 +01:00
snipe 1678330f0c Merge pull request #18426 from akemidx/global-report-templates
Fixed: Added global report templates
2026-03-06 09:30:15 +01:00
snipe 58cf3fc2ea Dev assets 2026-03-06 08:17:48 +00:00
snipe 13ce17ffc6 Merge pull request #18494 from marcusmoore/livewire4
Upgraded Livewire to v4
2026-03-06 09:16:25 +01:00
snipe 70e020ee0c Merge pull request #18637 from marcusmoore/test-updates
Fixed some minor issues in tests
2026-03-06 09:16:00 +01:00
snipe c6a167ef40 Removed min-height (this might go badly) 2026-03-06 07:42:28 +00:00
snipe 420ba5f261 Fixed #18341 - remove action button from user profile view 2026-03-06 06:45:46 +00:00
snipe 7aa1f3ae1d Merge pull request #18639 from grokability/#18282-add-user-notes-to-custom-export
Fixed #18282 - added original notes to checkout target in custom report
2026-03-06 07:23:58 +01:00
snipe 556d638136 Fixed #18282 - added original notes to checkout target in custom report 2026-03-06 06:19:16 +00:00
snipe c4aa10baf8 Added user company to custom asset report 2026-03-06 05:59:11 +00:00
snipe 86f647e714 Improved bulk audit bg 2026-03-06 05:39:09 +00:00
snipe 64f5d40fd9 Removed duplicate code 2026-03-06 05:21:59 +00:00
snipe 1a0869c2ca Merge pull request #18628 from marcusmoore/fixes/fd-54108-checkin-all-button
Fixed Checkin All Seats button
2026-03-06 06:17:12 +01:00
snipe 1fb32ee461 Merge pull request #18638 from grokability/experiments/compact-nav
Compacted nav UI, components for buttons
2026-03-06 05:45:02 +01:00
snipe 68a863e63e Updated test, fixed route 2026-03-06 04:38:48 +00:00
snipe a1e62ccd46 Fixed (shimmed) #18636 - added shim roite for fieldsets 2026-03-06 03:54:33 +00:00
snipe dae66c0fa4 Fixed audit background 2026-03-06 03:48:45 +00:00
snipe 1d6b21e1c7 Switched to newer button model 2026-03-06 03:33:04 +00:00
snipe 455be12058 Gate fix for admin 2026-03-06 03:05:40 +00:00
snipe 2ebb3ecb96 Update views with new button blades 2026-03-06 01:17:00 +00:00
Marcus Moore b29056dddf Delete duplicate test 2026-03-05 16:35:15 -08:00
Marcus Moore 3ed09f304c Fix method name 2026-03-05 16:30:05 -08:00
Marcus Moore 4875283ed1 Fix test route 2026-03-05 16:20:27 -08:00
Marcus Moore 261231c09e Fix method and variable names 2026-03-05 15:55:59 -08:00
snipe 180dad6ee6 Use updated infobox 2026-03-05 14:36:12 +00:00
snipe d7121ad82f Removed class active (this is handled in jquery) 2026-03-05 11:46:55 +00:00
snipe f121c61524 Added hidden-print class to action buttons column 2026-03-05 11:45:21 +00:00
Marcus Moore 93bf91869b Fix checkin all seats button 2026-03-03 14:57:43 -08:00
snipe 2ed32612b9 Fixed typo in comments 2026-03-02 18:35:57 +01:00
snipe 314bcbe208 Added assets upload url singleton 2026-03-02 18:35:57 +01:00
snipe 6290e34623 Exclude show route for settings API [RB-17718] 2026-03-02 18:35:57 +01:00
snipe 5e5521a128 Merge pull request #18623 from grokability/dependabot/github_actions/develop/actions/upload-artifact-7
Bump actions/upload-artifact from 6 to 7
2026-03-02 12:51:02 +00:00
dependabot[bot] 1e8bed86d3 Bump actions/upload-artifact from 6 to 7
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2026-03-02 08:43:13 +00:00
snipe 8bc7d50e35 Updated to check gate on object 2026-02-26 16:03:57 +00:00
Marcus Moore aa420e5006 Bump Livewire to v4.1.4 2026-02-25 13:30:30 -08:00
Marcus Moore 4babaa85fc Merge branch 'develop' into livewire4
# Conflicts:
#	composer.lock
2026-02-25 13:29:07 -08:00
snipe 378d9e008e Removed truncate that ran after maintenance seeder 2026-02-25 19:46:09 +00:00
snipe 340fabe4f6 Merge pull request #18614 from spencerrlongg/eof-rollbar
Fixes (hopefully) RB #19772 Unexpected EOF
2026-02-25 19:05:30 +00:00
spencerrlongg 29331b8b06 missing semicolon - kind of a shot in the dark 2026-02-25 12:54:43 -06:00
snipe 6fbcaa0959 Make sure manager_id is an integer 2026-02-25 18:41:53 +00:00
snipe 52e10205c5 Add license ID to tabke cookie 2026-02-25 18:40:29 +00:00
snipe f419ae3f4a Fixed license history target 2026-02-25 17:41:26 +00:00
snipe 84a6b8e012 Add display_name to asset advanced search filter 2026-02-25 16:54:54 +00:00
snipe f234aee691 Use display_name in transformUserCompact() 2026-02-25 16:41:30 +00:00
snipe 623d516595 Merge pull request #18095 from marcusmoore/5947-bulk-checkout-rollup
#5947 - roll up bulk asset checkout email
2026-02-25 15:36:58 +00:00
snipe 156eaf53d5 Fix for #18408 2026-02-25 15:30:37 +00:00
snipe 678a7c1437 Removed BS class 2026-02-25 15:04:24 +00:00
snipe ce2a760093 Merge pull request #17964 from Godmartinz/add-License-checkedout-to-user
Adds #11741 currently assigned license table to license checkout
2026-02-25 14:50:39 +00:00
snipe 34b02d8534 Merge pull request #18485 from marcusmoore/debugbar
Bumped Debugbar to v4
2026-02-25 14:43:03 +00:00
snipe 42e0e691dd Merge pull request #18609 from ubc-cpsc/bugfix/php-deprecated-string-interpolation
Fix deprecated string interpolation in controllers
2026-02-25 14:41:24 +00:00
snipe ccfda99060 Merge pull request #18613 from grokability/add-sorting-on-model-name-and-number-for-maintenances
Added model number as a separate field, added sorting
2026-02-25 14:22:48 +00:00
snipe 57f02bdc57 Fixed typo 2026-02-25 14:22:27 +00:00
snipe 7056656eab Added model number as a separate field, added sorting 2026-02-25 14:19:01 +00:00
snipe 2d899fc772 Merge pull request #18612 from grokability/added-maintenances-seeder
Added maintenances seeder
2026-02-25 14:16:44 +00:00
snipe 80ee0835aa Added maintenances seeder 2026-02-25 14:12:13 +00:00
snipe 7b7e6c7971 Fixed maintence image display 2026-02-25 12:39:29 +00:00
snipe 025fb30335 Added user email to exportable field in custom report 2026-02-25 12:03:23 +00:00
snipe fcace4a192 Override the table search with the asset tag search if one is passed 2026-02-25 11:50:52 +00:00
snipe 619e1c70ea Fixed #18603 - set unique cookie ID on asset history table 2026-02-25 11:48:42 +00:00
Joël Pittet 7a95bdfba6 Fix deprecated string interpolation in controllers 2026-02-24 14:57:29 -08:00
Marcus Moore 89962de161 Move to Traits directory 2026-02-24 11:37:07 -08:00
Marcus Moore d9328bd0ce Merge branch 'develop' into debugbar 2026-02-24 11:27:04 -08:00
snipe 81306df06a Merge pull request #18606 from grokability/#18600-check-filesystem-on-healthcheck
Fixed #18600 - add filesystem check on health checker
2026-02-24 14:00:14 +00:00
snipe 75abe9eb3e Re-add try/catch for DB for cleaner output 2026-02-24 13:23:12 +00:00
snipe 1f26bf1125 Fixed #18600 - add filesystem check on health checker 2026-02-24 13:17:15 +00:00
snipe 14b9c06d77 Remove optional qualifier 2026-02-24 12:00:06 +00:00
snipe 4f3d23d1ef Merge pull request #18576 from marcusmoore/fixes/rb-20713-license-seat-assigned-to
Fixed RB-20713: Improved validation of license seat update api endpoint
2026-02-24 07:29:41 +00:00
Marcus Moore cada43f34d Allow checking in from unfound targets 2026-02-23 17:23:42 -08:00
Marcus Moore 1cc7ef0543 Organization 2026-02-23 10:51:34 -08:00
Marcus Moore e81ccf4280 Add more failing assertions 2026-02-19 16:53:22 -08:00
Marcus Moore 9730f2c0f3 Add some failing assertions 2026-02-19 16:40:45 -08:00
Marcus Moore 1de34c0656 Some controller clean up 2026-02-19 16:40:34 -08:00
Marcus Moore bdce6b1387 Add test case 2026-02-19 13:51:20 -08:00
Marcus Moore ce0c2ecd8f Populate new tests 2026-02-19 13:47:52 -08:00
Marcus Moore 40f07e3d72 Scaffold addition test cases 2026-02-19 11:50:04 -08:00
Godfrey M be211f6f86 fix apostophes 2026-02-19 09:57:29 -08:00
Marcus Moore 504f63066f Add note 2026-02-18 16:34:22 -08:00
Marcus Moore 41b327529b Reference rollbar 2026-02-18 16:31:55 -08:00
Marcus Moore e84279c402 Implement remaining tests 2026-02-18 16:17:34 -08:00
Marcus Moore dbbb3beacc Clean up 2026-02-18 15:35:57 -08:00
Marcus Moore e8a73a8de6 Organization 2026-02-18 15:29:44 -08:00
Marcus Moore 411cbc0962 Avoid overwriting created_by and timestamps 2026-02-18 15:20:28 -08:00
Marcus Moore b487c0e3e9 Scaffold additional tests 2026-02-18 15:20:18 -08:00
Marcus Moore fa0e8f6e01 Improve validation 2026-02-18 15:11:52 -08:00
Marcus Moore e25e405f74 Scaffold additional test cases and organize 2026-02-18 14:52:43 -08:00
Marcus Moore 302c4a6414 Organize test 2026-02-18 14:35:06 -08:00
Marcus Moore d1e7f6e55e Inline 2026-02-18 14:03:28 -08:00
Marcus Moore d12f0974df Add test for permission 2026-02-18 14:01:53 -08:00
Marcus Moore 5055aafe1d Scaffold tests 2026-02-17 17:37:24 -08:00
Marcus Moore e68b9ea267 Validate assigned_to is integer 2026-02-17 16:51:31 -08:00
Marcus Moore 1d8ba2ec61 Add failing test 2026-02-17 16:49:32 -08:00
Marcus Moore 7eb536f80e Bump debugbar to v4.0.7 2026-02-11 11:37:57 -08:00
Marcus Moore d91ce88e9a Merge branch 'develop' into debugbar 2026-02-11 11:37:02 -08:00
Marcus Moore 7ada7fb327 Merge branch 'develop' into livewire4 2026-02-05 10:39:56 -08:00
Marcus Moore 9d632e39bf Merge branch 'develop' into debugbar 2026-02-05 10:33:13 -08:00
Marcus Moore 5d085469ec Bump debugbar to v4.0.6 2026-02-04 10:46:34 -08:00
Marcus Moore 7c54429c13 Bump Livewire to v4.1.2 2026-02-03 09:14:41 -08:00
Marcus Moore 8dfd04573e Bump debugbar to v4.0.5 2026-02-02 09:53:17 -08:00
Marcus Moore 1aee8679d2 Fix updating bug in oauth clients 2026-01-28 12:46:57 -08:00
Marcus Moore 8829ea9b29 Update category edit form 2026-01-27 17:08:21 -08:00
Marcus Moore 6ba99e8199 Bump livewire to v4.1.0 2026-01-27 14:03:52 -08:00
Marcus Moore b4eb603f22 Switch blur to change 2026-01-27 13:58:42 -08:00
Marcus Moore 62f9ce979d Fix js 2026-01-27 13:41:57 -08:00
Marcus Moore f5928fc707 Fix tags in importer 2026-01-27 12:33:46 -08:00
Marcus Moore f7040e3616 Remove console.log 2026-01-26 17:43:47 -08:00
Marcus Moore a70f1cc1ef Migrate request hook 2026-01-26 17:38:01 -08:00
Marcus Moore a86b738231 Update route 2026-01-26 17:13:56 -08:00
Marcus Moore 8a9ddba208 Use traditional component naming 2026-01-26 17:02:32 -08:00
Marcus Moore 4c727966e7 Migrate config 2026-01-26 16:59:08 -08:00
Marcus Moore c2ac53029a Update to v4 2026-01-26 16:58:58 -08:00
Marcus Moore 5d300d85bd Update content-type assertion 2026-01-26 14:52:53 -08:00
Marcus Moore 1dc181797b Move trait to base controller 2026-01-26 14:39:48 -08:00
Marcus Moore 30d932e2e0 Re-enable exception collector 2026-01-26 14:30:03 -08:00
Marcus Moore 9fb32d33af Migrate to v4 config 2026-01-26 14:28:18 -08:00
Marcus Moore 70baa60521 Install v4 of laravel debugbar 2026-01-26 14:02:01 -08:00
Marcus Moore 8ea2784d44 Uninstall debugbar 2026-01-26 14:01:29 -08:00
Marcus Moore 2b56d82577 Move disabling debugbar to trait 2026-01-26 14:01:21 -08:00
akemidx 5d91e0fa0a name box alignment/icons for shared or not 2026-01-12 07:48:53 -05:00
akemidx eb41247f2d changing 'shared_report_template' to 'is_shared' in DB part 2, also last commit deleted an unused request file 2026-01-08 18:54:44 -07:00
akemidx d53eafe87a changing 'shared_report_template' to 'is_shared' in DB 2026-01-08 18:52:36 -07:00
Marcus Moore 065c17002e Remove unused test cases 2026-01-08 15:18:16 -08:00
Marcus Moore 0e46a54013 Improve input alignment 2026-01-08 15:08:56 -08:00
Marcus Moore 0e35fb941b Improve assertions 2026-01-08 14:17:10 -08:00
Marcus Moore 71c9b927c6 Allow using same template name 2026-01-08 14:17:00 -08:00
akemidx e42960ea15 sharing a report template test 2026-01-07 18:49:34 -07:00
Marcus Moore 636d42a52e Make test more explicit 2026-01-07 16:42:47 -08:00
Marcus Moore 1451843f84 Implement test for viewing shared template 2026-01-07 16:39:10 -08:00
Marcus Moore f8af21306a Handle attempting to delete another user's template 2026-01-07 16:37:34 -08:00
Marcus Moore 4e874cdb1b Fix update logic 2026-01-07 16:13:22 -08:00
akemidx dbd9a844dc scaffold test cases around sharing templates 2026-01-07 16:29:32 -07:00
akemidx c5284ed195 works fully, just needs to restrict editing for non template creator 2026-01-06 17:21:22 -07:00
Marcus Moore 5cd92dd794 Remove redundant display of "Category" 2026-01-05 15:13:27 -08:00
akemidx bd98ee62e1 something something prebreak 2026-01-05 12:16:16 -07:00
akemidx 33f7a8d356 save copy 2025-12-16 21:38:13 -05:00
akemidx 64c3fe9099 notes and new direction? 2025-12-16 21:27:51 -05:00
akemidx 193fba71f3 fixing validation 2025-12-11 17:21:48 -05:00
akemidx 8a14800ef2 fixes/beginning validation 2025-12-11 03:42:10 -05:00
akemidx a46d73f562 spacing/hiding when no template loaded 2025-12-11 03:21:34 -05:00
akemidx 865392d1f7 margin 2025-12-09 14:10:32 -05:00
akemidx b880ed2371 front end clarity 2025-12-09 13:14:09 -05:00
Marcus Moore def04017e0 Improve readability in tests 2025-12-08 14:10:44 -08:00
Marcus Moore 9eeb916796 Improve clarity in test 2025-12-08 14:04:18 -08:00
Marcus Moore b06a0c5d83 Use value already computed 2025-12-08 13:59:07 -08:00
Marcus Moore 90541ba349 Use foreach instead of reduce 2025-12-08 13:57:38 -08:00
Marcus Moore 0cc346259b Use foreach instead of reduce 2025-12-08 13:51:30 -08:00
Marcus Moore 98c343b438 Improve method ordering 2025-12-08 13:48:22 -08:00
akemidx 7ee0cdc6c7 hide edit and delete for non report creators 2025-12-08 16:42:38 -05:00
akemidx 6a770832ba only creator can see share checkbox 2025-12-08 16:32:11 -05:00
akemidx ef0ff65162 scoping shared templates 2025-12-08 16:29:14 -05:00
akemidx 8c0e7e1bb3 share option saved in db column 2025-12-08 15:55:26 -05:00
Marcus Moore 8cb2ef7cac Add typehint 2025-12-08 12:17:04 -08:00
Marcus Moore 046b38e5c2 Improve method name 2025-12-08 12:10:25 -08:00
Marcus Moore d50d7fd631 Account for null value 2025-12-08 12:09:58 -08:00
Marcus Moore a34ea0804d Separate out info and prompt 2025-12-04 17:22:23 -08:00
Marcus Moore 0fbf4ce443 Move singular eula to bottom of email 2025-12-04 17:08:48 -08:00
Marcus Moore d062cc45df Add translation 2025-12-04 15:18:24 -08:00
Marcus Moore da790136ff WIP 2025-12-04 14:40:51 -08:00
Marcus Moore 134f374ada WIP 2025-12-04 14:39:37 -08:00
Marcus Moore df304a894f WIP 2025-12-04 14:38:13 -08:00
Marcus Moore 2d1d90e38c Add comment 2025-12-04 14:34:50 -08:00
Marcus Moore dcbdc6fcb8 WIP 2025-12-04 14:27:53 -08:00
Marcus Moore 5a4ef15de5 Avoid rendering rule if last item in loop 2025-12-04 14:22:13 -08:00
Marcus Moore affc4c8bd9 Styling 2025-12-04 14:07:10 -08:00
Marcus Moore bc5d6e89ba Readability 2025-12-04 14:05:22 -08:00
Marcus Moore c17e6811d2 Group categories visually 2025-12-04 14:03:11 -08:00
Marcus Moore 7f097c029a Fix indent 2025-12-04 13:52:26 -08:00
akemidx 60f5affe43 more sharing framewor. tests outlines 2025-12-04 13:48:36 -05:00
akemidx e769239213 only user can change report sharing 2025-12-04 00:39:47 -05:00
akemidx 45923a74f6 only user can change report sharing 2025-12-04 00:34:30 -05:00
Marcus Moore 7bf7a87f8a Begin to display EULAs for all categories 2025-12-03 16:59:57 -08:00
Marcus Moore 8396e27a2c Revert "Avoid showing EULA"
This reverts commit 8c89eb6650.
2025-12-03 16:16:30 -08:00
Marcus Moore 5153c68b8b Remove old todos 2025-12-03 16:15:43 -08:00
Marcus Moore 391495dd86 Remove some assertions 2025-12-02 17:41:22 -08:00
Marcus Moore 8c89eb6650 Avoid showing EULA 2025-12-02 17:37:21 -08:00
Marcus Moore 4167c6ea70 Add some translations 2025-12-02 17:36:05 -08:00
Marcus Moore ca3151ce29 Improve naming 2025-12-02 16:10:53 -08:00
akemidx cc20844eff share template bits 2025-12-02 18:34:13 -05:00
Marcus Moore d876e710e4 Be more specific in tests 2025-12-02 13:48:59 -08:00
Marcus Moore 5c1290425b Improve variable name 2025-12-02 13:28:59 -08:00
Marcus Moore 2043488c67 Cleanups 2025-12-02 12:31:04 -08:00
Marcus Moore e7e48c8f03 Cleanups 2025-12-02 12:30:16 -08:00
Marcus Moore dad650b804 Readability 2025-12-02 12:28:51 -08:00
Marcus Moore d0e73714c6 Implement test 2025-12-02 11:57:02 -08:00
Marcus Moore d8b95d3a20 Organization 2025-12-02 11:53:37 -08:00
Marcus Moore 559d8cc0db Implement test 2025-12-02 11:53:01 -08:00
Marcus Moore 7a804aa576 Implement test 2025-12-02 11:51:28 -08:00
Marcus Moore 0bca66b671 Send email if asset has checkin_email set to true 2025-12-01 16:58:02 -08:00
Marcus Moore 24e5cf8121 Improve readability 2025-12-01 16:51:09 -08:00
Marcus Moore ee7c4ce0f3 Improve assertion 2025-12-01 16:47:23 -08:00
Marcus Moore 428b511687 Send if eula is set 2025-12-01 16:41:50 -08:00
Marcus Moore 49497996d5 Fix template 2025-12-01 16:41:39 -08:00
Marcus Moore bccd65e2fc Add failing test 2025-12-01 16:33:46 -08:00
Marcus Moore f2158843ce Avoid attempting to loop over null 2025-12-01 16:25:37 -08:00
Marcus Moore 87fc4a4f22 Scaffold scenarios 2025-12-01 16:01:34 -08:00
Marcus Moore 27291f9ee9 Add todo 2025-12-01 14:23:33 -08:00
Marcus Moore cba963110e Remove unused import 2025-12-01 14:22:06 -08:00
Marcus Moore aa014e3706 Improve wording 2025-12-01 14:19:54 -08:00
akemidx 58d577f67a shared/notshared marker 2025-12-01 16:48:39 -05:00
Marcus Moore cd3678841b Fix intro line to locations 2025-12-01 13:41:23 -08:00
Marcus Moore 425e0c33df Add tests for introduction line 2025-12-01 12:55:39 -08:00
Marcus Moore 2018407782 Avoid error by pre-checking if user has email address 2025-12-01 12:04:53 -08:00
iryadifarhan a4729a7de8 Fix implemented by using existing function from Depreciable trait, hence addressing the floor value 2025-11-26 10:17:21 +07:00
Marcus Moore 54f065f42c Improve test 2025-11-19 17:11:39 -08:00
Marcus Moore 333ebb88b9 Enable sending to manager 2025-11-19 17:08:00 -08:00
Marcus Moore 53ff367473 Add failing tests 2025-11-19 16:31:48 -08:00
Marcus Moore 33a7de9448 Add custom fields to email 2025-11-19 13:31:30 -08:00
akemidx c797472bcc migration, and front end 2025-11-18 15:03:28 -05:00
Godfrey M 6faf171007 update asset_deployable translation 2025-11-10 16:58:42 -08:00
Godfrey M 9348204987 remove spacing adjustment 2025-11-05 11:22:11 -08:00
Godfrey M 776c7caaa5 get warning/success status check to display 2025-11-05 11:19:05 -08:00
Godfrey M 2216b83ca7 get warning/success status check to display 2025-11-05 11:16:35 -08:00
Marcus Moore 777872d41f Add notification group 2025-10-23 13:53:38 -07:00
Marcus Moore b85d1f184a Remove redundant test 2025-10-23 13:52:52 -07:00
Marcus Moore 02129eeddb Add try/catch 2025-10-23 13:51:53 -07:00
Marcus Moore 2612e0bbc8 Remove unused import 2025-10-23 12:43:12 -07:00
Marcus Moore 3670efacb4 Implement test 2025-10-23 12:39:36 -07:00
Marcus Moore 476611b70f Remove redundant test 2025-10-23 12:27:20 -07:00
Marcus Moore 60df2a17f8 Check context when sending to alert address 2025-10-22 16:41:36 -07:00
Marcus Moore f64f4795c1 Send request instead of firing event 2025-10-22 16:39:34 -07:00
Marcus Moore e036f756d5 Improve setup 2025-10-22 16:24:47 -07:00
Marcus Moore 92fd121cae Clean up 2025-10-22 16:12:35 -07:00
Marcus Moore 6307337892 Add scenario 2025-10-22 16:09:26 -07:00
Marcus Moore fc2e35cd32 Improve assertions 2025-10-22 14:23:07 -07:00
Marcus Moore 1811e061aa Populate scenario 2025-10-22 14:21:24 -07:00
Marcus Moore 59037f0d83 Move scenario 2025-10-22 14:18:45 -07:00
Marcus Moore 67edb7d396 Send to alert email 2025-10-22 14:17:32 -07:00
Marcus Moore 0da393f950 Populate scenario 2025-10-22 14:02:16 -07:00
Marcus Moore abd30e551e Clean up 2025-10-22 13:46:19 -07:00
Marcus Moore 6fb2889a92 Clean up 2025-10-22 13:45:00 -07:00
Marcus Moore 54125d27e0 Add scenario 2025-10-22 13:44:14 -07:00
Marcus Moore 41efda5f82 Add todos 2025-10-21 13:22:41 -07:00
Marcus Moore 2aee14a800 Only send mail to target if they have an email address 2025-10-21 13:14:50 -07:00
Marcus Moore be69da0a0d Add test case 2025-10-21 13:13:45 -07:00
Marcus Moore 31a247b55b Add test case 2025-10-21 12:44:50 -07:00
Marcus Moore 33c156be16 Add failing test 2025-10-21 12:43:23 -07:00
Marcus Moore fd66a083d6 Fix assertion 2025-10-21 12:41:51 -07:00
Marcus Moore d276f50fdf Fix assertion 2025-10-21 12:30:27 -07:00
Marcus Moore 4cb748e124 Improve test assertions 2025-10-21 12:29:25 -07:00
Marcus Moore 503e6898c3 WIP 2025-10-20 16:53:36 -07:00
Marcus Moore f34056fe2e Scaffold some testing changes 2025-10-20 16:35:27 -07:00
Marcus Moore 8ff3575442 Add test for listener registration 2025-10-20 16:31:52 -07:00
Marcus Moore b5e3358bbd Add todos 2025-10-20 14:29:05 -07:00
Marcus Moore 047a1197be Add failing conditions 2025-10-20 14:18:11 -07:00
Marcus Moore 0e87843446 WIP: start testing 2025-10-16 14:30:48 -07:00
Marcus Moore 4f1ff328ad Display eula if it is the same for all items 2025-10-14 17:10:57 -07:00
Marcus Moore ad5bbb9b37 Add divider 2025-10-14 16:34:18 -07:00
Marcus Moore c6e2fd2cab Add note 2025-10-14 16:33:37 -07:00
Marcus Moore d3a7e25b86 Move expected checking and only show once 2025-10-14 16:29:59 -07:00
Marcus Moore 062445a48e Add expected checkin 2025-10-14 16:25:32 -07:00
Marcus Moore 3c32be6181 Make introduction line dynamic 2025-10-14 16:22:19 -07:00
Marcus Moore e2f4a9bf9f Make subject dynamic 2025-10-14 16:20:01 -07:00
Marcus Moore 2db4c1b2e4 Add todo 2025-10-14 16:19:42 -07:00
Marcus Moore 6ed93f4a4f Add asset details 2025-10-14 14:02:21 -07:00
Marcus Moore 9dcee71baf wip 2025-10-08 16:18:54 -07:00
Marcus Moore 9bdd0d1d1e Add admin name 2025-10-08 16:05:55 -07:00
Marcus Moore 13b51d8608 Make acceptance section dynamic 2025-10-08 15:46:36 -07:00
Marcus Moore 19969fee39 Update closing 2025-10-08 15:32:38 -07:00
Marcus Moore 28dc4bf52e Move template to correct directory 2025-10-08 14:13:04 -07:00
Marcus Moore 9a380ac3d4 Extract intro text 2025-10-08 14:12:35 -07:00
Marcus Moore 17a26b43f0 Naively send email 2025-10-08 14:01:07 -07:00
Marcus Moore 3c42acebf0 Scaffold new listener 2025-09-30 15:11:12 -07:00
Marcus Moore 3327b2ce3c Add assertions 2025-09-30 13:03:24 -07:00
Godfrey M 8c56aa9575 changed the wrong language file 2025-09-30 12:42:46 -07:00
Godfrey M d528126f15 right hand table loading, need styling and translations 2025-09-30 12:31:44 -07:00
akemidx 64d0e3928c clean erroneous added space 2025-09-30 13:11:38 -04:00
Marcus Moore 7017a0cae1 WIP: introduce event 2025-09-25 16:23:43 -07:00
Marcus Moore a40e4d7d04 Begin experimenting with context 2025-09-25 15:43:04 -07:00
Marcus Moore 9e3b56f4bc Add failing test 2025-09-25 15:41:37 -07:00
akemidx 3492ed54de i'm dumb, fixed query 2025-09-10 19:05:28 -04:00
akemidx 1455281957 updated to outside window 2025-09-10 18:49:04 -04:00
akemidx e1de57384e field for number choice 2025-08-26 18:03:47 -04:00
akemidx c95462328a selected value(s) 2025-08-19 18:35:07 -04:00
akemidx 84fc89250a backend works, no save yet 2025-08-19 14:30:26 -04:00
akemidx a80f52cbf4 putting dropdown back 2025-08-18 19:47:26 -04:00
akemidx 7ce324a3a5 controller 2025-08-14 17:42:19 -04:00
akemidx 7624082b29 dropdown 2025-08-13 18:07:39 -04:00
akemidx 6d3bba696a first front end bit 2025-08-12 19:14:11 -04:00
179 changed files with 47789 additions and 4473 deletions
+1 -1
View File
@@ -82,7 +82,7 @@ jobs:
- name: Upload Laravel logs as artifacts
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: laravel-logs-php-${{ matrix.php-version }}-run-${{ github.run_attempt }}
path: |
+1 -1
View File
@@ -81,7 +81,7 @@ jobs:
- name: Upload Laravel logs as artifacts
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: laravel-logs-php-${{ matrix.php-version }}-run-${{ github.run_attempt }}
path: |
+1 -1
View File
@@ -67,7 +67,7 @@ jobs:
- name: Upload Laravel logs as artifacts
if: always()
uses: actions/upload-artifact@v6
uses: actions/upload-artifact@v7
with:
name: laravel-logs-php-${{ matrix.php-version }}-run-${{ github.run_attempt }}
path: |
@@ -0,0 +1,24 @@
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
class CheckoutablesCheckedOutInBulk
{
use Dispatchable, SerializesModels;
public function __construct(
public Collection $assets,
public Model $target,
public User $admin,
public string $checkout_at,
public string $expected_checkin,
public string $note,
) {
}
}
+2
View File
@@ -162,6 +162,8 @@ class Handler extends ExceptionHandler
$route = 'licenses.index';
} elseif (($route === 'customfieldsets.index') || ($route === 'customfields.index')) {
$route = 'fields.index';
} elseif ($route == 'actionlogs.index') {
$route = 'home';
}
return redirect()
+1
View File
@@ -12,6 +12,7 @@ class IconHelper
case 'checkin':
return 'fa-solid fa-rotate-right';
case 'edit':
case 'update':
return 'fas fa-pencil-alt';
case 'clone':
return 'far fa-clone';
@@ -98,24 +98,52 @@ class LicenseSeatsController extends Controller
*/
public function update(Request $request, $licenseId, $seatId) : JsonResponse | array
{
$validated = $this->validate($request, [
'assigned_to' => [
'sometimes',
'int',
'nullable',
'prohibits:asset_id',
// must be a valid user or null to unassign
function ($attribute, $value, $fail) {
if (!is_null($value) && !User::where('id', $value)->whereNull('deleted_at')->exists()) {
$fail('The selected assigned_to is invalid.');
}
},
],
'asset_id' => [
'sometimes',
'int',
'nullable',
'prohibits:assigned_to',
// must be a valid asset or null to unassign
function ($attribute, $value, $fail) {
if (!is_null($value) && !Asset::where('id', $value)->whereNull('deleted_at')->exists()) {
$fail('The selected asset_id is invalid.');
}
},
],
'notes' => 'sometimes|string|nullable',
]);
$this->authorize('checkout', License::class);
$licenseSeat = LicenseSeat::with(['license', 'asset', 'user'])->find($seatId);
if (! $licenseSeat = LicenseSeat::find($seatId)) {
if (!$licenseSeat) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Seat not found'));
}
$license = $licenseSeat->license()->first();
$license = $licenseSeat->license;
if (!$license || $license->id != intval($licenseId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Seat does not belong to the specified license'));
}
$oldUser = $licenseSeat->user()->first();
$oldAsset = $licenseSeat->asset()->first();
$oldUser = $licenseSeat->user;
$oldAsset = $licenseSeat->asset;
// attempt to update the license seat
$licenseSeat->fill($request->all());
$licenseSeat->created_by = auth()->id();
$licenseSeat->fill($validated);
// check if this update is a checkin operation
// 1. are relevant fields touched at all?
@@ -140,12 +168,17 @@ class LicenseSeatsController extends Controller
if ($licenseSeat->isDirty('assigned_to')) {
$target = $is_checkin ? $oldUser : User::find($licenseSeat->assigned_to);
}
if ($licenseSeat->isDirty('asset_id')) {
$target = $is_checkin ? $oldAsset : Asset::find($licenseSeat->asset_id);
}
if ($assignmentTouched && is_null($target)){
return response()->json(Helper::formatStandardApiResponse('error', null, 'Target not found'));
// if both asset_id and assigned_to are null then we are "checking-in"
// a related model that does not exist (possible purged or bad data).
if (!is_null($request->input('asset_id')) || !is_null($request->input('assigned_to'))) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Target not found'));
}
}
if ($licenseSeat->save()) {
@@ -155,6 +188,7 @@ class LicenseSeatsController extends Controller
$licenseSeat->unreassignable_seat = true;
$licenseSeat->save();
}
// todo: skip if target is null?
$licenseSeat->logCheckin($target, $licenseSeat->notes);
} else {
// in this case, relevant fields are touched but it's not a checkin operation. so it must be a checkout operation.
@@ -82,6 +82,8 @@ class MaintenancesController extends Controller
'location',
'is_warranty',
'status_label',
'model',
'model_number',
];
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -100,6 +102,12 @@ class MaintenancesController extends Controller
case 'asset_name':
$maintenances = $maintenances->OrderByAssetName($order);
break;
case 'model':
$maintenances = $maintenances->OrderByAssetModelName($order);
break;
case 'model_number':
$maintenances = $maintenances->OrderByAssetModelNumber($order);
break;
case 'serial':
$maintenances = $maintenances->OrderByAssetSerial($order);
break;
@@ -188,7 +188,7 @@ class UploadedFilesController extends Controller
// Check the permissions to make sure the user can view the object
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
$this->authorize('update', self::$map_object_type[$object_type]);
$this->authorize('update', $object);
if (!$object) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_upload_status.invalid_object')));
+45 -17
View File
@@ -450,10 +450,18 @@ class UsersController extends Controller
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the superuser permission if the API user isn't a superadmin
if (! auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
if ((is_array($permissions_array)) && (array_key_exists('superuser', $permissions_array))) {
unset($permissions_array['superuser']);
}
}
if (!auth()->user()->isAdmin()) {
if ((is_array($permissions_array)) && (array_key_exists('admin', $permissions_array))) {
unset($permissions_array['admin']);
}
}
$user->permissions = $permissions_array;
}
@@ -530,8 +538,6 @@ class UsersController extends Controller
*/
public function update(SaveUserRequest $request, User $user): JsonResponse
{
$this->authorize('update', User::class);
$this->authorize('update', $user);
/**
@@ -567,11 +573,43 @@ class UsersController extends Controller
$user->activated = $request->input('activated');
}
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
$orig_permissions_array = $user->decodePermissions();
// Strip out the individual superuser permission if the API user isn't a superadmin
if (!auth()->user()->isSuperUser()) {
if (is_array($orig_permissions_array)) {
if (array_key_exists('superuser', $orig_permissions_array)) {
$permissions_array['superuser'] = $orig_permissions_array['superuser'];
}
}
}
// Strip out the individual admin permission if the API user isn't an admin
if ((!auth()->user()->isAdmin()) && (!auth()->user()->isSuperUser())) {
if (is_array($orig_permissions_array)) {
if (array_key_exists('admin', $orig_permissions_array)) {
$permissions_array['admin'] = $orig_permissions_array['admin'];
}
}
}
// This is going to update the whole thing, not just what was passed
$user->permissions = $permissions_array;
}
}
// We need to use has() instead of filled()
// here because we need to overwrite permissions
// if someone needs to null them out
if ($request->filled('display_name')) {
$user->display_name = $request->input('display_name');
@@ -586,17 +624,7 @@ class UsersController extends Controller
}
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the individual superuser permission if the API user isn't a superadmin
if (!auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->permissions = $permissions_array;
}
if ($request->has('location_id')) {
// Update the location of any assets checked out to this user
@@ -2,6 +2,7 @@
namespace App\Http\Controllers\Assets;
use App\Events\CheckoutablesCheckedOutInBulk;
use App\Helpers\Helper;
use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
@@ -12,6 +13,7 @@ use App\Models\Setting;
use App\View\Label;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
@@ -644,6 +646,8 @@ class BulkAssetsController extends Controller
*/
public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse | ModelNotFoundException
{
Context::add('action', 'bulk_asset_checkout');
$this->authorize('checkout', Asset::class);
try {
@@ -730,6 +734,15 @@ class BulkAssetsController extends Controller
});
if (! $errors) {
CheckoutablesCheckedOutInBulk::dispatch(
$assets,
$target,
$admin,
$checkout_at,
$expected_checkin,
e($request->get('note')),
);
// Redirect to the new asset page
return redirect()->to('hardware')->with('success', trans_choice('admin/hardware/message.multi-checkout.success', $asset_ids));
}
+3 -2
View File
@@ -32,15 +32,16 @@ use App\Models\Location;
use App\Models\Maintenance;
use App\Models\Supplier;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use App\Traits\DisablesDebugbar;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth;
abstract class Controller extends BaseController
{
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
use AuthorizesRequests, DisablesDebugbar, DispatchesJobs, ValidatesRequests;
static $map_object_type = [
'accessories' => Accessory::class,
+25 -7
View File
@@ -28,23 +28,41 @@ class HealthController extends BaseController
*/
public function get()
{
try {
if (DB::select('select 2 + 2')) {
return response()->json([
'status' => 'ok',
]);
$db_status = 'ok';
} else {
$db_status = 'Could not connect to database';
}
} catch (\Exception $e) {
\Log::error('Could not connect to database');
return response()->json([
'status' => 'database connection failed',
], 500);
$db_status = 'Could not connect to database';
}
if (is_writable(storage_path('logs'))) {
$filesystem_status = 'ok';
} else {
$filesystem_status = 'Could not write to storage/logs';
}
if (($filesystem_status!='ok') || ($db_status!='ok')) {
return response()->json([
'status' =>
[
'database' => $db_status,
'filesystem' => $filesystem_status,
]
], 500);
}
return response()->json([
'status' => 'ok',
]);
}
}
@@ -315,7 +315,8 @@ class LicensesController extends Controller
public function getExportLicensesCsv()
{
$this->authorize('view', License::class);
\Debugbar::disable();
$this->disableDebugbar();
$response = new StreamedResponse(function () {
// Open output stream
+1 -1
View File
@@ -38,7 +38,7 @@ class ModalController extends Controller
if (in_array($type, $allowed_types)) {
$view = view("modals.${type}");
$view = view("modals.{$type}");
if ($type == "statuslabel") {
$view->with('statuslabel_types', Helper::statusTypeList());
@@ -19,7 +19,8 @@ class ReportTemplatesController extends Controller
$report = $request->user()->reportTemplates()->create([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
'options' => $request->except(['_token', 'name', 'is_shared']),
'is_shared' => $request->has('is_shared'),
]);
session()->flash('success', trans('admin/reports/message.create.success'));
@@ -45,6 +46,12 @@ class ReportTemplatesController extends Controller
{
$this->authorize('reports.view');
if ($reportTemplate->created_by != auth()->id()) {
return redirect()
->route('report-templates.show', $reportTemplate)
->withError(trans('general.report_not_editable'));
}
return view('reports/custom', [
'customfields' => CustomField::get(),
'template' => $reportTemplate,
@@ -55,13 +62,29 @@ class ReportTemplatesController extends Controller
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
if ($reportTemplate->created_by != auth()->id()) {
return redirect()
->route('report-templates.show', $reportTemplate)
->withError(trans('general.report_not_editable'));
}
$reportTemplate->update([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
$properties = [
'name' => $request->input('name'),
'options' => Arr::except($request->all(), ['_token', 'id', 'name', 'is_shared']),
'is_shared' => $reportTemplate->is_shared,
];
if ($reportTemplate->created_by == $request->user()->id) {
$properties['is_shared'] = $request->boolean('is_shared');
}
$reportTemplate->fill($properties);
if ($reportTemplate->isInvalid()) {
return redirect()->back()->withInput()->withErrors($reportTemplate->getErrors());
}
$reportTemplate->save();
session()->flash('success', trans('admin/reports/message.update.success'));
@@ -72,6 +95,12 @@ class ReportTemplatesController extends Controller
{
$this->authorize('reports.view');
if ($reportTemplate->creator()->isNot(auth()->user())) {
return redirect()
->route('report-templates.show', $reportTemplate)
->withError(trans('general.generic_model_not_found', ['model' => 'report template']));
}
$reportTemplate->delete();
return redirect()->route('reports/custom')
+60 -4
View File
@@ -40,6 +40,7 @@ use League\Csv\EscapeFormula;
use App\Http\Requests\CustomAssetReportRequest;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\RedirectResponse;
use function Livewire\before;
/**
* This controller handles all actions related to Reports for
@@ -242,7 +243,8 @@ class ReportsController extends Controller
ini_set('max_execution_time', 12000);
$this->authorize('reports.view');
\Debugbar::disable();
$this->disableDebugbar();
$response = new StreamedResponse(function () {
Log::debug('Starting streamed response');
@@ -437,8 +439,8 @@ class ReportsController extends Controller
ini_set('max_execution_time', env('REPORT_TIME_LIMIT', 12000)); //12000 seconds = 200 minutes
$this->authorize('reports.view');
$this->disableDebugbar();
\Debugbar::disable();
$customfields = CustomField::get();
$response = new StreamedResponse(function () use ($customfields, $request) {
Log::debug('Starting streamed response');
@@ -452,6 +454,10 @@ class ReportsController extends Controller
$header = [];
if($request->filled('is_shared')) {
$header[] = trans('admin/reports/general.share_template');
}
if ($request->filled('id')) {
$header[] = trans('general.id');
}
@@ -549,6 +555,14 @@ class ReportsController extends Controller
$header[] = 'Username';
}
if ($request->filled('user_company')) {
$header[] = trans('admin/reports/general.custom_export.user_company');
}
if ($request->filled('email')) {
$header[] = 'Email';
}
if ($request->filled('employee_num')) {
$header[] = 'Employee No.';
}
@@ -589,6 +603,10 @@ class ReportsController extends Controller
$header[] = trans('admin/reports/general.custom_export.user_zip');
}
if ($request->filled('target_notes')) {
$header[] = trans('admin/reports/general.custom_export.target_notes');
}
if ($request->filled('status')) {
$header[] = trans('general.status');
}
@@ -646,7 +664,14 @@ class ReportsController extends Controller
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
Log::debug('Added headers: '.$executionTime);
$assets = Asset::select('assets.*')->with(
if($request->filled('is_shared')) {
//to fill with logic for the report template and NOT the assets retrieved by the query
//do we scope here or??
}
$assets = Asset::select('assets.*')->with(
'location', 'assetstatus', 'company', 'defaultLoc', 'assignedTo',
'model.category', 'model.manufacturer', 'supplier');
@@ -753,9 +778,15 @@ class ReportsController extends Controller
$assets->whereBetween('assets.updated_at', [$request->input('last_updated_start'), $request->input('last_updated_end')]);
}
if(($request->filled('last_updated_before'))){
$last_updated_window = Carbon::parse(today()->subDays($request->input('last_updated_before')));
$assets->where('assets.updated_at', '<' , $last_updated_window);
}
if ($request->filled('exclude_archived')) {
$assets->notArchived();
}
if ($request->input('deleted_assets') == 'include_deleted') {
$assets->withTrashed();
}
@@ -763,7 +794,6 @@ class ReportsController extends Controller
$assets->onlyTrashed();
}
Log::debug($assets->toSql());
$assets->orderBy('assets.id', 'ASC')->chunk(500, function ($assets) use ($handle, $customfields, $request) {
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
@@ -882,6 +912,23 @@ class ReportsController extends Controller
}
}
if ($request->filled('user_company')) {
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto->company) ? $asset->assignedto->company->display_name : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->filled('email')) {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->email : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->filled('employee_num')) {
// Only works if we're checked out to a user, not anything else.
if ($asset->checkedOutToUser()) {
@@ -963,6 +1010,15 @@ class ReportsController extends Controller
}
}
if ($request->filled('target_notes')) {
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->notes : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->filled('status')) {
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
}
@@ -133,7 +133,7 @@ class UploadedFilesController extends Controller
// Check the permissions to make sure the user can view the object
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
$this->authorize('update', self::$map_object_type[$object_type]);
$this->authorize('update', $object);
if (!$object) {
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
+17 -3
View File
@@ -122,9 +122,22 @@ class UsersController extends Controller
// Strip out the superuser permission if the user isn't a superadmin
$permissions_array = $request->input('permission');
if (! auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
// Strip out the individual superuser permission if the API user isn't a superadmin
if (!auth()->user()->isSuperUser()) {
if ((is_array($permissions_array)) && (array_key_exists('superuser', $permissions_array))) {
unset($permissions_array['superuser']);
}
}
// Strip out the individual admin permission if the API user isn't an admin
if (!auth()->user()->isAdmin()) {
if ((is_array($permissions_array)) && (array_key_exists('admin', $permissions_array))) {
unset($permissions_array['admin']);
}
}
$user->permissions = json_encode($permissions_array);
// we have to invoke the form request here to handle image uploads
@@ -510,7 +523,8 @@ class UsersController extends Controller
public function getExportUserCsv()
{
$this->authorize('view', User::class);
\Debugbar::disable();
$this->disableDebugbar();
$response = new StreamedResponse(function () {
// Open output stream
@@ -206,7 +206,7 @@ class ViewAssetsController extends Controller
if ($fullItemType == Asset::class) {
$data['item_url'] = route('hardware.show', $item->id);
} else {
$data['item_url'] = route("view/${itemType}", $item->id);
$data['item_url'] = route("view/{$itemType}", $item->id);
}
$settings = Setting::getSettings();
+1 -1
View File
@@ -34,7 +34,7 @@ class SaveUserRequest extends FormRequest
{
$rules = [
'department_id' => 'nullable|integer|exists:departments,id',
'manager_id' => 'nullable|exists:users,id',
'manager_id' => 'nullable|integer|exists:users,id',
'company_id' => ['nullable', 'integer', 'exists:companies,id']
];
+1 -1
View File
@@ -211,7 +211,7 @@ class AssetsTransformer
return $asset->assigned ? [
'id' => (int) $asset->assigned->id,
'username' => e($asset->assigned->username),
'name' => e($asset->assigned->getFullNameAttribute()),
'name' => e($asset->assigned->display_name),
'first_name'=> e($asset->assigned->first_name),
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
@@ -63,7 +63,7 @@ class DepreciationReportTransformer
*/
if (($asset->model) && ($asset->model->depreciation) && ($asset->model->depreciation->months !== 0)) {
$depreciated_value = Helper::formatCurrencyOutput($asset->getDepreciatedValue());
$monthly_depreciation =Helper::formatCurrencyOutput($asset->purchase_cost / $asset->model->depreciation->months);
$monthly_depreciation =Helper::formatCurrencyOutput($asset->getMonthlyDepreciation());
$diff = Helper::formatCurrencyOutput(($asset->purchase_cost - $asset->getDepreciatedValue()));
}
else if($asset->model->eol !== null) {
@@ -37,7 +37,8 @@ class MaintenancesTransformer
'image' => ($assetmaintenance->image != '') ? Storage::disk('public')->url('maintenances/'.e($assetmaintenance->image)) : null,
'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [
'id' => (int) $assetmaintenance->asset->model->id,
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null,
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name) : null,
'model_number'=> ($assetmaintenance->asset->model->model_number) ? e($assetmaintenance->asset->model->model_number) : null,
] : null,
'status_label' => (($assetmaintenance->asset) && ($assetmaintenance->asset->assetstatus)) ? [
'id' => (int) $assetmaintenance->asset->assetstatus->id,
+1 -1
View File
@@ -141,7 +141,7 @@ class UsersTransformer
'id' => (int) $user->id,
'image' => e($user->present()->gravatar) ?? null,
'type' => 'user',
'name' => e($user->getFullNameAttribute()),
'name' => e($user->display_name),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
+13 -3
View File
@@ -33,6 +33,7 @@ use App\Notifications\CheckoutConsumableNotification;
use App\Notifications\CheckoutLicenseSeatNotification;
use GuzzleHttp\Exception\ClientException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Context;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Notification;
use Exception;
@@ -128,7 +129,7 @@ class CheckoutableListener
->notify($this->getCheckoutNotification($event, $acceptance));
}
} catch (ClientException $e) {
$status = optional($e->getResponse()->getStatusCode());
$status = $e->getResponse()->getStatusCode();
if (strpos($e->getMessage(), 'channel_not_found') !== false) {
Log::warning(Setting::getSettings()->webhook_selected . " notification failed: " . $e->getMessage());
@@ -231,7 +232,7 @@ class CheckoutableListener
->notify($this->getCheckinNotification($event));
}
} catch (ClientException $e) {
$status = optional($e->getResponse()->getStatusCode());
$status = $e->getResponse()->getStatusCode();
if (strpos($e->getMessage(), 'channel_not_found') !== false) {
Log::warning(Setting::getSettings()->webhook_selected . " notification failed: " . $e->getMessage());
@@ -441,12 +442,17 @@ class CheckoutableListener
private function shouldSendCheckoutEmailToUser(Model $checkoutable): bool
{
/**
* Send an email if any of the following conditions are met:
* Send an email if we didn't get here from a bulk checkout
* and any of the following conditions are met:
* 1. The asset requires acceptance
* 2. The item has a EULA
* 3. The item should send an email at check-in/check-out
*/
if (Context::get('action') === 'bulk_asset_checkout') {
return false;
}
if ($checkoutable->requireAcceptance()) {
return true;
}
@@ -464,6 +470,10 @@ class CheckoutableListener
private function shouldSendEmailToAlertAddress($acceptance = null): bool
{
if (Context::get('action') === 'bulk_asset_checkout') {
return false;
}
$setting = Setting::getSettings();
if (!$setting) {
@@ -0,0 +1,154 @@
<?php
namespace App\Listeners;
use App\Events\CheckoutablesCheckedOutInBulk;
use App\Mail\BulkAssetCheckoutMail;
use App\Models\Asset;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Exception;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Mail;
class CheckoutablesCheckedOutInBulkListener
{
public function subscribe($events)
{
$events->listen(
CheckoutablesCheckedOutInBulk::class,
CheckoutablesCheckedOutInBulkListener::class
);
}
public function handle(CheckoutablesCheckedOutInBulk $event): void
{
$notifiableUser = $this->getNotifiableUser($event);
$shouldSendEmailToUser = $this->shouldSendCheckoutEmailToUser($notifiableUser, $event->assets);
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress($event->assets);
if ($shouldSendEmailToUser && $notifiableUser) {
try {
Mail::to($notifiableUser)->send(new BulkAssetCheckoutMail(
$event->assets,
$event->target,
$event->admin,
$event->checkout_at,
$event->expected_checkin,
$event->note,
));
Log::info('BulkAssetCheckoutMail sent to checkout target');
} catch (Exception $e) {
Log::debug("Exception caught during BulkAssetCheckoutMail to target: " . $e->getMessage());
}
}
if ($shouldSendEmailToAlertAddress && Setting::getSettings()->admin_cc_email) {
try {
Mail::to(Setting::getSettings()->admin_cc_email)->send(new BulkAssetCheckoutMail(
$event->assets,
$event->target,
$event->admin,
$event->checkout_at,
$event->expected_checkin,
$event->note,
));
Log::info('BulkAssetCheckoutMail sent to admin_cc_email');
} catch (Exception $e) {
Log::debug("Exception caught during BulkAssetCheckoutMail to admin_cc_email: " . $e->getMessage());
}
}
}
private function shouldSendCheckoutEmailToUser(?User $user, Collection $assets): bool
{
if (!$user?->email) {
return false;
}
if ($this->hasAssetWithEula($assets)) {
return true;
}
if ($this->hasAssetWithCategorySettingToSendEmail($assets)) {
return true;
}
return $this->hasAssetThatRequiresAcceptance($assets);
}
private function shouldSendEmailToAlertAddress(Collection $assets): bool
{
$setting = Setting::getSettings();
if (!$setting) {
return false;
}
if ($setting->admin_cc_always) {
return true;
}
if (!$this->hasAssetThatRequiresAcceptance($assets)) {
return false;
}
return (bool) $setting->admin_cc_email;
}
private function hasAssetWithEula(Collection $assets): bool
{
foreach ($assets as $asset) {
if ($asset->getEula()) {
return true;
}
}
return false;
}
private function hasAssetWithCategorySettingToSendEmail(Collection $assets): bool
{
foreach ($assets as $asset) {
if ($asset->checkin_email()) {
return true;
}
}
return false;
}
private function hasAssetThatRequiresAcceptance(Collection $assets): bool
{
foreach ($assets as $asset) {
if ($asset->requireAcceptance()) {
return true;
}
}
return false;
}
private function getNotifiableUser(CheckoutablesCheckedOutInBulk $event): ?Model
{
$target = $event->target;
if ($target instanceof Asset) {
$target->load('assignedTo');
return $target->assignedto;
}
if ($target instanceof Location) {
return $target->manager;
}
return $target;
}
}
+1 -1
View File
@@ -84,7 +84,7 @@ class OauthClients extends Component
]);
$client = app(ClientRepository::class)->find($editClientId->id);
if ($client->created_by == auth()->id()) {
if ($client->user_id == auth()->id()) {
$client->name = $this->editName;
$client->redirect = $this->editRedirect;
$client->save();
+165
View File
@@ -0,0 +1,165 @@
<?php
namespace App\Mail;
use App\Models\Asset;
use App\Models\CustomField;
use App\Models\Location;
use App\Models\User;
use Illuminate\Bus\Queueable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Collection;
class BulkAssetCheckoutMail extends Mailable
{
use Queueable, SerializesModels;
public bool $requires_acceptance;
public Collection $assetsByCategory;
public function __construct(
public Collection $assets,
public Model $target,
public User $admin,
public string $checkout_at,
public string $expected_checkin,
public string $note,
) {
$this->requires_acceptance = $this->requiresAcceptance();
$this->loadCustomFieldsOnAssets();
$this->loadEulasOnAssets();
$this->assetsByCategory = $this->groupAssetsByCategory();
}
public function envelope(): Envelope
{
return new Envelope(
subject: $this->getSubject(),
);
}
public function content(): Content
{
return new Content(
markdown: 'mail.markdown.bulk-asset-checkout-mail',
with: [
'introduction' => $this->getIntroduction(),
'requires_acceptance' => $this->requires_acceptance,
'requires_acceptance_info' => $this->getRequiresAcceptanceInfo(),
'requires_acceptance_prompt' => $this->getRequiresAcceptancePrompt(),
'singular_eula' => $this->getSingularEula(),
],
);
}
public function attachments(): array
{
return [];
}
private function getSubject(): string
{
if ($this->assets->count() > 1) {
return ucfirst(trans('general.assets_checked_out_count'));
}
return trans('mail.Asset_Checkout_Notification', ['tag' => $this->assets->first()->asset_tag]);
}
private function loadCustomFieldsOnAssets(): void
{
$this->assets = $this->assets->map(function (Asset $asset) {
$fields = $asset->model?->fieldset?->fields->filter(function (CustomField $field) {
return $field->show_in_email && !$field->field_encrypted;
});
$asset->setRelation('fields', $fields);
return $asset;
});
}
private function loadEulasOnAssets(): void
{
$this->assets = $this->assets->map(function (Asset $asset) {
$asset->eula = $asset->getEula();
return $asset;
});
}
private function groupAssetsByCategory(): Collection
{
return $this->assets->groupBy(fn($asset) => $asset->model->category->id);
}
private function getIntroduction(): string
{
if ($this->target instanceof Location) {
return trans_choice('mail.new_item_checked_location', $this->assets->count(), ['location' => $this->target->name]);
}
return trans_choice('mail.new_item_checked', $this->assets->count());
}
private function getRequiresAcceptanceInfo(): ?string
{
if (!$this->requires_acceptance) {
return null;
}
return trans_choice('mail.items_checked_out_require_acceptance', $this->assets->count());
}
private function getRequiresAcceptancePrompt(): ?string
{
if (!$this->requires_acceptance) {
return null;
}
$acceptanceUrl = $this->assets->count() === 1
? route('account.accept.item', $this->assets->first())
: route('account.accept');
return
sprintf(
'**[✔ %s](%s)**',
trans_choice('mail.click_here_to_review_terms_and_accept_item', $this->assets->count()),
$acceptanceUrl,
);
}
private function getSingularEula()
{
// get unique categories from all assets
$categories = $this->assets->pluck('model.category.id')->unique();
// if assets do not have the same category then return early...
if ($categories->count() > 1) {
return null;
}
// if assets do have the same category then return the shared EULA
if ($categories->count() === 1) {
return $this->assets->first()->getEula();
}
}
private function requiresAcceptance(): bool
{
foreach ($this->assets as $asset) {
if ($asset->requireAcceptance()) {
return true;
}
}
return false;
}
}
-1
View File
@@ -12,7 +12,6 @@ use Illuminate\Mail\Mailables\Address;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Queue\SerializesModels;
class CheckoutAssetMail extends BaseMailable
+9 -8
View File
@@ -2,7 +2,6 @@
namespace App\Models;
use App\Helpers\Helper;
use App\Models\Traits\Acceptable;
use App\Models\Traits\CompanyableTrait;
use App\Models\Traits\HasUploads;
@@ -21,21 +20,23 @@ use Watson\Validating\ValidatingTrait;
*/
class Accessory extends SnipeModel
{
use HasFactory;
protected $presenter = \App\Presenters\AccessoryPresenter::class;
use Acceptable;
use CompanyableTrait;
use HasFactory;
use HasUploads;
use Loggable, Presentable;
use Loggable;
use Presentable;
use Searchable;
use SoftDeletes;
use ValidatingTrait;
protected $table = 'accessories';
protected $casts = [
'purchase_date' => 'datetime',
'requestable' => 'boolean', ];
use Searchable;
use Acceptable;
protected $presenter = \App\Presenters\AccessoryPresenter::class;
/**
* The attributes that should be included when searching the model.
@@ -80,7 +81,7 @@ class Accessory extends SnipeModel
* @var bool
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
/**
* The attributes that are mass assignable.
+1
View File
@@ -1916,6 +1916,7 @@ class Asset extends Depreciable
function ($query) use ($search_val) {
$query->where('users.first_name', 'LIKE', '%'.$search_val.'%')
->orWhere('users.last_name', 'LIKE', '%'.$search_val.'%')
->orWhere('users.display_name', 'LIKE', '%'.$search_val.'%')
->orWhere('users.username', 'LIKE', '%'.$search_val.'%');
}
);
+26
View File
@@ -13,6 +13,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Session;
use Watson\Validating\ValidatingTrait;
@@ -158,6 +159,14 @@ class License extends Depreciable
);
}
public function isDeletable()
{
return Gate::allows('delete', $this)
&& ($this->free_seats_count == $this->seats)
&& ($this->deleted_at == '');
}
protected function terminatesFormattedDate(): Attribute
{
@@ -582,6 +591,23 @@ class License extends Depreciable
->whereNull('deleted_at');
}
/**
* This is really dumb - needs to be refactored, since we have ~3 diff methods that do almost the same thing
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v2.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function numRemaining()
{
return $this->licenseSeatsRelation()
->whereNull('asset_id')
->whereNull('assigned_to')
->where('unreassignable_seat', '=', false)
->whereNull('deleted_at')
->count();
}
/**
* Sets the available seats attribute
*
+23 -9
View File
@@ -15,14 +15,18 @@ use Watson\Validating\ValidatingTrait;
class Location extends SnipeModel
{
use HasFactory;
use CompanyableTrait;
use HasFactory;
use HasUploads;
use Loggable;
use Presentable;
use Searchable;
use SoftDeletes;
use UniqueUndeletedTrait;
use ValidatingTrait;
protected $presenter = \App\Presenters\LocationPresenter::class;
use Presentable;
use SoftDeletes;
use HasUploads;
protected $table = 'locations';
protected $rules = [
@@ -53,8 +57,7 @@ class Location extends SnipeModel
* @var bool
*/
protected $injectUniqueIdentifier = true;
use ValidatingTrait;
use UniqueUndeletedTrait;
/**
* The attributes that are mass assignable.
@@ -80,16 +83,28 @@ class Location extends SnipeModel
'tag_color',
'notes',
];
protected $hidden = ['user_id'];
use Searchable;
/**
* The attributes that should be included when searching the model.
*
* @var array
*/
protected $searchableAttributes = ['name', 'address', 'city', 'state', 'zip', 'created_at', 'ldap_ou', 'phone', 'fax', 'notes'];
protected $searchableAttributes =
[
'name',
'address',
'city',
'state',
'zip',
'created_at',
'ldap_ou',
'phone',
'fax',
'notes'
];
/**
* The relations and their attributes that should be included when searching the model.
@@ -114,7 +129,6 @@ class Location extends SnipeModel
*/
public function isDeletable()
{
return Gate::allows('delete', $this)
&& ($this->deleted_at == '')
&& (($this->assets_count ?? $this->assets()->count()) === 0)
+14
View File
@@ -323,4 +323,18 @@ class Maintenance extends SnipeModel implements ICompanyableChild
{
return $query->leftJoin('users as admin_sort', 'maintenances.created_by', '=', 'admin_sort.id')->select('maintenances.*')->orderBy('admin_sort.first_name', $order)->orderBy('admin_sort.last_name', $order);
}
public function scopeOrderByAssetModelName($query, $order)
{
return $query->join('assets as maintained_asset', 'maintenances.asset_id', '=', 'maintained_asset.id')
->leftjoin('models as maintained_asset_model', 'maintained_asset_model.id', '=', 'maintained_asset.model_id')
->orderBy('maintained_asset_model.name', $order);
}
public function scopeOrderByAssetModelNumber($query, $order)
{
return $query->join('assets as maintained_asset', 'maintenances.asset_id', '=', 'maintained_asset.id')
->leftjoin('models as maintained_asset_model', 'maintained_asset_model.id', '=', 'maintained_asset.model_id')
->orderBy('maintained_asset_model.model_number', $order);
}
}
+14 -2
View File
@@ -2,6 +2,7 @@
namespace App\Models;
use App\Http\Traits\UniqueUndeletedTrait;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
@@ -13,36 +14,47 @@ class ReportTemplate extends Model
{
use HasFactory;
use SoftDeletes;
use UniqueUndeletedTrait;
use ValidatingTrait;
protected $table = 'report_templates';
protected $casts = [
'options' => 'array',
'is_shared' => 'boolean',
];
protected $fillable = [
'created_by',
'name',
'options',
'is_shared',
];
protected $rules = [
'name' => [
'required',
'string',
'unique_undeleted:report_templates,name',
],
'options' => [
'required',
'array',
],
'is_shared' => [
'boolean',
],
];
protected static function booted()
{
// Scope to current user
// Scope to current user or if template is shared
static::addGlobalScope(
'current_user', function (Builder $builder) {
if (auth()->check()) {
$builder->where('created_by', auth()->id());
$builder->where('created_by', auth()->id())
->orWhere('is_shared', 1);
}
}
);
+1 -1
View File
@@ -20,7 +20,7 @@ trait CompanyableTrait
if (__CLASS__ != 'App\Models\Location') {
static::addGlobalScope(new CompanyableScope);
} else {
if (Setting::getSettings()->scope_locations_fmcs == 1) {
if (Setting::getSettings()?->scope_locations_fmcs == 1) {
static::addGlobalScope(new CompanyableScope);
}
}
+86
View File
@@ -0,0 +1,86 @@
<?php
namespace App\Observers;
use App\Models\Actionlog;
use App\Models\Location;
class LocationObserver
{
/**
* Listen to the User created event.
*
* @param Location $location
* @return void
*/
public function updating(Location $location)
{
$changed = [];
foreach ($location->getRawOriginal() as $key => $value) {
// Check and see if the value changed
if ($location->getRawOriginal()[$key] != $location->getAttributes()[$key]) {
$changed[$key]['old'] = $location->getRawOriginal()[$key];
$changed[$key]['new'] = $location->getAttributes()[$key];
}
}
if (count($changed) > 0) {
$logAction = new Actionlog();
$logAction->item_type = Location::class;
$logAction->item_id = $location->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
}
}
/**
* Listen to the Location created event when
* a new location is created.
*
* @param Location $location
* @return void
*/
public function created(Location $location)
{
$logAction = new Actionlog();
$logAction->item_type = Location::class;
$logAction->item_id = $location->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
if($location->imported) {
$logAction->setActionSource('importer');
}
$logAction->logaction('create');
}
/**
* Listen to the Location deleting event.
*
* @param Location $location
* @return void
*/
public function deleting(Location $location)
{
$logAction = new Actionlog();
$logAction->item_type = Location::class;
$logAction->item_id = $location->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->logaction('delete');
}
public function restoring(Location $location)
{
$logAction = new Actionlog();
$logAction->item_type = Location::class;
$logAction->item_id = $location->id;
$logAction->created_at = date('Y-m-d H:i:s');
$logAction->created_by = auth()->id();
$logAction->logaction('restore');
}
}
+2
View File
@@ -181,6 +181,7 @@ class AccessoryPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'accessoriesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
@@ -250,6 +251,7 @@ class AccessoryPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'accessoriesInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+1
View File
@@ -268,6 +268,7 @@ class AssetAuditPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'hardwareAuditFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
+2
View File
@@ -17,6 +17,7 @@ class AssetModelPresenter extends Presenter
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -214,6 +215,7 @@ class AssetModelPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'modelsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
+3
View File
@@ -23,6 +23,7 @@ class AssetPresenter extends Presenter
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print'
], [
'field' => 'id',
'searchable' => false,
@@ -358,6 +359,7 @@ class AssetPresenter extends Presenter
'visible' => true,
'formatter' => 'hardwareInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
$layout[] = [
@@ -368,6 +370,7 @@ class AssetPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'hardwareActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
+3
View File
@@ -18,6 +18,8 @@ class CategoryPresenter extends Presenter
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -127,6 +129,7 @@ class CategoryPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'categoriesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+1
View File
@@ -152,6 +152,7 @@ class CompanyPresenter extends Presenter
'visible' => true,
'formatter' => 'companiesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+2
View File
@@ -186,6 +186,7 @@ class ComponentPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'componentsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
@@ -241,6 +242,7 @@ class ComponentPresenter extends Presenter
'visible' => true,
'formatter' => 'componentsInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+1
View File
@@ -181,6 +181,7 @@ class ConsumablePresenter extends Presenter
'visible' => true,
'formatter' => 'consumablesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+1
View File
@@ -111,6 +111,7 @@ class DepartmentPresenter extends Presenter
'visible' => true,
'formatter' => 'departmentsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+1
View File
@@ -97,6 +97,7 @@ class DepreciationPresenter extends Presenter
'visible' => true,
'formatter' => 'depreciationsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+1
View File
@@ -69,6 +69,7 @@ class GroupPresenter extends Presenter
'visible' => true,
'formatter' => 'groupsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+3
View File
@@ -213,6 +213,7 @@ class LicensePresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'licensesActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
];
return json_encode($layout);
@@ -307,6 +308,8 @@ class LicensePresenter extends Presenter
'title' => trans('general.checkin').'/'.trans('general.checkout'),
'visible' => true,
'formatter' => 'licenseSeatInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+4
View File
@@ -20,6 +20,7 @@ class LocationPresenter extends Presenter
'formatter' => 'checkboxEnabledFormatter',
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
], [
'field' => 'id',
'searchable' => false,
@@ -266,6 +267,8 @@ class LocationPresenter extends Presenter
'title' => trans('table.actions'),
'visible' => true,
'formatter' => 'locationsActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
@@ -334,6 +337,7 @@ class LocationPresenter extends Presenter
'title' => trans('table.actions'),
'formatter' => 'accessoriesInOutFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+8
View File
@@ -81,6 +81,14 @@ class MaintenancesPresenter extends Presenter
'visible' => false,
'formatter' => 'modelsLinkObjFormatter',
], [
'field' => 'model.model_number',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.model_no'),
'visible' => true,
],
[
'field' => 'supplier',
'searchable' => true,
'sortable' => true,
+3
View File
@@ -18,6 +18,8 @@ class ManufacturerPresenter extends Presenter
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -168,6 +170,7 @@ class ManufacturerPresenter extends Presenter
'visible' => true,
'formatter' => 'manufacturersActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+2
View File
@@ -17,6 +17,8 @@ class SupplierPresenter extends Presenter
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print'
],
[
'field' => 'id',
@@ -59,6 +59,8 @@ class UploadedFilesPresenter extends Presenter
'title' => trans('general.download'),
'visible' => true,
'formatter' => 'fileDownloadButtonsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'note',
@@ -93,6 +95,7 @@ class UploadedFilesPresenter extends Presenter
'visible' => true,
'formatter' => 'deleteUploadFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+2
View File
@@ -26,6 +26,7 @@ class UserPresenter extends Presenter
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
'printIgnore' => true,
'class' => 'hidden-print',
],
[
'field' => 'id',
@@ -432,6 +433,7 @@ class UserPresenter extends Presenter
'visible' => true,
'formatter' => 'usersActionsFormatter',
'printIgnore' => true,
'class' => 'hidden-print',
],
];
+11 -8
View File
@@ -7,23 +7,25 @@ use App\Models\Asset;
use App\Models\Component;
use App\Models\Consumable;
use App\Models\License;
use App\Models\Location;
use App\Models\Maintenance;
use App\Models\User;
use App\Models\Setting;
use App\Models\SnipeSCIMConfig;
use App\Models\User;
use App\Observers\AccessoryObserver;
use App\Observers\AssetObserver;
use App\Observers\UserObserver;
use App\Observers\ComponentObserver;
use App\Observers\ConsumableObserver;
use App\Observers\LicenseObserver;
use App\Observers\SettingObserver;
use App\Observers\LocationObserver;
use App\Observers\MaintenanceObserver;
use App\Observers\SettingObserver;
use App\Observers\UserObserver;
use Illuminate\Routing\UrlGenerator;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\URL;
use Illuminate\Support\ServiceProvider;
/**
* This service provider handles setting the observers on models
@@ -68,14 +70,15 @@ class AppServiceProvider extends ServiceProvider
\Illuminate\Pagination\Paginator::useBootstrap();
Schema::defaultStringLength(191);
Asset::observe(AssetObserver::class);
Maintenance::observe(MaintenanceObserver::class);
User::observe(UserObserver::class);
Accessory::observe(AccessoryObserver::class);
Asset::observe(AssetObserver::class);
Component::observe(ComponentObserver::class);
Consumable::observe(ConsumableObserver::class);
License::observe(LicenseObserver::class);
Location::observe(LocationObserver::class);
Maintenance::observe(MaintenanceObserver::class);
Setting::observe(SettingObserver::class);
User::observe(UserObserver::class);
}
/**
+2 -1
View File
@@ -441,7 +441,8 @@ class BreadcrumbsServiceProvider extends ServiceProvider
Breadcrumbs::for('maintenances.edit', fn (Trail $trail, Maintenance $maintenance) =>
$trail->parent('maintenances.index', route('maintenances.index'))
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $maintenance->name]), route('maintenances.edit', $maintenance))
->push($maintenance->name, route('maintenances.show', $maintenance))
->push(trans('general.update', ['name' => $maintenance->name]), route('maintenances.edit', $maintenance))
);
+2
View File
@@ -3,6 +3,7 @@
namespace App\Providers;
use App\Listeners\CheckoutableListener;
use App\Listeners\CheckoutablesCheckedOutInBulkListener;
use App\Listeners\LogListener;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
@@ -31,5 +32,6 @@ class EventServiceProvider extends ServiceProvider
protected $subscribe = [
LogListener::class,
CheckoutableListener::class,
CheckoutablesCheckedOutInBulkListener::class,
];
}
@@ -85,6 +85,10 @@ class SettingsServiceProvider extends ServiceProvider
return 'models/';
});
app()->singleton('assets_upload_url', function () {
return 'assets/';
});
app()->singleton('licenses_upload_url', function () {
return 'licenses/';
});
@@ -179,6 +183,10 @@ class SettingsServiceProvider extends ServiceProvider
return 'components/';
});
app()->singleton('maintenances_upload_url', function () {
return 'maintenances/';
});
// Set the monetary locale to the configured locale to make helper::parseFloat work.
setlocale(LC_MONETARY, config('app.locale'));
setlocale(LC_NUMERIC, config('app.locale'));
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Traits;
trait DisablesDebugbar
{
public function disableDebugbar()
{
if (class_exists(\Fruitcake\LaravelDebugbar\Facades\Debugbar::class)) {
\Fruitcake\LaravelDebugbar\Facades\Debugbar::disable();
}
}
}
+4 -3
View File
@@ -31,7 +31,6 @@
"alek13/slack": "^2.0",
"arietimmerman/laravel-scim-server": "dev-master",
"bacon/bacon-qr-code": "^2.0",
"barryvdh/laravel-debugbar": "^3.13",
"doctrine/cache": "^1.10",
"doctrine/dbal": "^3.1",
"doctrine/instantiator": "^1.3",
@@ -55,7 +54,7 @@
"laravelcollective/html": "6.x-dev",
"league/csv": "^9.7",
"league/flysystem-aws-s3-v3": "^3.0",
"livewire/livewire": "^3.5",
"livewire/livewire": "^4.0",
"neitanod/forceutf8": "^2.0",
"nesbot/carbon": "^3.0",
"nunomaduro/collision": "^8.1",
@@ -84,6 +83,7 @@
"ext-exif": "*"
},
"require-dev": {
"fruitcake/laravel-debugbar": "^4.0",
"larastan/larastan": "^2.9",
"laravel/telescope": "^5.11",
"mockery/mockery": "^1.4",
@@ -125,7 +125,8 @@
"post-autoload-dump": [
"Illuminate\\Foundation\\ComposerScripts::postAutoloadDump",
"@php artisan package:discover --ansi",
"@php artisan vendor:publish --force --tag=livewire:assets --ansi"
"@php artisan vendor:publish --force --tag=livewire:assets --ansi",
"@php fix-permissions.php"
],
"post-create-project-cmd": [
"php artisan key:generate"
Generated
+321 -209
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "b1dfc90a20cecf851224ea8a5c71f26d",
"content-hash": "58603818d33285d78c0c8655385e7c0e",
"packages": [
{
"name": "alek13/slack",
@@ -340,91 +340,6 @@
},
"time": "2022-12-07T17:46:57+00:00"
},
{
"name": "barryvdh/laravel-debugbar",
"version": "v3.16.0",
"source": {
"type": "git",
"url": "https://github.com/barryvdh/laravel-debugbar.git",
"reference": "f265cf5e38577d42311f1a90d619bcd3740bea23"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/barryvdh/laravel-debugbar/zipball/f265cf5e38577d42311f1a90d619bcd3740bea23",
"reference": "f265cf5e38577d42311f1a90d619bcd3740bea23",
"shasum": ""
},
"require": {
"illuminate/routing": "^9|^10|^11|^12",
"illuminate/session": "^9|^10|^11|^12",
"illuminate/support": "^9|^10|^11|^12",
"php": "^8.1",
"php-debugbar/php-debugbar": "~2.2.0",
"symfony/finder": "^6|^7"
},
"require-dev": {
"mockery/mockery": "^1.3.3",
"orchestra/testbench-dusk": "^7|^8|^9|^10",
"phpunit/phpunit": "^9.5.10|^10|^11",
"squizlabs/php_codesniffer": "^3.5"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Debugbar": "Barryvdh\\Debugbar\\Facades\\Debugbar"
},
"providers": [
"Barryvdh\\Debugbar\\ServiceProvider"
]
},
"branch-alias": {
"dev-master": "3.16-dev"
}
},
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"Barryvdh\\Debugbar\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "PHP Debugbar integration for Laravel",
"keywords": [
"debug",
"debugbar",
"dev",
"laravel",
"profiler",
"webprofiler"
],
"support": {
"issues": "https://github.com/barryvdh/laravel-debugbar/issues",
"source": "https://github.com/barryvdh/laravel-debugbar/tree/v3.16.0"
},
"funding": [
{
"url": "https://fruitcake.nl",
"type": "custom"
},
{
"url": "https://github.com/barryvdh",
"type": "github"
}
],
"time": "2025-07-14T11:56:43+00:00"
},
{
"name": "brick/math",
"version": "0.14.0",
@@ -4458,16 +4373,16 @@
},
{
"name": "livewire/livewire",
"version": "v3.6.4",
"version": "v4.1.4",
"source": {
"type": "git",
"url": "https://github.com/livewire/livewire.git",
"reference": "ef04be759da41b14d2d129e670533180a44987dc"
"reference": "4697085e02a1f5f11410a1b5962400e3539f8843"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/livewire/livewire/zipball/ef04be759da41b14d2d129e670533180a44987dc",
"reference": "ef04be759da41b14d2d129e670533180a44987dc",
"url": "https://api.github.com/repos/livewire/livewire/zipball/4697085e02a1f5f11410a1b5962400e3539f8843",
"reference": "4697085e02a1f5f11410a1b5962400e3539f8843",
"shasum": ""
},
"require": {
@@ -4522,7 +4437,7 @@
"description": "A front-end framework for Laravel.",
"support": {
"issues": "https://github.com/livewire/livewire/issues",
"source": "https://github.com/livewire/livewire/tree/v3.6.4"
"source": "https://github.com/livewire/livewire/tree/v4.1.4"
},
"funding": [
{
@@ -4530,7 +4445,7 @@
"type": "github"
}
],
"time": "2025-07-17T05:12:15+00:00"
"time": "2026-02-09T22:59:54+00:00"
},
{
"name": "masterminds/html5",
@@ -5840,79 +5755,6 @@
},
"time": "2025-12-30T16:16:35+00:00"
},
{
"name": "php-debugbar/php-debugbar",
"version": "v2.2.4",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/3146d04671f51f69ffec2a4207ac3bdcf13a9f35",
"reference": "3146d04671f51f69ffec2a4207ac3bdcf13a9f35",
"shasum": ""
},
"require": {
"php": "^8",
"psr/log": "^1|^2|^3",
"symfony/var-dumper": "^4|^5|^6|^7"
},
"replace": {
"maximebf/debugbar": "self.version"
},
"require-dev": {
"dbrekelmans/bdi": "^1",
"phpunit/phpunit": "^8|^9",
"symfony/panther": "^1|^2.1",
"twig/twig": "^1.38|^2.7|^3.0"
},
"suggest": {
"kriswallsmith/assetic": "The best way to manage assets",
"monolog/monolog": "Log using Monolog",
"predis/predis": "Redis storage"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.1-dev"
}
},
"autoload": {
"psr-4": {
"DebugBar\\": "src/DebugBar/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxime Bouroumeau-Fuseau",
"email": "maxime.bouroumeau@gmail.com",
"homepage": "http://maximebf.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Debug bar in the browser for php application",
"homepage": "https://github.com/php-debugbar/php-debugbar",
"keywords": [
"debug",
"debug bar",
"debugbar",
"dev"
],
"support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v2.2.4"
},
"time": "2025-07-22T14:01:30+00:00"
},
{
"name": "phpdocumentor/reflection-common",
"version": "2.2.0",
@@ -9103,23 +8945,23 @@
},
{
"name": "symfony/finder",
"version": "v7.3.2",
"version": "v7.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/finder.git",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe"
"reference": "01b24a145bbeaa7141e75887ec904c34a6728a5f"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/2a6614966ba1074fa93dae0bc804227422df4dfe",
"reference": "2a6614966ba1074fa93dae0bc804227422df4dfe",
"url": "https://api.github.com/repos/symfony/finder/zipball/01b24a145bbeaa7141e75887ec904c34a6728a5f",
"reference": "01b24a145bbeaa7141e75887ec904c34a6728a5f",
"shasum": ""
},
"require": {
"php": ">=8.2"
},
"require-dev": {
"symfony/filesystem": "^6.4|^7.0"
"symfony/filesystem": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -9147,7 +8989,7 @@
"description": "Finds files and directories via an intuitive fluent interface",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/finder/tree/v7.3.2"
"source": "https://github.com/symfony/finder/tree/v7.4.4"
},
"funding": [
{
@@ -9167,27 +9009,26 @@
"type": "tidelift"
}
],
"time": "2025-07-15T13:41:35+00:00"
"time": "2026-01-12T12:19:02+00:00"
},
{
"name": "symfony/http-foundation",
"version": "v7.3.7",
"version": "v7.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/http-foundation.git",
"reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4"
"reference": "977a554a34cf8edc95ca351fbecb1bb1ad05cc94"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/db488a62f98f7a81d5746f05eea63a74e55bb7c4",
"reference": "db488a62f98f7a81d5746f05eea63a74e55bb7c4",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/977a554a34cf8edc95ca351fbecb1bb1ad05cc94",
"reference": "977a554a34cf8edc95ca351fbecb1bb1ad05cc94",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3.0",
"symfony/polyfill-mbstring": "~1.1",
"symfony/polyfill-php83": "^1.27"
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-mbstring": "^1.1"
},
"conflict": {
"doctrine/dbal": "<3.6",
@@ -9196,13 +9037,13 @@
"require-dev": {
"doctrine/dbal": "^3.6|^4",
"predis/predis": "^1.1|^2.0",
"symfony/cache": "^6.4.12|^7.1.5",
"symfony/clock": "^6.4|^7.0",
"symfony/dependency-injection": "^6.4|^7.0",
"symfony/expression-language": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/mime": "^6.4|^7.0",
"symfony/rate-limiter": "^6.4|^7.0"
"symfony/cache": "^6.4.12|^7.1.5|^8.0",
"symfony/clock": "^6.4|^7.0|^8.0",
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
"symfony/expression-language": "^6.4|^7.0|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/mime": "^6.4|^7.0|^8.0",
"symfony/rate-limiter": "^6.4|^7.0|^8.0"
},
"type": "library",
"autoload": {
@@ -9230,7 +9071,7 @@
"description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.3.7"
"source": "https://github.com/symfony/http-foundation/tree/v7.4.4"
},
"funding": [
{
@@ -9250,7 +9091,7 @@
"type": "tidelift"
}
],
"time": "2025-11-08T16:41:12+00:00"
"time": "2026-01-09T12:14:21+00:00"
},
{
"name": "symfony/http-kernel",
@@ -9456,20 +9297,21 @@
},
{
"name": "symfony/mime",
"version": "v7.3.2",
"version": "v7.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/mime.git",
"reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1"
"reference": "40945014c0a9471ccfe19673c54738fa19367a3c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/e0a0f859148daf1edf6c60b398eb40bfc96697d1",
"reference": "e0a0f859148daf1edf6c60b398eb40bfc96697d1",
"url": "https://api.github.com/repos/symfony/mime/zipball/40945014c0a9471ccfe19673c54738fa19367a3c",
"reference": "40945014c0a9471ccfe19673c54738fa19367a3c",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-intl-idn": "^1.10",
"symfony/polyfill-mbstring": "^1.0"
},
@@ -9484,11 +9326,11 @@
"egulias/email-validator": "^2.1.10|^3.1|^4",
"league/html-to-markdown": "^5.0",
"phpdocumentor/reflection-docblock": "^3.0|^4.0|^5.0",
"symfony/dependency-injection": "^6.4|^7.0",
"symfony/process": "^6.4|^7.0",
"symfony/property-access": "^6.4|^7.0",
"symfony/property-info": "^6.4|^7.0",
"symfony/serializer": "^6.4.3|^7.0.3"
"symfony/dependency-injection": "^6.4|^7.0|^8.0",
"symfony/process": "^6.4|^7.0|^8.0",
"symfony/property-access": "^6.4|^7.0|^8.0",
"symfony/property-info": "^6.4|^7.0|^8.0",
"symfony/serializer": "^6.4.3|^7.0.3|^8.0"
},
"type": "library",
"autoload": {
@@ -9520,7 +9362,7 @@
"mime-type"
],
"support": {
"source": "https://github.com/symfony/mime/tree/v7.3.2"
"source": "https://github.com/symfony/mime/tree/v7.4.4"
},
"funding": [
{
@@ -9540,7 +9382,7 @@
"type": "tidelift"
}
],
"time": "2025-07-15T13:41:35+00:00"
"time": "2026-01-08T16:12:55+00:00"
},
{
"name": "symfony/polyfill-ctype",
@@ -10872,16 +10714,16 @@
},
{
"name": "symfony/var-dumper",
"version": "v7.3.3",
"version": "v7.4.4",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f"
"reference": "0e4769b46a0c3c62390d124635ce59f66874b282"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/34d8d4c4b9597347306d1ec8eb4e1319b1e6986f",
"reference": "34d8d4c4b9597347306d1ec8eb4e1319b1e6986f",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/0e4769b46a0c3c62390d124635ce59f66874b282",
"reference": "0e4769b46a0c3c62390d124635ce59f66874b282",
"shasum": ""
},
"require": {
@@ -10893,10 +10735,10 @@
"symfony/console": "<6.4"
},
"require-dev": {
"symfony/console": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/process": "^6.4|^7.0",
"symfony/uid": "^6.4|^7.0",
"symfony/console": "^6.4|^7.0|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/process": "^6.4|^7.0|^8.0",
"symfony/uid": "^6.4|^7.0|^8.0",
"twig/twig": "^3.12"
},
"bin": [
@@ -10935,7 +10777,7 @@
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/v7.3.3"
"source": "https://github.com/symfony/var-dumper/tree/v7.4.4"
},
"funding": [
{
@@ -10955,7 +10797,7 @@
"type": "tidelift"
}
],
"time": "2025-08-13T11:49:31+00:00"
"time": "2026-01-01T22:13:48+00:00"
},
{
"name": "tabuna/breadcrumbs",
@@ -12771,6 +12613,108 @@
],
"time": "2025-09-10T09:51:40+00:00"
},
{
"name": "fruitcake/laravel-debugbar",
"version": "v4.0.7",
"source": {
"type": "git",
"url": "https://github.com/fruitcake/laravel-debugbar.git",
"reference": "a9cc62c81cd0bda4ca7410229487638d7df786be"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/fruitcake/laravel-debugbar/zipball/a9cc62c81cd0bda4ca7410229487638d7df786be",
"reference": "a9cc62c81cd0bda4ca7410229487638d7df786be",
"shasum": ""
},
"require": {
"illuminate/routing": "^11|^12",
"illuminate/session": "^11|^12",
"illuminate/support": "^11|^12",
"php": "^8.2",
"php-debugbar/php-debugbar": "^3.1",
"php-debugbar/symfony-bridge": "^1.1"
},
"replace": {
"barryvdh/laravel-debugbar": "self.version"
},
"require-dev": {
"larastan/larastan": "^3",
"laravel/octane": "^2",
"laravel/pennant": "^1",
"laravel/pint": "^1",
"laravel/telescope": "^5.16",
"livewire/livewire": "^3.7|^4",
"mockery/mockery": "^1.3.3",
"orchestra/testbench-dusk": "^9|^10",
"php-debugbar/twig-bridge": "^2.0",
"phpstan/phpstan-phpunit": "^2",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^11",
"shipmonk/phpstan-rules": "^4.3"
},
"type": "library",
"extra": {
"laravel": {
"aliases": {
"Debugbar": "Fruitcake\\LaravelDebugbar\\Facades\\Debugbar"
},
"providers": [
"Fruitcake\\LaravelDebugbar\\ServiceProvider"
]
},
"branch-alias": {
"dev-master": "4.0-dev"
}
},
"autoload": {
"files": [
"src/helpers.php"
],
"psr-4": {
"Fruitcake\\LaravelDebugbar\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Fruitcake",
"homepage": "https://fruitcake.nl"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "PHP Debugbar integration for Laravel",
"keywords": [
"barryvdh",
"debug",
"debugbar",
"dev",
"laravel",
"profiler",
"webprofiler"
],
"support": {
"issues": "https://github.com/fruitcake/laravel-debugbar/issues",
"source": "https://github.com/fruitcake/laravel-debugbar/tree/v4.0.7"
},
"funding": [
{
"url": "https://fruitcake.nl",
"type": "custom"
},
{
"url": "https://github.com/barryvdh",
"type": "github"
}
],
"time": "2026-02-06T20:53:50+00:00"
},
{
"name": "hamcrest/hamcrest-php",
"version": "v2.1.1",
@@ -13608,6 +13552,174 @@
},
"time": "2022-02-21T01:04:05+00:00"
},
{
"name": "php-debugbar/php-debugbar",
"version": "v3.2.2",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/php-debugbar.git",
"reference": "a1f4e156811f000efb6e118178832581fab94f11"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/php-debugbar/zipball/a1f4e156811f000efb6e118178832581fab94f11",
"reference": "a1f4e156811f000efb6e118178832581fab94f11",
"shasum": ""
},
"require": {
"php": "^8.2",
"psr/log": "^1|^2|^3",
"symfony/var-dumper": "^5.4|^6|^7|^8"
},
"replace": {
"maximebf/debugbar": "self.version"
},
"require-dev": {
"dbrekelmans/bdi": "^1.4",
"friendsofphp/php-cs-fixer": "^3.92",
"monolog/monolog": "^3.9",
"php-debugbar/doctrine-bridge": "^3@dev",
"php-debugbar/monolog-bridge": "^1@dev",
"php-debugbar/symfony-bridge": "^1@dev",
"php-debugbar/twig-bridge": "^2@dev",
"phpstan/phpstan": "^2.1",
"phpstan/phpstan-phpunit": "^2.0",
"phpstan/phpstan-strict-rules": "^2.0",
"phpunit/phpunit": "^10",
"predis/predis": "^3.3",
"shipmonk/phpstan-rules": "^4.3",
"symfony/browser-kit": "^6.4|7.0",
"symfony/dom-crawler": "^6.4|^7",
"symfony/event-dispatcher": "^5.4|^6.4|^7.3|^8.0",
"symfony/http-foundation": "^5.4|^6.4|^7.3|^8.0",
"symfony/mailer": "^5.4|^6.4|^7.3|^8.0",
"symfony/panther": "^1|^2.1",
"twig/twig": "^3.11.2"
},
"suggest": {
"php-debugbar/doctrine-bridge": "To integrate Doctrine with php-debugbar.",
"php-debugbar/monolog-bridge": "To integrate Monolog with php-debugbar.",
"php-debugbar/symfony-bridge": "To integrate Symfony with php-debugbar.",
"php-debugbar/twig-bridge": "To integrate Twig with php-debugbar."
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"psr-4": {
"DebugBar\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxime Bouroumeau-Fuseau",
"email": "maxime.bouroumeau@gmail.com",
"homepage": "http://maximebf.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Debug bar in the browser for php application",
"homepage": "https://github.com/php-debugbar/php-debugbar",
"keywords": [
"debug",
"debug bar",
"debugbar",
"dev",
"profiler",
"toolbar"
],
"support": {
"issues": "https://github.com/php-debugbar/php-debugbar/issues",
"source": "https://github.com/php-debugbar/php-debugbar/tree/v3.2.2"
},
"funding": [
{
"url": "https://fruitcake.nl",
"type": "custom"
},
{
"url": "https://github.com/barryvdh",
"type": "github"
}
],
"time": "2026-01-25T20:59:56+00:00"
},
{
"name": "php-debugbar/symfony-bridge",
"version": "v1.1.0",
"source": {
"type": "git",
"url": "https://github.com/php-debugbar/symfony-bridge.git",
"reference": "e37d2debe5d316408b00d0ab2688d9c2cf59b5ad"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/php-debugbar/symfony-bridge/zipball/e37d2debe5d316408b00d0ab2688d9c2cf59b5ad",
"reference": "e37d2debe5d316408b00d0ab2688d9c2cf59b5ad",
"shasum": ""
},
"require": {
"php": "^8.2",
"php-debugbar/php-debugbar": "^3.1",
"symfony/http-foundation": "^5.4|^6.4|^7.3|^8.0"
},
"require-dev": {
"dbrekelmans/bdi": "^1.4",
"phpunit/phpunit": "^10",
"symfony/browser-kit": "^6|^7",
"symfony/dom-crawler": "^6|^7",
"symfony/mailer": "^5.4|^6.4|^7.3|^8.0",
"symfony/panther": "^1|^2.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "1.0-dev"
}
},
"autoload": {
"psr-4": {
"DebugBar\\Bridge\\Symfony\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Maxime Bouroumeau-Fuseau",
"email": "maxime.bouroumeau@gmail.com",
"homepage": "http://maximebf.com"
},
{
"name": "Barry vd. Heuvel",
"email": "barryvdh@gmail.com"
}
],
"description": "Symfony bridge for PHP Debugbar",
"homepage": "https://github.com/php-debugbar/php-debugbar",
"keywords": [
"debugbar",
"dev",
"symfony"
],
"support": {
"issues": "https://github.com/php-debugbar/symfony-bridge/issues",
"source": "https://github.com/php-debugbar/symfony-bridge/tree/v1.1.0"
},
"time": "2026-01-15T14:47:34+00:00"
},
{
"name": "php-mock/php-mock",
"version": "2.6.2",
+301 -102
View File
@@ -1,5 +1,7 @@
<?php
declare(strict_types=1);
return [
/*
@@ -10,98 +12,53 @@ return [
| Debugbar is enabled by default, when debug is set to true in app.php.
| You can override the value by setting enable to true or false instead of null.
|
*/
'enabled' => null,
/*
|--------------------------------------------------------------------------
| Storage settings
|--------------------------------------------------------------------------
|
| DebugBar stores data for session/ajax requests.
| You can disable this, so the debugbar stores data in headers/session,
| but this can cause problems with large data collectors.
| By default, file storage (in the storage folder) is used. Redis and PDO
| can also be used. For PDO, run the package migrations first.
| You can provide an array of URI's that must be ignored (eg. 'api/*')
|
*/
'storage' => [
'enabled' => true,
'driver' => 'file', // redis, file, pdo
'path' => storage_path().'/debugbar', // For file driver
'connection' => null, // Leave null for default connection (Redis/PDO)
'enabled' => env('DEBUGBAR_ENABLED'),
'collect_jobs' => env('DEBUGBAR_COLLECT_JOBS', false),
'except' => [
'telescope*',
'horizon*',
'_boost/browser-logs',
],
/*
|--------------------------------------------------------------------------
| Vendors
|--------------------------------------------------------------------------
|
| Vendor files are included by default, but can be set to false.
| This can also be set to 'js' or 'css', to only include javascript or css vendor files.
| Vendor files are for css: font-awesome (including fonts) and highlight.js (css files)
| and for js: jquery and and highlight.js
| So if you want syntax highlighting, set it to true.
| jQuery is set to not conflict with existing jQuery scripts.
|
*/
'include_vendors' => true,
/*
|--------------------------------------------------------------------------
| Capture Ajax Requests
|--------------------------------------------------------------------------
|
| The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
| you can use this option to disable sending the data through the headers.
|
*/
'capture_ajax' => true,
/*
|--------------------------------------------------------------------------
| Clockwork integration
|--------------------------------------------------------------------------
|
| The Debugbar can emulate the Clockwork headers, so you can use the Chrome
| Extension, without the server-side code. It uses Debugbar collectors instead.
|
*/
'clockwork' => true,
/*
|--------------------------------------------------------------------------
| DataCollectors
|--------------------------------------------------------------------------
|
| Enable/disable DataCollectors
|
*/
|--------------------------------------------------------------------------
| DataCollectors
|--------------------------------------------------------------------------
|
| Enable/disable DataCollectors
|
*/
'collectors' => [
'phpinfo' => true, // Php version
'messages' => true, // Messages
'time' => true, // Time Datalogger
'memory' => true, // Memory usage
'exceptions' => true, // Exception displayer
'log' => true, // Logs from Monolog (merged in messages if enabled)
'db' => true, // Show database (PDO) queries and bindings
'views' => true, // Views with their data
'route' => true, // Current route information
'laravel' => true, // Laravel version and environment
'events' => true, // All events fired
'default_request' => false, // Regular or special Symfony request logger
'symfony_request' => true, // Only one can be enabled..
'mail' => true, // Catch mail messages
'logs' => true, // Add the latest log messages
'files' => true, // Show the included files
'config' => false, // Display config settings
'auth' => true, // Display Laravel authentication status
'gate' => true, // Display Laravel Gate checks
'session' => true, // Display session data
'phpinfo' => env('DEBUGBAR_COLLECTORS_PHPINFO', true), // Php version
'messages' => env('DEBUGBAR_COLLECTORS_MESSAGES', true), // Messages
'time' => env('DEBUGBAR_COLLECTORS_TIME', true), // Time Datalogger
'memory' => env('DEBUGBAR_COLLECTORS_MEMORY', true), // Memory usage
'exceptions' => env('DEBUGBAR_COLLECTORS_EXCEPTIONS', true), // Exception displayer
'log' => env('DEBUGBAR_COLLECTORS_LOG', true), // Logs from Monolog (merged in messages if enabled)
'db' => env('DEBUGBAR_COLLECTORS_DB', true), // Show database (PDO) queries and bindings
'views' => env('DEBUGBAR_COLLECTORS_VIEWS', true), // Views with their data
'route' => env('DEBUGBAR_COLLECTORS_ROUTE', true), // Current route information
'auth' => env('DEBUGBAR_COLLECTORS_AUTH', true), // Display Laravel authentication status
'gate' => env('DEBUGBAR_COLLECTORS_GATE', true), // Display Laravel Gate checks
'session' => env('DEBUGBAR_COLLECTORS_SESSION', true), // Display session data
'symfony_request' => env('DEBUGBAR_COLLECTORS_SYMFONY_REQUEST', false), // Default Request Data
'mail' => env('DEBUGBAR_COLLECTORS_MAIL', true), // Catch mail messages
'laravel' => env('DEBUGBAR_COLLECTORS_LARAVEL', true), // Laravel version and environment
'events' => env('DEBUGBAR_COLLECTORS_EVENTS', true), // All events fired
'logs' => env('DEBUGBAR_COLLECTORS_LOGS', true), // Add the latest log messages
'config' => env('DEBUGBAR_COLLECTORS_CONFIG', false), // Display config settings
'cache' => env('DEBUGBAR_COLLECTORS_CACHE', true), // Display cache events
'models' => env('DEBUGBAR_COLLECTORS_MODELS', true), // Display models
'livewire' => env('DEBUGBAR_COLLECTORS_LIVEWIRE', true), // Display Livewire (when available)
'inertia' => env('DEBUGBAR_COLLECTORS_INERTIA', true), // Display Inertia (when available)
'jobs' => env('DEBUGBAR_COLLECTORS_JOBS', true), // Display dispatched jobs
'pennant' => env('DEBUGBAR_COLLECTORS_PENNANT', true), // Display Pennant feature flags
'http_client' => env('DEBUGBAR_COLLECTORS_HTTP_CLIENT', true), // Display HTTP Client requests
],
/*
@@ -114,56 +71,298 @@ return [
*/
'options' => [
'time' => [
'memory_usage' => env('DEBUGBAR_OPTIONS_TIME_MEMORY_USAGE', false), // Calculated by subtracting memory start and end, it may be inaccurate
],
'messages' => [
'trace' => env('DEBUGBAR_OPTIONS_MESSAGES_TRACE', true), // Trace the origin of the debug message
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
'capture_dumps' => env('DEBUGBAR_OPTIONS_MESSAGES_CAPTURE_DUMPS', false), // Capture laravel `dump();` as message
'timeline' => env('DEBUGBAR_OPTIONS_MESSAGES_TIMELINE', true), // Add messages to the timeline
],
'memory' => [
'reset_peak' => env('DEBUGBAR_OPTIONS_MEMORY_RESET_PEAK', false), // run memory_reset_peak_usage before collecting
'with_baseline' => env('DEBUGBAR_OPTIONS_MEMORY_WITH_BASELINE', false), // Set boot memory usage as memory peak baseline
'precision' => (int) env('DEBUGBAR_OPTIONS_MEMORY_PRECISION', 0), // Memory rounding precision
],
'auth' => [
'show_name' => false, // Also show the users name/email in the debugbar
'show_name' => env('DEBUGBAR_OPTIONS_AUTH_SHOW_NAME', false), // Also show the users name/email in the debugbar
'show_guards' => env('DEBUGBAR_OPTIONS_AUTH_SHOW_GUARDS', true), // Show the guards that are used
],
'gate' => [
'trace' => false, // Trace the origin of the Gate checks
'timeline' => env('DEBUGBAR_OPTIONS_GATE_TIMELINE', false), // Add mails to the timeline
],
'db' => [
'with_params' => true, // Render SQL with the parameters substituted
'timeline' => true, // Add the queries to the timeline
'backtrace' => true, // EXPERIMENTAL: Use a backtrace to find the origin of the query in your files.
'explain' => [ // EXPERIMENTAL: Show EXPLAIN output on queries
'enabled' => false,
'types' => ['SELECT'], // array('SELECT', 'INSERT', 'UPDATE', 'DELETE'); for MySQL 5.6.3+
'with_params' => env('DEBUGBAR_OPTIONS_WITH_PARAMS', true), // Render SQL with the parameters substituted
'exclude_paths' => [ // Paths to exclude entirely from the collector
//'vendor/laravel/framework/src/Illuminate/Session', // Exclude sessions queries
],
'hints' => true, // Show hints for common mistakes
'backtrace' => env('DEBUGBAR_OPTIONS_DB_BACKTRACE', true), // Use a backtrace to find the origin of the query in your files.
'backtrace_exclude_paths' => [], // Paths to exclude from backtrace. (in addition to defaults)
'timeline' => env('DEBUGBAR_OPTIONS_DB_TIMELINE', true), // Add the queries to the timeline
'duration_background' => env('DEBUGBAR_OPTIONS_DB_DURATION_BACKGROUND', true), // Show shaded background on each query relative to how long it took to execute.
'explain' => [ // Show EXPLAIN output on queries
'enabled' => env('DEBUGBAR_OPTIONS_DB_EXPLAIN_ENABLED', false),
],
'only_slow_queries' => env('DEBUGBAR_OPTIONS_DB_ONLY_SLOW_QUERIES', true), // Only track queries that last longer than `slow_threshold`
'slow_threshold' => env('DEBUGBAR_OPTIONS_DB_SLOW_THRESHOLD', false), // Max query execution time (ms). Exceeding queries will be highlighted
'memory_usage' => env('DEBUGBAR_OPTIONS_DB_MEMORY_USAGE', false), // Show queries memory usage
'soft_limit' => (int) env('DEBUGBAR_OPTIONS_DB_SOFT_LIMIT', 100), // After the soft limit, no parameters/backtrace are captured
'hard_limit' => (int) env('DEBUGBAR_OPTIONS_DB_HARD_LIMIT', 500), // After the hard limit, queries are ignored
],
'mail' => [
'full_log' => false,
'timeline' => env('DEBUGBAR_OPTIONS_MAIL_TIMELINE', true), // Add mails to the timeline
'show_body' => env('DEBUGBAR_OPTIONS_MAIL_SHOW_BODY', true),
],
'views' => [
'data' => false, //Note: Can slow down the application, because the data can be quite large..
'timeline' => env('DEBUGBAR_OPTIONS_VIEWS_TIMELINE', true), // Add the views to the timeline
'data' => env('DEBUGBAR_OPTIONS_VIEWS_DATA', false), // True for all data, 'keys' for only names, false for no parameters.
'group' => (int) env('DEBUGBAR_OPTIONS_VIEWS_GROUP', 50), // Group duplicate views. Pass value to auto-group, or true/false to force
'exclude_paths' => [ // Add the paths which you don't want to appear in the views
'vendor/filament', // Exclude Filament components by default
],
],
'inertia' => [
'pages' => env('DEBUGBAR_OPTIONS_VIEWS_INERTIA_PAGES', 'js/Pages'), // Path for Inertia views
],
'route' => [
'label' => true, // show complete route on bar
'label' => env('DEBUGBAR_OPTIONS_ROUTE_LABEL', true), // Show complete route on bar
],
'session' => [
'masked' => [], // List of keys that are masked
],
'symfony_request' => [
'label' => env('DEBUGBAR_OPTIONS_SYMFONY_REQUEST_LABEL', true), // Show route on bar
'masked' => [], // List of keys that are masked
],
'events' => [
'data' => env('DEBUGBAR_OPTIONS_EVENTS_DATA', false), // Collect events data
'listeners' => env('DEBUGBAR_OPTIONS_EVENTS_LISTENERS', false), // Add listeners to the events data
'excluded' => [], // Example: ['eloquent.*', 'composing', Illuminate\Cache\Events\CacheHit::class]
],
'logs' => [
'file' => null,
'file' => env('DEBUGBAR_OPTIONS_LOGS_FILE'),
],
'cache' => [
'values' => env('DEBUGBAR_OPTIONS_CACHE_VALUES', true), // Collect cache values
'timeline' => env('DEBUGBAR_OPTIONS_CACHE_TIMELINE', false), // Add mails to the timeline
],
'http_client' => [
'masked' => [],
'timeline' => env('DEBUGBAR_OPTIONS_HTTP_CLIENT_TIMELINE', true), // Add requests to the timeline
],
],
/**
* Add any additional DataCollectors by adding the class name of a DataCollector or invokable class.
*/
'custom_collectors' => [
// MyCollector::class => env('DEBUGBAR_COLLECTORS_MYCOLLECTOR', true),
],
/*
|--------------------------------------------------------------------------
| Editor
|--------------------------------------------------------------------------
|
| Choose your preferred editor to use when clicking file name.
|
| Supported: "sublime", "textmate", "emacs", "macvim", "codelite",
| "phpstorm", "phpstorm-remote", "idea", "idea-remote",
| "vscode", "vscode-insiders", "vscode-remote", "vscode-insiders-remote",
| "vscodium", "nova", "xdebug", "atom", "espresso",
| "netbeans", "cursor", "windsurf", "zed", "antigravity"
|
*/
'editor' => env('DEBUGBAR_EDITOR') ?: env('IGNITION_EDITOR', 'phpstorm'),
/*
|--------------------------------------------------------------------------
| Capture Ajax Requests
|--------------------------------------------------------------------------
|
| The Debugbar can capture Ajax requests and display them. If you don't want this (ie. because of errors),
| you can use this option to disable sending the data through the headers.
|
| Optionally, you can also send ServerTiming headers on ajax requests for the Chrome DevTools.
|
| Note for your request to be identified as ajax requests they must either send the header
| X-Requested-With with the value XMLHttpRequest (most JS libraries send this), or have application/json as a Accept header.
|
| By default `ajax_handler_auto_show` is set to true allowing ajax requests to be shown automatically in the Debugbar.
| Changing `ajax_handler_auto_show` to false will prevent the Debugbar from reloading.
|
| You can defer loading the dataset, so it will be loaded with ajax after the request is done. (Experimental)
*/
'capture_ajax' => env('DEBUGBAR_CAPTURE_AJAX', true),
'add_ajax_timing' => env('DEBUGBAR_ADD_AJAX_TIMING', false),
'ajax_handler_auto_show' => env('DEBUGBAR_AJAX_HANDLER_AUTO_SHOW', true),
'ajax_handler_enable_tab' => env('DEBUGBAR_AJAX_HANDLER_ENABLE_TAB', true),
'defer_datasets' => env('DEBUGBAR_DEFER_DATASETS', false),
/*
|--------------------------------------------------------------------------
| Remote Path Mapping
|--------------------------------------------------------------------------
|
| If you are using a remote dev server, like Laravel Homestead, Docker, or
| even a remote VPS, it will be necessary to specify your path mapping.
|
| Leaving one, or both of these, empty or null will not trigger the remote
| URL changes and Debugbar will treat your editor links as local files.
|
| "remote_sites_path" is an absolute base path for your sites or projects
| in Homestead, Vagrant, Docker, or another remote development server.
|
| Example value: "/home/vagrant/Code"
|
| "local_sites_path" is an absolute base path for your sites or projects
| on your local computer where your IDE or code editor is running on.
|
| Example values: "/Users/<name>/Code", "C:\Users\<name>\Documents\Code"
|
*/
'remote_sites_path' => env('DEBUGBAR_REMOTE_SITES_PATH'),
'local_sites_path' => env('DEBUGBAR_LOCAL_SITES_PATH', env('IGNITION_LOCAL_SITES_PATH')),
/*
|--------------------------------------------------------------------------
| Storage settings
|--------------------------------------------------------------------------
|
| Debugbar stores data for session/ajax requests.
| You can disable this, so the debugbar stores data in headers/session,
| but this can cause problems with large data collectors.
| By default, file storage (in the storage folder) is used. Sqlite will
| create a database file in the storage folder.
| Redis and PDO can also be used. For PDO, run the package migrations first.
|
| Warning: Enabling storage.open will allow everyone to access previous
| request, do not enable open storage in publicly available environments!
| Specify a callback if you want to limit based on IP or authentication.
| Leaving it to null will allow localhost only.
*/
'storage' => [
'enabled' => env('DEBUGBAR_STORAGE_ENABLED', true),
'open' => env('DEBUGBAR_OPEN_STORAGE'), // bool/callback.
'driver' => env('DEBUGBAR_STORAGE_DRIVER', 'file'), // redis, file, sqlite, pdo, custom
'path' => env('DEBUGBAR_STORAGE_PATH', storage_path('debugbar')), // For file driver
'connection' => env('DEBUGBAR_STORAGE_CONNECTION'), // Leave null for default connection (Redis/PDO)
'provider' => env('DEBUGBAR_STORAGE_PROVIDER', ''), // Instance of StorageInterface for custom driver
],
/*
|--------------------------------------------------------------------------
| Assets
|--------------------------------------------------------------------------
|
| Vendor files are included by default, but can be set to false.
| This can also be set to 'js' or 'css', to only include javascript or css vendor files.
| Vendor files are for css: (none)
| and for js: highlight.js
| So if you want syntax highlighting, set it to true.
|
*/
'use_dist_files' => env('DEBUGBAR_USE_DIST_FILES', true),
'include_vendors' => env('DEBUGBAR_INCLUDE_VENDORS', true),
/*
|--------------------------------------------------------------------------
| Custom Error Handler for Deprecated warnings
|--------------------------------------------------------------------------
|
| When enabled, the Debugbar shows deprecated warnings for Symfony components
| in the Messages tab.
|
| You can set a custom error reporting level to filter which errors are
| handled. For example, to exclude deprecation warnings:
| E_ALL & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
| To exclude notices, strict warnings, and deprecations:
| E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED & ~E_USER_DEPRECATED
|
| Defaults to E_ALL (all errors).
|
*/
'error_handler' => env('DEBUGBAR_ERROR_HANDLER', false),
'error_level' => env('DEBUGBAR_ERROR_LEVEL', E_ALL),
/*
|--------------------------------------------------------------------------
| Clockwork integration
|--------------------------------------------------------------------------
|
| The Debugbar can emulate the Clockwork headers, so you can use the Chrome
| Extension, without the server-side code. It uses Debugbar collectors instead.
|
*/
'clockwork' => env('DEBUGBAR_CLOCKWORK', true),
/*
|--------------------------------------------------------------------------
| Inject Debugbar in Response
|--------------------------------------------------------------------------
|
| Usually, the debugbar is added just before <body>, by listening to the
| Usually, the debugbar is added just before </body>, by listening to the
| Response after the App is done. If you disable this, you have to add them
| in your template yourself. See http://phpdebugbar.com/docs/rendering.html
|
*/
'inject' => true,
'inject' => env('DEBUGBAR_INJECT', true),
/*
|--------------------------------------------------------------------------
| DebugBar route prefix
| Debugbar route prefix
|--------------------------------------------------------------------------
|
| Sometimes you want to set route prefix to be used by DebugBar to load
| Sometimes you want to set route prefix to be used by Debugbar to load
| its resources from. Usually the need comes from misconfigured web server or
| from trying to overcome bugs like this: http://trac.nginx.org/nginx/ticket/97
|
*/
'route_prefix' => '_debugbar',
'route_prefix' => env('DEBUGBAR_ROUTE_PREFIX', '_debugbar'),
/*
|--------------------------------------------------------------------------
| Debugbar route middleware
|--------------------------------------------------------------------------
|
| Additional middleware to run on the Debugbar routes
*/
'route_middleware' => [],
/*
|--------------------------------------------------------------------------
| Debugbar route domain
|--------------------------------------------------------------------------
|
| By default Debugbar route served from the same domain that request served.
| To override default domain, specify it as a non-empty value.
*/
'route_domain' => env('DEBUGBAR_ROUTE_DOMAIN'),
/*
|--------------------------------------------------------------------------
| Debugbar theme
|--------------------------------------------------------------------------
|
| Switches between light and dark theme. If set to auto it will respect system preferences
| Possible values: auto, light, dark
*/
'theme' => env('DEBUGBAR_THEME', 'auto'),
/*
|--------------------------------------------------------------------------
| Backtrace stack limit
|--------------------------------------------------------------------------
|
| By default, the Debugbar limits the number of frames returned by the 'debug_backtrace()' function.
| If you need larger stacktraces, you can increase this number. Setting it to 0 will result in no limit.
*/
'debug_backtrace_limit' => (int) env('DEBUGBAR_DEBUG_BACKTRACE_LIMIT', 50),
];
+137 -33
View File
@@ -2,6 +2,81 @@
return [
/*
|---------------------------------------------------------------------------
| Component Locations
|---------------------------------------------------------------------------
|
| This value sets the root directories that'll be used to resolve view-based
| components like single and multi-file components. The make command will
| use the first directory in this array to add new component files to.
|
*/
'component_locations' => [
resource_path('views/livewire'),
],
/*
|---------------------------------------------------------------------------
| Component Namespaces
|---------------------------------------------------------------------------
|
| This value sets default namespaces that will be used to resolve view-based
| components like single-file and multi-file components. These folders'll
| also be referenced when creating new components via the make command.
|
*/
'component_namespaces' => [
'layouts' => resource_path('views/layouts'),
'pages' => resource_path('views/pages'),
],
/*
|---------------------------------------------------------------------------
| Page Layout
|---------------------------------------------------------------------------
| The view that will be used as the layout when rendering a single component as
| an entire page via `Route::livewire('/post/create', 'pages::create-post')`.
| In this case, the content of pages::create-post will render into $slot.
|
*/
'component_layout' => 'layouts::app',
/*
|---------------------------------------------------------------------------
| Lazy Loading Placeholder
|---------------------------------------------------------------------------
| Livewire allows you to lazy load components that would otherwise slow down
| the initial page load. Every component can have a custom placeholder or
| you can define the default placeholder view for all components below.
|
*/
'component_placeholder' => null, // Example: 'placeholders::skeleton'
/*
|---------------------------------------------------------------------------
| Make Command
|---------------------------------------------------------------------------
| This value determines the default configuration for the artisan make command
| You can configure the component type (sfc, mfc, class) and whether to use
| the high-voltage () emoji as a prefix in the sfc|mfc component names.
|
*/
'make_command' => [
'type' => 'class', // Options: 'sfc', 'mfc', 'class'
'emoji' => false, // Options: true, false
'with' => [
'js' => false,
'css' => false,
'test' => false,
],
],
/*
|---------------------------------------------------------------------------
| Class Namespace
@@ -15,6 +90,19 @@ return [
'class_namespace' => 'App\\Livewire',
/*
|---------------------------------------------------------------------------
| Class Path
|---------------------------------------------------------------------------
|
| This value is used to specify the path where Livewire component class files
| are created when running creation commands like `artisan make:livewire`.
| This path is customizable to match your projects directory structure.
|
*/
'class_path' => app_path('Livewire'),
/*
|---------------------------------------------------------------------------
| View Path
@@ -28,30 +116,6 @@ return [
'view_path' => resource_path('views/livewire'),
/*
|---------------------------------------------------------------------------
| Layout
|---------------------------------------------------------------------------
| The view that will be used as the layout when rendering a single component
| as an entire page via `Route::get('/post/create', CreatePost::class);`.
| In this case, the view returned by CreatePost will render into $slot.
|
*/
'layout' => 'components.layouts.app',
/*
|---------------------------------------------------------------------------
| Lazy Loading Placeholder
|---------------------------------------------------------------------------
| Livewire allows you to lazy load components that would otherwise slow down
| the initial page load. Every component can have a custom placeholder or
| you can define the default placeholder view for all components below.
|
*/
'lazy_placeholder' => null,
/*
|---------------------------------------------------------------------------
| Temporary File Uploads
@@ -145,6 +209,19 @@ return [
'inject_morph_markers' => true,
/*
|---------------------------------------------------------------------------
| Smart Wire Keys
|---------------------------------------------------------------------------
|
| Livewire uses loops and keys used within loops to generate smart keys that
| are applied to nested components that don't have them. This makes using
| nested components more reliable by ensuring that they all have keys.
|
*/
'smart_wire_keys' => true,
/*
|---------------------------------------------------------------------------
| Pagination Theme
@@ -160,18 +237,45 @@ return [
/*
|---------------------------------------------------------------------------
| URL Prefix
| Release Token
|---------------------------------------------------------------------------
|
| By default, Livewire sends network requests to {app.com}/livewire/update
| while javascript assets are served via {app.com}/livewire/livewire.js
| If you need to adjust the prefix of those urls you can do it below.
|
| Defining a prefix will result in the following url
| {app.com}/{prefix}/livewire/{update|livewire.js}
| Note: do not include the leading or trailing /
| This token is stored client-side and sent along with each request to check
| a users session to see if a new release has invalidated it. If there is
| a mismatch it will throw an error and prompt for a browser refresh.
|
*/
'url_prefix' => env('LIVEWIRE_URL_PREFIX', null),
'release_token' => 'a',
/*
|---------------------------------------------------------------------------
| CSP Safe
|---------------------------------------------------------------------------
|
| This config is used to determine if Livewire will use the CSP-safe version
| of Alpine in its bundle. This is useful for applications that are using
| strict Content Security Policy (CSP) to protect against XSS attacks.
|
*/
'csp_safe' => false,
/*
|---------------------------------------------------------------------------
| Payload Guards
|---------------------------------------------------------------------------
|
| These settings protect against malicious or oversized payloads that could
| cause denial of service. The default values should feel reasonable for
| most web applications. Each can be set to null to disable the limit.
|
*/
'payload' => [
'max_size' => 1024 * 1024, // 1MB - maximum request payload size in bytes
'max_nesting_depth' => 10, // Maximum depth of dot-notation property paths
'max_calls' => 50, // Maximum method calls per request
'max_components' => 20, // Maximum components per batch request
],
];
+1
View File
@@ -1 +1,2 @@
*.sqlite
*.journal
+30
View File
@@ -215,4 +215,34 @@ class CategoryFactory extends Factory
'require_acceptance' => false,
]);
}
public function sendsCheckinEmail()
{
return $this->state([
'checkin_email' => true,
]);
}
public function doesNotSendCheckinEmail()
{
return $this->state([
'checkin_email' => false,
]);
}
public function hasLocalEula()
{
return $this->state([
'use_default_eula' => false,
'eula_text' => 'Some EULA text here',
]);
}
public function withNoLocalOrGlobalEula()
{
return $this->state([
'use_default_eula' => false,
'eula_text' => '',
]);
}
}
@@ -43,6 +43,13 @@ class LicenseSeatFactory extends Factory
});
}
public function unreassignable()
{
return $this->afterMaking(function (LicenseSeat $seat) {
$seat->license->update(['reassignable' => false]);
});
}
public function notReassignable()
{
return $this->afterMaking(function (LicenseSeat $seat) {
+6 -2
View File
@@ -5,6 +5,7 @@ namespace Database\Factories;
use App\Models\Asset;
use App\Models\Maintenance;
use App\Models\Supplier;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class MaintenanceFactory extends Factory
@@ -24,14 +25,17 @@ class MaintenanceFactory extends Factory
public function definition()
{
return [
'asset_id' => Asset::factory(),
'asset_id' => Asset::factory()->laptopZenbook(),
'supplier_id' => Supplier::factory(),
'asset_maintenance_type' => $this->faker->randomElement(['maintenance', 'repair', 'upgrade']),
'name' => $this->faker->sentence(),
'name' => $this->faker->name(),
'start_date' => $this->faker->date(),
'is_warranty' => $this->faker->boolean(),
'notes' => $this->faker->paragraph(),
'url' => $this->faker->url(),
'cost' => $this->faker->randomFloat(),
'created_by' => User::factory()->superuser(),
'image' => $this->faker->numberBetween(1,11).'.png',
];
}
}
@@ -20,6 +20,21 @@ class ReportTemplateFactory extends Factory
'id' => '1',
],
'created_by' => User::factory(),
'is_shared' => 0,
];
}
public function shared()
{
return $this->state(function () {
return['is_shared' => 1];
});
}
public function notShared()
{
return $this->state(function () {
return ['is_shared' => 0];
});
}
}
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('report_templates', function (Blueprint $table) {
$table->boolean('is_shared', )->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('report_templates', function (Blueprint $table) {
if (Schema::hasColumn('report_templates', 'is_shared')) {
$table->dropColumn('is_shared');
}
});
}
};
+1 -1
View File
@@ -44,6 +44,7 @@ class DatabaseSeeder extends Seeder
$this->call(ComponentSeeder::class);
$this->call(ConsumableSeeder::class);
$this->call(ActionlogSeeder::class);
$this->call(MaintenanceSeeder::class);
Artisan::call('snipeit:sync-asset-locations', ['--output' => 'all']);
@@ -53,7 +54,6 @@ class DatabaseSeeder extends Seeder
Model::reguard();
DB::table('imports')->truncate();
DB::table('maintenances')->truncate();
DB::table('requested_assets')->truncate();
}
}
+52
View File
@@ -0,0 +1,52 @@
<?php
namespace Database\Seeders;
use App\Models\Maintenance;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class MaintenanceSeeder extends Seeder
{
public function run()
{
Maintenance::truncate();
Maintenance::factory()->create(['image' => '1.png']);
Maintenance::factory()->create(['image' => '2.png']);
Maintenance::factory()->create(['image' => '3.png']);
Maintenance::factory()->create(['image' => '4.png']);
Maintenance::factory()->create(['image' => '5.png']);
Maintenance::factory()->create(['image' => '6.png']);
Maintenance::factory()->create(['image' => '7.png']);
Maintenance::factory()->create(['image' => '8.png']);
Maintenance::factory()->create(['image' => '9.png']);
Maintenance::factory()->create(['image' => '10.png']);
Maintenance::factory()->create(['image' => '11.png']);
$src = public_path('/img/demo/maintenances/');
$dst = 'maintenances'.'/';
$del_files = Storage::files($dst);
foreach ($del_files as $del_file) { // iterate files
$file_to_delete = str_replace($src, '', $del_file);
Log::debug('Deleting: '.$file_to_delete);
try {
Storage::disk('public')->delete($dst.$del_file);
} catch (\Exception $e) {
Log::debug($e);
}
}
$add_files = glob($src.'/*.*');
foreach ($add_files as $add_file) {
$file_to_copy = str_replace($src, '', $add_file);
Log::debug('Copying: '.$file_to_copy);
try {
Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy));
} catch (\Exception $e) {
Log::debug($e);
}
}
}
}
+54
View File
@@ -0,0 +1,54 @@
<?php
(PHP_SAPI !== 'cli' || isset($_SERVER['HTTP_USER_AGENT'])) && die('Access denied.');
$icon = '';
$files = [
'storage/oauth-private.key' => '660',
'storage/oauth-public.key' => '660',
];
echo "\n";
// Normalize key permissions for Passport 13 (covers both fresh installs and upgrades)
if (PHP_OS_FAMILY !== 'Windows') {
foreach ($files as $file => $permission) {
if (file_exists($file)) {
try {
@chmod($file, $permission);
$messages[]['success'] = "Permissions updated to ".$permission." on ".$file." \n";
} catch (Exception $e) {
$messages[]['error'] = "Could not change permissions for ".$file.". Please manually change the permissions on this file to ".$permission.". See the documentation: https://snipe-it.readme.io/docs/debugging-permissions#linuxosx \n";
}
} else {
$messages[]['info'] = "The file ".$file." was not found and may not have been created yet. \n";
}
}
if (count($messages) > 0) {
for($x = 0; $x < count($messages); $x++) {
foreach ($messages[$x] as $type => $message) {
if ($type === 'error') {
echo " \e[0;97;41m ERROR \e[0m ";
} elseif ($type === 'info') {
echo " \e[0;97;44m INFO \e[0m ";
} elseif ($type === 'success') {
echo " \e[0;97;42m SUCCESS \e[0m ";
}
echo $message;
}
}
}
echo "\n";
exit();
}
echo " \e[0;97;44m INFO \e[0m Windows OS detected, so OAuth key permissions could not be set. If you have problems with API calls or tables loading in your Snipe-IT application, see the documentation on how to correct them: https://snipe-it.readme.io/docs/debugging-permissions#windows \n";
exit();
Binary file not shown.

After

Width:  |  Height:  |  Size: 203 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 384 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 377 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 242 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 229 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 363 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 295 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 387 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 289 KiB

+5 -4
View File
@@ -52653,11 +52653,12 @@ document.addEventListener('livewire:init', function () {
}
Livewire.find(target.data('livewire-component')).set(event.target.name, this.options[this.selectedIndex].value);
});
Livewire.hook('request', function (_ref) {
var succeed = _ref.succeed;
succeed(function () {
Livewire.interceptMessage(function (_ref) {
var onFinish = _ref.onFinish;
onFinish(function () {
// Runs after DOM morph completes (or on error/cancel)
queueMicrotask(function () {
$('.livewire-select2').select2();
$(".livewire-select2").select2();
});
});
});
+1 -1
View File
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,5 +1,5 @@
{
"/js/dist/all.js": "/js/dist/all.js?id=28a9bc8ac35af5e39b37d977f5761cee",
"/js/dist/all.js": "/js/dist/all.js?id=4176097fd869edd2d6cb18a71ccb4ff6",
"/css/build/overrides.css": "/css/build/overrides.css?id=69b145f1bb0fb5c3de63350ef73207b4",
"/css/build/app.css": "/css/build/app.css?id=ca045cda8d9164ddb2f7a0ec6fd92a40",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=ee0ed88465dd878588ed044eefb67723",
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+5391 -1770
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
+6507 -1666
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1,2 +1,2 @@
{"/livewire.js":"df3a17f2"}
{"/livewire.js":"cfc5c1ae"}
+8 -6
View File
@@ -604,13 +604,15 @@ document.addEventListener('livewire:init', () => {
Livewire.find(target.data('livewire-component')).set(event.target.name, this.options[this.selectedIndex].value)
});
Livewire.hook('request', ({succeed}) => {
succeed(() => {
queueMicrotask(() => {
$('.livewire-select2').select2();
});
Livewire.interceptMessage(({ onFinish }) => {
onFinish(() => {
// Runs after DOM morph completes (or on error/cancel)
queueMicrotask(() => {
$(".livewire-select2").select2();
});
});
});
}
);
});

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