Compare commits

...

154 Commits

Author SHA1 Message Date
snipe 1a7c7fdebf Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	config/version.php
#	public/css/build/app.css
#	public/css/build/app.css.map
#	public/css/build/overrides.css
#	public/css/build/overrides.css.map
#	public/css/dist/all.css
#	public/mix-manifest.json
2025-10-17 18:37:18 +01:00
snipe 65ff3d414a Bumped version 2025-10-17 18:34:54 +01:00
snipe 9fa38b70c8 Bumped version 2025-10-17 18:26:44 +01:00
snipe 470172f53f Re-run assets 2025-10-17 18:26:05 +01:00
snipe 81261d9e36 Put the session check back in - possible fix for #18004 2025-10-17 18:25:50 +01:00
snipe 3ab2e20119 Merge remote-tracking branch 'origin/develop' 2025-10-17 17:12:47 +01:00
snipe b773d576ea Updated cipher-base library 2025-10-17 17:12:31 +01:00
snipe 23feb64b5a Fixed potential XSS on locations 2025-10-17 17:07:57 +01:00
snipe 87fe9d9d3d Merge remote-tracking branch 'origin/develop'
# Conflicts:
#	public/css/build/app.css
#	public/css/build/app.css.map
#	public/css/build/overrides.css
#	public/css/build/overrides.css.map
#	public/css/dist/all.css
#	public/css/dist/skins/_all-skins.css
#	public/css/dist/skins/_all-skins.css.map
#	public/css/dist/skins/_all-skins.min.css
#	public/css/dist/skins/skin-contrast.css
#	public/css/dist/skins/skin-contrast.css.map
#	public/css/dist/skins/skin-contrast.min.css
#	public/mix-manifest.json
2025-10-17 17:00:10 +01:00
snipe b1ef3f51cb Merge pull request #18064 from grokability/new-fieldsets
Use new fieldset component
2025-10-17 16:58:17 +01:00
snipe e1b6488f8e Use new fieldset component 2025-10-17 16:55:36 +01:00
snipe a472dede2b Merge pull request #18063 from grokability/improved-fieldset-UI-and-better-help-test-for-ldap-mapping
New legend styles and additional help hints for LDAP
2025-10-17 15:45:05 +01:00
snipe 263cc3f7a1 New styles and additional help hints for LDAP 2025-10-17 15:29:24 +01:00
snipe d355812433 Updated assets 2025-10-16 19:06:22 +01:00
snipe 1afc14f5ab Merge remote-tracking branch 'origin/develop' 2025-10-16 19:04:30 +01:00
snipe 8947b667ae Fixed status labels skin for visited link buttons 2025-10-16 19:04:15 +01:00
snipe 6b41796d44 Fixed restore button on asset view page 2025-10-16 19:04:01 +01:00
snipe 6efe8eb55b Small fix for high contrast skin 2025-10-16 18:33:33 +01:00
snipe 4c8f8918e8 Merge remote-tracking branch 'origin/develop' 2025-10-16 15:49:59 +01:00
snipe 4cb5bb1855 Merge pull request #18057 from grokability/user-selector-fix
Fixed #18053 - user selector missing on page load without cookies
2025-10-16 15:49:39 +01:00
snipe eb007e025a Fixed #18053 - user selector missing on page load without cookies 2025-10-16 15:47:25 +01:00
snipe 18aefa9dee Merge remote-tracking branch 'origin/develop' 2025-10-16 15:10:29 +01:00
snipe 2ec540bd36 Updated language translations 2025-10-16 15:10:17 +01:00
snipe 1374ec408a Merge pull request #18019 from akemidx/emdashcharfix
Fixed #17363 - Emdash Character Encoding error
2025-10-16 15:07:31 +01:00
snipe 8f8fed2b79 Merge remote-tracking branch 'origin/develop' 2025-10-16 14:33:30 +01:00
snipe a1e6f01fe9 Fixed updating notes in bulk edit 2025-10-16 14:33:21 +01:00
snipe d7496f22e5 Merge remote-tracking branch 'origin/develop' 2025-10-16 14:04:44 +01:00
snipe 7de25a1c37 Merge pull request #18056 from grokability/add-expected-checkin-to-view-assets
Added expected_checkin to user’s View Assigned page
2025-10-16 14:04:31 +01:00
snipe 78da89340c Added expected_checkin to user’s View Assigned page 2025-10-16 13:59:59 +01:00
snipe 60606115fe Merge remote-tracking branch 'origin/develop' 2025-10-16 12:46:47 +01:00
snipe 57b49fc31c Check for array key for license report/formatters 2025-10-16 12:46:17 +01:00
snipe 6e90c8f6e6 Bumped hash for master 2025-10-16 11:28:37 +01:00
snipe a7ff2595a5 Bumped hash 2025-10-16 11:28:01 +01:00
snipe 1edea6abef Fixed RB-20347 - ambigious field in custom fields 2025-10-16 11:27:25 +01:00
snipe 3339d1999f Merge remote-tracking branch 'origin/develop' 2025-10-16 11:12:56 +01:00
akemidx df3e8ec0f3 cleaning up notes 2025-10-15 17:35:25 -04:00
snipe 2dbec867d9 Merge pull request #18038 from boteroTradebe/develop
Fixed LDAP sync not syncing all user fields
2025-10-15 17:25:33 +01:00
snipe b91d23023d Fix blade template syntax for accessory fields 2025-10-14 13:45:58 +01:00
boteroTradebe cc234c60b8 Update LdapSync.php to populate/update user fields
Added missing IF statements for address, city, state, and ZIP code. Previously, this information would be pulled via LDAP sync but would not update the user data due to the missing IF statements for these attributes.
2025-10-13 13:42:11 -05:00
snipe f1883c8004 Merge remote-tracking branch 'origin/develop' 2025-10-13 14:48:46 +01:00
snipe 79f6ddc8ee Merge pull request #18036 from grokability/better-messaging-for-bulk-deletes
Fixed #18034 - Shows success message on partial bulk delete success
2025-10-13 14:30:26 +01:00
snipe 89f439a18d Shows success message on partial bulk delete success 2025-10-13 14:25:05 +01:00
snipe 79eb5bfad9 Merge pull request #18035 from grokability/fixes-bulk-error-notification
Fixed bulk error display to be more consistent and correct HTML
2025-10-13 14:02:11 +01:00
snipe 3a36b7dafd Fixed display to be more consistent and correct HTML 2025-10-13 13:57:04 +01:00
snipe 1fe2fd9891 Merge pull request #17573 from spencerrlongg/feature/8709-bulk-deletion-of-asset-categories-suppliers-manufacturers
Fixed #8709 - Bulk Deletion of Categories, Suppliers, Manufa...
2025-10-13 13:20:13 +01:00
snipe 5fdb999ece Merge branch 'develop' into feature/8709-bulk-deletion-of-asset-categories-suppliers-manufacturers 2025-10-13 13:07:53 +01:00
snipe 5a38d9c2b6 Merge pull request #18029 from grokability/dependabot/github_actions/develop/github/codeql-action-4
Bump github/codeql-action from 3 to 4
2025-10-13 12:00:49 +01:00
snipe b1c7dc6cbb Merge remote-tracking branch 'origin/develop' 2025-10-13 11:32:19 +01:00
snipe b21b2ac41c Merge pull request #18032 from grokability/move-asset-private-files
Added migration to move asset model private uploads
2025-10-13 11:31:55 +01:00
snipe 1396c597ef Move files 2025-10-13 11:19:25 +01:00
dependabot[bot] 46af72ee4e Bump github/codeql-action from 3 to 4
Bumps [github/codeql-action](https://github.com/github/codeql-action) from 3 to 4.
- [Release notes](https://github.com/github/codeql-action/releases)
- [Changelog](https://github.com/github/codeql-action/blob/main/CHANGELOG.md)
- [Commits](https://github.com/github/codeql-action/compare/v3...v4)

---
updated-dependencies:
- dependency-name: github/codeql-action
  dependency-version: '4'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
2025-10-13 08:19:22 +00:00
snipe e3e8f553c8 Merge remote-tracking branch 'origin/develop' 2025-10-09 18:39:13 +01:00
snipe 549928d3d1 Updated assets 2025-10-09 18:38:59 +01:00
snipe abefec9628 Upgraded jdpdf to ^3.0.3 2025-10-09 18:37:59 +01:00
snipe b483eeded4 Merge remote-tracking branch 'origin/develop' 2025-10-09 11:24:47 +01:00
snipe fab85dafa8 Added employee number and email to acceptance PDF 2025-10-09 11:24:16 +01:00
snipe 955faed919 Merge pull request #18018 from grokability/advanced-user-search
Normalize advanced search
2025-10-09 11:04:28 +01:00
snipe 3ff516180d Merge remote-tracking branch 'origin/develop' 2025-10-09 10:56:08 +01:00
snipe 0c8ca6d6b0 Search on status label name 2025-10-09 10:54:11 +01:00
snipe a5de077e04 Merge pull request #17975 from marcusmoore/replace-date-and-time-display-macros
Removed date and time display format form macros
2025-10-09 04:54:05 +01:00
akemidx c0a99d6b52 notes 2025-10-08 19:20:32 -04:00
Marcus Moore a1e65cd897 Merge branch 'develop' into replace-date-and-time-display-macros
# Conflicts:
#	resources/macros/macros.php
2025-10-08 13:10:56 -07:00
snipe 5d65f1ffc5 Merge pull request #17976 from marcusmoore/17204-replace-form-digit-separator
Fixed #17204 - replace Form::digit_separator macro
2025-10-08 21:01:11 +01:00
snipe b7193a06fd Normalize advanced search 2025-10-08 20:51:35 +01:00
akemidx cba090f8eb notes 2025-10-08 15:50:00 -04:00
snipe 0d6baa1081 Merge remote-tracking branch 'origin/develop' 2025-10-08 15:29:02 +01:00
snipe bc60d796a3 Fixed RB-20329 - ambiguous clause on deleted_at 2025-10-08 15:28:48 +01:00
snipe 85a208526b Merge remote-tracking branch 'origin/develop' 2025-10-08 10:38:08 +01:00
snipe c3ac0a750d Added licenses checkin permission 2025-10-08 10:37:58 +01:00
snipe 0f111127a5 Merge pull request #18005 from marcusmoore/fixes/drop-index-migration
Fixed exception when rolling back migrations
2025-10-08 05:26:22 +01:00
snipe cd266a6bef Merge remote-tracking branch 'origin/develop' 2025-10-08 05:13:14 +01:00
snipe 0f4945621c Merge pull request #18009 from grokability/#18002-audit-image-location
Fixed #18002 - use correct path for audit images to determine validity
2025-10-08 05:12:54 +01:00
snipe 9a477f227b Fixed #18002 - use correct path for audit images to determine validity 2025-10-08 05:09:04 +01:00
akemidx 3c81257325 fix? 2025-10-07 20:23:46 -04:00
Marcus Moore 218fe9ebdc Allow Laravel to calculate index name 2025-10-07 16:04:12 -07:00
spencerrlongg 24bb45ab97 change translation 2025-10-07 13:26:08 -05:00
snipe 85f39de540 Merge pull request #18001 from grokability/#17670-fixes-advanced-search-on-assets
Fixed #17670 - advanced search on relationships not working
2025-10-07 17:35:05 +01:00
snipe 5cc3277e2d Merge pull request #18003 from uberbrady/fix_file_upload_base64
Fixed [FD-50921] - base64-encoded image files for asset creation was broken
2025-10-07 17:34:53 +01:00
snipe d5ef7f3204 Merge remote-tracking branch 'origin/develop' 2025-10-07 17:29:24 +01:00
snipe cb47d01f51 Fixed variable name in location print 2025-10-07 17:29:12 +01:00
Brady Wetherington ee499c1385 Fix base64-encoded image files for asset creation; add test 2025-10-07 16:00:16 +01:00
snipe 4ae4af5c10 Fixed #17670 - advanced search on relationships not working 2025-10-07 15:39:09 +01:00
snipe b0f5fe7e25 Merge remote-tracking branch 'origin/develop' 2025-10-07 14:32:33 +01:00
snipe fd32585efc Added notes back to audit email 2025-10-07 14:32:24 +01:00
snipe c675bb7252 Merge remote-tracking branch 'origin/develop' 2025-10-07 14:29:21 +01:00
snipe e65d11d71e Pulled incorrect button label 2025-10-07 14:29:10 +01:00
snipe c2680334f1 Clearer title on maintenances within asset context 2025-10-07 14:28:38 +01:00
snipe 1217a02ec1 Merge pull request #17992 from marcusmoore/17963-undelete-files-command
Added command to remove invalid "upload deleted" entries from the action log
2025-10-07 14:17:56 +01:00
snipe 143a091f45 Merge remote-tracking branch 'origin/develop' 2025-10-07 14:15:59 +01:00
snipe 49ecc93dbe Merge pull request #17999 from grokability/updated-audit-report
Improved upcoming audit email layout and cli feedback
2025-10-07 14:15:44 +01:00
snipe 1735fb6bed Improved audit email 2025-10-07 14:08:33 +01:00
snipe 8fefc11b4d Merge remote-tracking branch 'origin/develop' 2025-10-07 12:09:32 +01:00
snipe 1a3b22171c Merge pull request #17997 from grokability/#17924-add-url-to-maintenances
Fixed #17924 - added url to maintenances
2025-10-07 12:09:06 +01:00
snipe 5e773be260 Enhanced tests 2025-10-07 12:05:37 +01:00
snipe c317a1dc8b Added url to factory 2025-10-07 12:03:35 +01:00
snipe 9401ffc83c Added link to view 2025-10-07 11:55:32 +01:00
snipe 479a852446 Fixed #17924 - added url to maintenances 2025-10-07 11:49:10 +01:00
snipe 9188fb03f0 Merge remote-tracking branch 'origin/develop' 2025-10-07 10:49:59 +01:00
snipe 36bb91cbc3 Merge pull request #17995 from grokability/#17910-show-counts-on-mobile
Fixed #17910 - added counts to mobile view for assets
2025-10-07 10:47:41 +01:00
snipe 56e5ab8bc6 Fixed #17910 - added counts to mobile view for assets 2025-10-07 10:41:03 +01:00
snipe 607eb6ca03 Merge remote-tracking branch 'origin/develop' 2025-10-07 09:42:59 +01:00
snipe ad745cc84b Fixed #17911 - updated language string 2025-10-07 09:42:30 +01:00
Marcus Moore 5a13d5ea6f Update command description 2025-10-06 15:23:55 -07:00
Marcus Moore 0b065eb7fe Improve command 2025-10-06 15:20:43 -07:00
Marcus Moore e2c0e4bc66 WIP build out command 2025-10-06 15:14:15 -07:00
Marcus Moore 655b0e6778 Scaffold command 2025-10-06 14:59:25 -07:00
Marcus Moore cd785c9fc3 Remove name_display_format macro that was accidentally re-added 2025-10-06 13:06:52 -07:00
Marcus Moore 23885f5166 Merge branch 'develop' into 17204-replace-form-digit-separator
# Conflicts:
#	resources/macros/macros.php
2025-10-06 13:04:34 -07:00
Marcus Moore 689d5a2d58 Remove digit_separator form macro 2025-10-02 15:39:28 -07:00
Marcus Moore b2e9eb866c Replace digit_separator form macro
Fixes #17204
2025-10-02 15:38:59 -07:00
Marcus Moore c8b7782d1d Remove date_display_format and time_display_format macros 2025-10-02 15:27:20 -07:00
Marcus Moore 673f936689 Replace Form:: time_display_format on localization screen 2025-10-02 15:26:31 -07:00
Marcus Moore 2ca0d39e51 Replace Form:: date_display_format on localization screen 2025-10-02 15:21:51 -07:00
spencerrlongg b9f4dc1e9d translation 2025-10-02 12:00:52 -05:00
akemidx b082fb6692 investigation and notes 2025-10-01 18:21:25 -04:00
akemidx a384245368 investigation and notes 2025-09-30 16:33:33 -04:00
spencerrlongg 32882f81e7 replace box-default 2025-09-29 15:52:43 -05:00
spencerrlongg 36f5099932 added new counts and throw new exceptions and catch them 2025-09-29 15:16:41 -05:00
spencerrlongg 1d24b7985b another translation change 2025-08-27 17:25:17 -05:00
spencerrlongg 526bb2c650 more translation changes 2025-08-27 17:23:46 -05:00
spencerrlongg c450c0ddb8 lots of translation changes 2025-08-27 17:17:18 -05:00
spencerrlongg 51f6927076 add details block for more than 3 errors to notification 2025-08-26 21:50:08 -05:00
spencerrlongg 1d88cf443f revert SuppliersController as well 2025-08-25 18:45:31 -05:00
spencerrlongg 7b6c0c3a40 Revert "tests passing, needs some manual testing"
This reverts commit fdb0651bf4.
2025-08-25 18:42:11 -05:00
spencerrlongg fdb0651bf4 tests passing, needs some manual testing 2025-08-25 18:25:36 -05:00
spencerrlongg c39d484611 rm unused import, new prop 2025-08-25 16:30:53 -05:00
spencerrlongg c42996429f rm unused import 2025-08-25 14:10:12 -05:00
spencerrlongg a091baf5a6 component finally working 2025-08-25 14:06:56 -05:00
spencerrlongg 643d44af22 change \Throwable to \Exceptionm, add missing report()s 2025-08-20 23:09:59 -05:00
spencerrlongg b934f43db0 rename all exceptions 2025-08-20 22:58:39 -05:00
spencerrlongg e33b1b6c90 fixed maintenances 2025-08-12 13:34:40 -05:00
Spencer Long 30520297e8 Merge branch 'develop' into feature/8709-bulk-deletion-of-asset-categories-suppliers-manufacturers 2025-08-12 11:58:11 -06:00
spencerrlongg 78ca1d1335 some cleanup 2025-08-11 21:07:08 -05:00
spencerrlongg 6159ee8c2c category done! 2025-08-11 20:16:43 -05:00
spencerrlongg 5cd5392958 manufacturer completed, just categories left 2025-08-11 19:42:09 -05:00
spencerrlongg 0dcdfc5d14 fix tests after routing change 2025-08-11 19:11:40 -05:00
spencerrlongg d0e068f1c0 suppliers completely done, rinse and repeat for the other two 2025-08-11 19:04:36 -05:00
spencerrlongg 3eefeec4ce partials made, need to figure out all this jquery, button disabled 2025-08-09 22:40:00 -05:00
spencerrlongg b61419c1ce oop, revert delete 2025-08-09 22:19:28 -05:00
spencerrlongg f590fcffbc some tests, a component i probably won't use, beginning of front end 2025-08-09 22:16:23 -05:00
spencerrlongg 7cdfaa93ec a couple more tests and cleanup 2025-07-10 16:45:15 -05:00
spencerrlongg 59ccc70303 bulk changes that should make this work 2025-07-10 16:02:39 -05:00
spencerrlongg f1584b722d work on bulk tests, switching branches to check something 2025-07-10 15:29:42 -05:00
spencerrlongg 4d8c5a86a4 routes added, tests scratched but need writing 2025-07-09 23:01:58 -05:00
spencerrlongg 5f835aa009 delete unused imports 2025-07-07 18:07:26 -05:00
spencerrlongg d5ca543719 start introducing parent exception 2025-07-07 18:05:23 -05:00
spencerrlongg db63ad1cf4 add image check to supplier action 2025-06-17 18:13:37 -05:00
spencerrlongg 5da79cd5ca destroy manufacturer action, bulk manufacturer controller 2025-06-12 17:11:45 -05:00
spencerrlongg 13c971b171 some refinements, bulk categories controller 2025-06-12 15:19:49 -05:00
spencerrlongg 1cee7e43ed more (reusable) exceptions, a couple notes 2025-06-12 00:47:57 -05:00
spencerrlongg 5e81c63d6e some notes and things moved 2025-06-11 11:39:14 -05:00
spencerrlongg 17456482d6 category destroy action 2025-06-04 21:42:58 -05:00
spencerrlongg a0431e1912 supplier actions working 2025-06-04 20:44:18 -05:00
spencerrlongg ee5aac8008 supplier destroy action creaated and a lot scratched out 2025-06-03 20:25:07 -05:00
611 changed files with 5559 additions and 1916 deletions
+3 -3
View File
@@ -30,10 +30,10 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
+1 -1
View File
@@ -52,6 +52,6 @@ jobs:
# Upload the SARIF file generated in the previous step
- name: Upload SARIF results file
uses: github/codeql-action/upload-sarif@v3
uses: github/codeql-action/upload-sarif@v4
with:
sarif_file: results.sarif
@@ -0,0 +1,59 @@
<?php
namespace App\Actions\Categories;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssetModels;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Models\Category;
use Illuminate\Support\Facades\Storage;
class DestroyCategoryAction
{
/**
* @throws ItemStillHasAssets
* @throws ItemStillHasAssetModels
* @throws ItemStillHasComponents
* @throws ItemStillHasAccessories
* @throws ItemStillHasLicenses
* @throws ItemStillHasConsumables
*/
static function run(Category $category): bool
{
$category->loadCount([
'assets as assets_count',
'accessories as accessories_count',
'consumables as consumables_count',
'components as components_count',
'licenses as licenses_count',
'models as models_count'
]);
if ($category->assets_count > 0) {
throw new ItemStillHasAssets($category);
}
if ($category->accessories_count > 0) {
throw new ItemStillHasAccessories($category);
}
if ($category->consumables_count > 0) {
throw new ItemStillHasConsumables($category);
}
if ($category->components_count > 0) {
throw new ItemStillHasComponents($category);
}
if ($category->licenses_count > 0) {
throw new ItemStillHasLicenses($category);
}
if ($category->models_count > 0) {
throw new ItemStillHasAssetModels($category);
}
Storage::disk('public')->delete('categories'.'/'.$category->image);
$category->delete();
return true;
}
}
@@ -0,0 +1,63 @@
<?php
namespace App\Actions\Manufacturers;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Models\Manufacturer;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class DeleteManufacturerAction
{
/**
* @throws ItemStillHasAssets
* @throws ItemStillHasComponents
* @throws ItemStillHasAccessories
* @throws ItemStillHasLicenses
* @throws ItemStillHasConsumables
*/
static function run(Manufacturer $manufacturer): bool
{
$manufacturer->loadCount([
'assets as assets_count',
'accessories as accessories_count',
'consumables as consumables_count',
'components as components_count',
'licenses as licenses_count',
]);
if ($manufacturer->assets_count > 0) {
throw new ItemStillHasAssets($manufacturer);
}
if ($manufacturer->accessories_count > 0) {
throw new ItemStillHasAccessories($manufacturer);
}
if ($manufacturer->consumables_count > 0) {
throw new ItemStillHasConsumables($manufacturer);
}
if ($manufacturer->components_count > 0) {
throw new ItemStillHasComponents($manufacturer);
}
if ($manufacturer->licenses_count > 0) {
throw new ItemStillHasLicenses($manufacturer);
}
if ($manufacturer->image) {
try {
Storage::disk('public')->delete('manufacturers/'.$manufacturer->image);
} catch (\Exception $e) {
Log::info($e);
}
}
$manufacturer->delete();
//dd($manufacturer);
return true;
}
}
@@ -0,0 +1,72 @@
<?php
namespace App\Actions\Suppliers;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Models\Supplier;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasMaintenances;
use App\Exceptions\ItemStillHasLicenses;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Storage;
class DestroySupplierAction
{
/**
*
* @throws ItemStillHasLicenses
* @throws ItemStillHasAssets
* @throws ItemStillHasMaintenances
* @throws ItemStillHasAccessories
* @throws ItemStillHasConsumables
* @throws ItemStillHasComponents
*/
static function run(Supplier $supplier): bool
{
$supplier->loadCount([
'maintenances as maintenances_count',
'assets as assets_count',
'licenses as licenses_count',
'accessories as accessories_count',
'consumables as consumables_count',
'components as components_count',
]);
if ($supplier->assets_count > 0) {
throw new ItemStillHasAssets($supplier);
}
if ($supplier->maintenances_count > 0) {
throw new ItemStillHasMaintenances($supplier);
}
if ($supplier->licenses_count > 0) {
throw new ItemStillHasLicenses($supplier);
}
if ($supplier->accessories_count > 0) {
throw new ItemStillHasAccessories($supplier);
}
if ($supplier->consumables_count > 0) {
throw new ItemStillHasConsumables($supplier);
}
if ($supplier->components_count > 0) {
throw new ItemStillHasComponents($supplier);
}
if ($supplier->image) {
try {
Storage::disk('public')->delete('suppliers/'.$supplier->image);
} catch (\Exception $e) {
Log::info($e->getMessage());
}
}
$supplier->delete();
return true;
}
}
+12
View File
@@ -317,9 +317,21 @@ class LdapSync extends Command
if($ldap_map["jobtitle"] != null){
$user->jobtitle = $item['jobtitle'];
}
if($ldap_map["address"] != null){
$user->address = $item['address'];
}
if($ldap_map["city"] != null){
$user->city = $item['city'];
}
if($ldap_map["state"] != null){
$user->state = $item['state'];
}
if($ldap_map["country"] != null){
$user->country = $item['country'];
}
if($ldap_map["zip"] != null){
$user->zip = $item['zip'];
}
if($ldap_map["dept"] != null){
$user->department_id = $department->id;
}
@@ -0,0 +1,56 @@
<?php
namespace App\Console\Commands;
use App\Models\Actionlog;
use Illuminate\Console\Command;
class RemoveInvalidUploadDeleteActionLogItems extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:remove-invalid-upload-delete-action-log-items';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Permanently remove invalid "upload deleted" action log items that have a null filename. This command can potentially result in deleted files being "resurrected" in the UI.';
/**
* Execute the console command.
*/
public function handle()
{
$invalidLogs = Actionlog::query()
->where('action_type', 'upload deleted')
->whereNull('filename')
->withTrashed()
->get();
$this->info("{$invalidLogs->count()} invalid log items found.");
if ($invalidLogs->count() === 0) {
return 0;
}
$this->table(['ID', 'Action Type', 'Item Type', 'Item ID', 'Created At', 'Deleted At'], $invalidLogs->map(fn($log) => [
$log->id,
$log->action_type,
$log->item_type,
$log->item_id,
$log->created_at,
$log->deleted_at,
])->toArray());
if ($this->confirm("Do you wish to remove {$invalidLogs->count()} log items?")) {
$invalidLogs->each(fn($log) => $log->forceDelete());
}
return 0;
}
}
@@ -107,7 +107,7 @@ class SendExpirationAlerts extends Command
trans('general.name') => $item->name,
trans('general.purchase_date') => $item->purchase_date_formatted,
trans('admin/licenses/form.expiration') => $item->expires_formatted_date,
trans('mail.expires') => $item->expires_diff_for_humans,
trans('mail.expires') => $item->expires_formatted_date ? $item->expires_diff_for_humans : '',
trans('admin/licenses/form.termination_date') => $item->terminates_formatted_date,
trans('mail.terminates') => $item->terminates_diff_for_humans
])
@@ -47,7 +47,7 @@ class SendUpcomingAuditReport extends Command
$today = Carbon::now();
$interval_date = $today->copy()->addDays($interval);
$assets = Asset::whereNull('deleted_at')->dueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
$assets = Asset::whereNull('deleted_at')->dueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'asc')->get();
$this->info($assets->count() . ' assets must be audited in on or before ' . $interval_date . ' is deadline');
@@ -61,6 +61,28 @@ class SendUpcomingAuditReport extends Command
$this->info('Sending Admin SendUpcomingAuditNotification to: ' . $settings->alert_email);
Mail::to($recipients)->send(new SendUpcomingAuditMail($assets, $settings->audit_warning_days));
$this->table(
[
trans('general.id'),
trans('general.name'),
trans('general.last_audit'),
trans('general.next_audit_date'),
trans('mail.Days'),
trans('mail.supplier'),
trans('mail.assigned_to'),
],
$assets->map(fn($item) => [
trans('general.id') => $item->id,
trans('general.name') => $item->display_name,
trans('general.last_audit') => $item->last_audit_formatted_date,
trans('general.next_audit_date') => $item->next_audit_formatted_date,
trans('mail.Days') => round($item->next_audit_diff_in_days),
trans('mail.supplier') => $item->supplier ? $item->supplier->name : '',
trans('mail.assigned_to') => $item->assignedTo ? $item->assignedTo->display_name : '',
])
);
}
}
@@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasAccessories extends ItemStillHasChildren
{
//
}
@@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasAssetModels extends ItemStillHasChildren
{
//
}
+9
View File
@@ -0,0 +1,9 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasAssets extends ItemStillHasChildren
{
}
+14
View File
@@ -0,0 +1,14 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasChildren extends Exception
{
//public function __construct($message, $code = 0, Exception $previous = null, $parent, $children)
//{
// trans()
//
//}
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasComponents extends ItemStillHasChildren
{
//
}
@@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasConsumables extends ItemStillHasChildren
{
//
}
+10
View File
@@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasLicenses extends ItemStillHasChildren
{
//
}
@@ -0,0 +1,10 @@
<?php
namespace App\Exceptions;
use Exception;
class ItemStillHasMaintenances extends ItemStillHasChildren
{
//
}
+4
View File
@@ -195,6 +195,10 @@ class IconHelper
case 'note':
case 'notes':
return 'fas fa-sticky-note';
case 'tip':
return 'fa-solid fa-lightbulb';
case 'highlight':
return 'fa-solid fa-highlighter';
}
}
}
@@ -157,6 +157,8 @@ class AcceptanceController extends Controller
'accepted_date' => Helper::getFormattedDateObject(now()->format('Y-m-d H:i:s'), 'datetime', false),
'declined_date' => Helper::getFormattedDateObject(now()->format('Y-m-d H:i:s'), 'datetime', false),
'assigned_to' => $assigned_user->display_name,
'email' => $assigned_user->email,
'employee_num' => $assigned_user->employee_num,
'site_name' => $settings->site_name,
'company_name' => $item->company?->name?? $settings->site_name,
'signature' => (($sig_filename && array_key_exists('1', $encoded_image))) ? $encoded_image[1] : null,
@@ -54,6 +54,15 @@ class AccessoriesController extends Controller
'notes',
'checkouts_count',
'qty',
// These are *relationships* so we wouldn't normally include them in this array,
// since they would normally create a `column not found` error,
// BUT we account for them in the ordering switch down at the end of this method
// DO NOT ADD ANYTHING TO THIS LIST WITHOUT CHECKING THE ORDERING SWITCH BELOW!
'company',
'location',
'category',
'supplier',
'manufacturer',
];
@@ -61,10 +70,23 @@ class AccessoriesController extends Controller
->with('category', 'company', 'manufacturer', 'checkouts', 'location', 'supplier', 'adminuser')
->withCount('checkouts as checkouts_count');
if ($request->filled('search')) {
$accessories = $accessories->TextSearch($request->input('search'));
$filter = [];
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
if ((! is_null($filter)) && (count($filter)) > 0) {
$accessories->ByFilter($filter);
} elseif ($request->filled('search')) {
$accessories->TextSearch($request->input('search'));
}
if ($request->filled('company_id')) {
$accessories->where('accessories.company_id', '=', $request->input('company_id'));
}
@@ -54,6 +54,12 @@ class AssetModelsController extends Controller
'deleted_at',
'updated_at',
'require_serial',
// These are *relationships* so we wouldn't normally include them in this array,
// since they would normally create a `column not found` error,
// BUT we account for them in the ordering switch down at the end of this method
// DO NOT ADD ANYTHING TO THIS LIST WITHOUT CHECKING THE ORDERING SWITCH BELOW!
'manufacturer',
'category',
];
$assetmodels = AssetModel::select([
@@ -81,6 +87,24 @@ class AssetModelsController extends Controller
->withCount('assignedAssets as assets_assigned_count')
->withCount('archivedAssets as assets_archived_count');
$filter = [];
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
if ((! is_null($filter)) && (count($filter)) > 0) {
$assetmodels->ByFilter($filter);
} elseif ($request->filled('search')) {
$assetmodels->TextSearch($request->input('search'));
}
if ($request->input('status')=='deleted') {
$assetmodels->onlyTrashed();
}
+18 -1
View File
@@ -116,6 +116,22 @@ class AssetsController extends Controller
'asset_eol_date',
'requestable',
'jobtitle',
// These are *relationships* so we wouldn't normally include them in this array,
// since they would normally create a `column not found` error,
// BUT we account for them in the ordering switch down at the end of this method
// DO NOT ADD ANYTHING TO THIS LIST WITHOUT CHECKING THE ORDERING SWITCH BELOW!
'company',
'model',
'location',
'rtd_location',
'category',
'status_label',
'manufacturer',
'supplier',
'jobtitle',
'assigned_to',
'created_by',
];
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
@@ -132,6 +148,7 @@ class AssetsController extends Controller
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
$assets = Asset::select('assets.*')
@@ -166,7 +183,7 @@ class AssetsController extends Controller
// Search custom fields by column name
foreach ($all_custom_fields as $field) {
if ($request->filled($field->db_column_name()) && $field->db_column_name()) {
$assets->where($field->db_column_name(), '=', $request->input($field->db_column_name()));
$assets->where('assets.'.$field->db_column_name(), '=', $request->input($field->db_column_name()));
}
}
@@ -2,6 +2,8 @@
namespace App\Http\Controllers\Api;
use App\Actions\Categories\DestroyCategoryAction;
use App\Exceptions\ItemStillHasChildren;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CategoriesTransformer;
@@ -61,6 +63,23 @@ class CategoriesController extends Controller
->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count', 'models as models_count');
$filter = [];
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
if ((! is_null($filter)) && (count($filter)) > 0) {
$categories->ByFilter($filter);
} elseif ($request->filled('search')) {
$categories->TextSearch($request->input('search'));
}
/*
* This checks to see if we should override the Admin Setting to show archived assets in list.
* We don't currently use it within the Snipe-IT GUI, but will be useful for API integrations where they
@@ -74,10 +93,6 @@ class CategoriesController extends Controller
$categories = $categories->withCount('showableAssets as assets_count');
}
if ($request->filled('search')) {
$categories = $categories->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$categories->where('name', '=', $request->input('name'));
}
@@ -211,17 +226,21 @@ class CategoriesController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id) : JsonResponse
public function destroy(Category $category): JsonResponse
{
$this->authorize('delete', Category::class);
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count', 'models as models_count')->findOrFail($id);
if (! $category->isDeletable()) {
try {
DestroyCategoryAction::run(category: $category);
} catch (ItemStillHasChildren $e) {
return response()->json(
Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>$category->category_type]))
Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.general_assoc_warning', ['asset_type' => $category->category_type]))
);
} catch (\Exception $e) {
report($e);
return response()->json(
Helper::formatStandardApiResponse('error', null, trans('general.something_went_wrong'))
);
}
$category->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/categories/message.delete.success')));
}
@@ -45,16 +45,40 @@ class ComponentsController extends Controller
'qty',
'image',
'notes',
// These are *relationships* so we wouldn't normally include them in this array,
// since they would normally create a `column not found` error,
// BUT we account for them in the ordering switch down at the end of this method
// DO NOT ADD ANYTHING TO THIS LIST WITHOUT CHECKING THE ORDERING SWITCH BELOW!
'company',
'location',
'category',
'manufacturer',
'supplier',
];
$components = Component::select('components.*')
->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser', 'manufacturer', 'uncontrainedAssets')
->withSum('uncontrainedAssets', 'components_assets.assigned_qty');
if ($request->filled('search')) {
$components = $components->TextSearch($request->input('search'));
$filter = [];
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
if ((! is_null($filter)) && (count($filter)) > 0) {
$components->ByFilter($filter);
} elseif ($request->filled('search')) {
$components->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$components->where('name', '=', $request->input('name'));
}
@@ -31,10 +31,53 @@ class ConsumablesController extends Controller
$consumables = Consumable::with('company', 'location', 'category', 'supplier', 'manufacturer')
->withCount('users as consumables_users_count');
if ($request->filled('search')) {
$consumables = $consumables->TextSearch(e($request->input('search')));
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
// These must match a column on the consumables table directly.
$allowed_columns = [
'id',
'name',
'order_number',
'min_amt',
'purchase_date',
'purchase_cost',
'company',
'category',
'model_number',
'item_no',
'manufacturer',
'location',
'qty',
'image',
// These are *relationships* so we wouldn't normally include them in this array,
// since they would normally create a `column not found` error,
// BUT we account for them in the ordering switch down at the end of this method
// DO NOT ADD ANYTHING TO THIS LIST WITHOUT CHECKING THE ORDERING SWITCH BELOW!
'company',
'location',
'category',
'supplier',
'manufacturer',
];
$filter = [];
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
if ((! is_null($filter)) && (count($filter)) > 0) {
$consumables->ByFilter($filter);
} elseif ($request->filled('search')) {
$consumables->TextSearch($request->input('search'));
}
if ($request->filled('name')) {
$consumables->where('name', '=', $request->input('name'));
}
@@ -96,25 +139,6 @@ class ConsumablesController extends Controller
$consumables = $consumables->OrderByCreatedBy($order);
break;
default:
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
// These must match a column on the consumables table directly.
$allowed_columns = [
'id',
'name',
'order_number',
'min_amt',
'purchase_date',
'purchase_cost',
'company',
'category',
'model_number',
'item_no',
'manufacturer',
'location',
'qty',
'image'
];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$consumables = $consumables->orderBy($sort, $order);
break;
@@ -52,6 +52,10 @@ class MaintenancesController extends Controller
$maintenances->where('maintenances.created_by', '=', $request->input('created_by'));
}
if ($request->filled('url')) {
$maintenances->where('maintenances.url', '=', $request->input('url'));
}
if ($request->filled('asset_maintenance_type')) {
$maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type'));
}
@@ -2,6 +2,13 @@
namespace App\Http\Controllers\Api;
use App\Actions\Manufacturers\DeleteManufacturerAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasChildren;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\ManufacturersTransformer;
@@ -184,19 +191,19 @@ class ManufacturersController extends Controller
* @since [v4.0]
* @param int $id
*/
public function destroy($id) : JsonResponse
public function destroy(Manufacturer $manufacturer): JsonResponse
{
$this->authorize('delete', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
$this->authorize('delete', $manufacturer);
if ($manufacturer->isDeletable()) {
$manufacturer->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
try {
DeleteManufacturerAction::run($manufacturer);
} catch (ItemStillHasChildren $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.general_assoc_warning', ['item' => trans('general.manufacturer')])));
} catch (\Exception $e) {
report($e);
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.something_went_wrong')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/manufacturers/message.assoc_users')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
}
/**
@@ -2,6 +2,13 @@
namespace App\Http\Controllers\Api;
use App\Actions\Suppliers\DestroySupplierAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasMaintenances;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasLicenses;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\SelectlistTransformer;
@@ -191,27 +198,40 @@ class SuppliersController extends Controller
* @since [v4.0]
* @param int $id
*/
public function destroy($id) : JsonResponse
public function destroy(Supplier $supplier): JsonResponse
{
$this->authorize('delete', Supplier::class);
$supplier = Supplier::with('maintenances', 'assets', 'licenses')->withCount('maintenances as maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
$this->authorize('delete', $supplier);
if ($supplier->assets_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count])));
try {
DestroySupplierAction::run(supplier: $supplier);
} catch (ItemStillHasAssets $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.assoc_assets', [
'asset_count' => (int) $supplier->assets_count, 'item' => trans('general.supplier')
])));
} catch (ItemStillHasMaintenances $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.assoc_maintenances', [
'asset_maintenances_count' => $supplier->asset_maintenances_count, 'item' => trans('general.supplier')
])));
} catch (ItemStillHasLicenses $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.assoc_licenses', [
'licenses_count' => (int) $supplier->licenses_count, 'item' => trans('general.supplier')
])));
} catch (ItemStillHasAccessories $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.assoc_accessories', [
'accessories_count' => (int) $supplier->accessories_count, 'item' => trans('general.supplier')
])));
} catch (ItemStillHasConsumables $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.assoc_consumables', [
'consumables_count' => (int) $supplier->consumables_count, 'item' => trans('general.supplier')
])));
} catch (ItemStillHasComponents $e) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.bulk_delete_associations.assoc_components', [
'components_count' => (int) $supplier->components_count, 'item' => trans('general.supplier')
])));
} catch (\Exception $e) {
report($e);
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.something_went_wrong')));
}
if ($supplier->maintenances_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['maintenances_count' => $supplier->maintenances_count])));
}
if ($supplier->licenses_count > 0) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count])));
}
$supplier->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/suppliers/message.delete.success')));
}
+68 -45
View File
@@ -103,9 +103,75 @@ class UsersController extends Controller
'managedLocations as manages_locations_count'
]);
$allowed_columns =
[
'last_name',
'first_name',
'display_name',
'email',
'jobtitle',
'username',
'employee_num',
'groups',
'activated',
'created_at',
'updated_at',
'two_factor_enrolled',
'two_factor_optin',
'last_login',
'assets_count',
'licenses_count',
'consumables_count',
'accessories_count',
'manages_users_count',
'manages_locations_count',
'phone',
'mobile',
'address',
'city',
'state',
'country',
'zip',
'id',
'ldap_import',
'two_factor_optin',
'two_factor_enrolled',
'remote',
'vip',
'start_date',
'end_date',
'autoassign_licenses',
'website',
'locale',
'notes',
'employee_num',
if ($request->filled('search') != '') {
$users = $users->TextSearch($request->input('search'));
// These are *relationships* so we wouldn't normally include them in this array,
// since they would normally create a `column not found` error,
// BUT we account for them in the ordering switch down at the end of this method
// DO NOT ADD ANYTHING TO THIS LIST WITHOUT CHECKING THE ORDERING SWITCH BELOW!
'company',
'location',
'department',
'manager',
'created_by',
];
$filter = [];
if ($request->filled('filter')) {
$filter = json_decode($request->input('filter'), true);
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
return in_array($key, $allowed_columns);
}, ARRAY_FILTER_USE_KEY);
}
if ((! is_null($filter)) && (count($filter)) > 0) {
$users->ByFilter($filter);
} elseif ($request->filled('search')) {
$users->TextSearch($request->input('search'));
}
if ($request->filled('activated')) {
@@ -286,49 +352,6 @@ class UsersController extends Controller
$users->orderBy('first_name', $order);
break;
default:
$allowed_columns =
[
'last_name',
'first_name',
'display_name',
'email',
'jobtitle',
'username',
'employee_num',
'groups',
'activated',
'created_at',
'updated_at',
'two_factor_enrolled',
'two_factor_optin',
'last_login',
'assets_count',
'licenses_count',
'consumables_count',
'accessories_count',
'manages_users_count',
'manages_locations_count',
'phone',
'mobile',
'address',
'city',
'state',
'country',
'zip',
'id',
'ldap_import',
'two_factor_optin',
'two_factor_enrolled',
'remote',
'vip',
'start_date',
'end_date',
'autoassign_licenses',
'website',
'locale',
'notes',
];
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'first_name';
$users = $users->orderBy($sort, $order);
break;
@@ -240,10 +240,6 @@ class BulkAssetsController extends Controller
$custom_fields_to_null[str_replace('null', '', $key)] = $value;
}
if (! $request->filled('ids') || count($request->input('ids')) == 0) {
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.update.no_assets_selected'));
@@ -274,6 +270,7 @@ class BulkAssetsController extends Controller
|| ($request->filled('company_id'))
|| ($request->filled('status_id'))
|| ($request->filled('model_id'))
|| ($request->filled('notes'))
|| ($request->filled('next_audit_date'))
|| ($request->filled('asset_eol_date'))
|| ($request->filled('null_name'))
@@ -0,0 +1,59 @@
<?php
namespace App\Http\Controllers;
use App\Actions\Categories\DestroyCategoryAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssetModels;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Models\Category;
use Illuminate\Http\Request;
class BulkCategoriesController extends Controller
{
public function destroy(Request $request)
{
$this->authorize('delete', Category::class);
$errors = [];
$success_count = 0;
foreach ($request->ids as $id) {
$category = Category::find($id);
if (is_null($category)) {
$errors[] = trans('admin/categories/message.does_not_exist');
continue;
}
try {
DestroyCategoryAction::run(category: $category);
$success_count++;
} catch (ItemStillHasAccessories $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_assets_no_count', ['item_name' => $category->name, 'item' => trans('general.category')]);
} catch (ItemStillHasAssetModels) {
$errors[] = trans('general.bulk_delete_associations.assoc_asset_models_no_count', ['item_name' => $category->name, 'item' => trans('general.category')]);
} catch (ItemStillHasAssets) {
$errors[] = trans('general.bulk_delete_associations.assoc_assets_no_count', ['item_name' => $category->name, 'item' => trans('general.category')]);
} catch (ItemStillHasComponents) {
$errors[] = trans('general.bulk_delete_associations.assoc_components_no_count', ['item_name' => $category->name, 'item' => trans('general.category')]);
} catch (ItemStillHasConsumables) {
$errors[] = trans('general.bulk_delete_associations.assoc_consumables_no_count', ['item_name' => $category->name, 'item' => trans('general.category')]);
} catch (ItemStillHasLicenses) {
$errors[] = trans('general.bulk_delete_associations.assoc_licenses_no_count', ['item_name' => $category->name, 'item' => trans('general.category')]);;
} catch (\Exception $e) {
report($e);
$errors[] = trans('general.something_went_wrong');
}
}
if (count($errors) > 0) {
if ($success_count > 0) {
return redirect()->route('categories.index')->with('success', trans_choice('admin/categories/message.delete.partial_success', $success_count, ['count' => $success_count]))->with('multi_error_messages', $errors);
}
return redirect()->route('categories.index')->with('multi_error_messages', $errors);
} else {
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.bulk_success'));
}
}
}
@@ -0,0 +1,57 @@
<?php
namespace App\Http\Controllers;
use App\Actions\Manufacturers\DeleteManufacturerAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssetModels;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasChildren;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Models\Manufacturer;
use Illuminate\Http\Request;
class BulkManufacturersController extends Controller
{
public function destroy(Request $request)
{
$this->authorize('delete', Manufacturer::class);
$errors = [];
$success_count = 0;
foreach ($request->ids as $id) {
$manufacturer = Manufacturer::find($id);
if (is_null($manufacturer)) {
$errors[] = trans('admin/manufacturers/message.does_not_exist');
continue;
}
try {
DeleteManufacturerAction::run(manufacturer: $manufacturer);
$success_count++;
} catch (ItemStillHasAssets $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_assets_no_count', ['item_name' => $manufacturer->name, 'item' => trans('general.manufacturer')]);
} catch (ItemStillHasAccessories $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_accessories_no_count', ['item_name' => $manufacturer->name, 'item' => trans('general.manufacturer')]);
} catch (ItemStillHasConsumables $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_consumables_no_count', ['item_name' => $manufacturer->name, 'item' => trans('general.manufacturer')]);
} catch (ItemStillHasComponents $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_components_no_count', ['item_name' => $manufacturer->name, 'item' => trans('general.manufacturer')]);
} catch (ItemStillHasLicenses $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_licenses_no_count', ['item_name' => $manufacturer->name, 'item' => trans('general.manufacturer')]);;
} catch (\Exception $e) {
report($e);
$errors[] = trans('general.something_went_wrong');
}
}
if (count($errors) > 0) {
if ($success_count > 0) {
return redirect()->route('manufacturers.index')->with('success', trans_choice('admin/manufacturers/message.delete.partial_success', $success_count, ['count' => $success_count]))->with('multi_error_messages', $errors);
}
return redirect()->route('manufacturers.index')->with('multi_error_messages', $errors);
} else {
return redirect()->route('manufacturers.index')->with('success', trans('admin/manufacturers/message.delete.bulk_success'));
}
}
}
@@ -0,0 +1,58 @@
<?php
namespace App\Http\Controllers;
use App\Actions\Suppliers\DestroySupplierAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasMaintenances;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasLicenses;
use App\Models\Supplier;
use Illuminate\Http\Request;
class BulkSuppliersController extends Controller
{
public function destroy(Request $request)
{
$this->authorize('delete', Supplier::class);
$errors = [];
$success_count = 0;
foreach ($request->ids as $id) {
$supplier = Supplier::find($id);
if (is_null($supplier)) {
$errors[] = trans('admin/suppliers/message.delete.not_found');
continue;
}
try {
DestroySupplierAction::run(supplier: $supplier);
} catch (ItemStillHasAssets $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_assets', ['asset_count' => (int) $supplier->assets_count, 'item' => trans('general.supplier'), 'item_name' => $supplier->name]);
} catch (ItemStillHasMaintenances $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count, 'item' => trans('general.supplier'), 'item_name' => $supplier->name]);
} catch (ItemStillHasLicenses $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count, 'item' => trans('general.supplier'), 'item_name' => $supplier->name]);
} catch (ItemStillHasAccessories $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_accessories', ['accessories_count' => (int) $supplier->accessories_count, 'item' => trans('general.supplier'), 'item_name' => $supplier->name]);
} catch (ItemStillHasConsumables $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_consumables', ['consumables_count' => (int) $supplier->consumables_count, 'item' => trans('general.supplier'), 'item_name' => $supplier->name]);
} catch (ItemStillHasComponents $e) {
$errors[] = trans('general.bulk_delete_associations.assoc_components', ['components_count' => (int) $supplier->components_count, 'item' => trans('general.supplier'), 'item_name' => $supplier->name]);
} catch (\Exception $e) {
report($e);
$errors[] = trans('general.something_went_wrong');
}
}
if (count($errors) > 0) {
if ($success_count > 0) {
return redirect()->route('suppliers.index')->with('success', trans_choice('admin/suppliers/message.delete.partial_success', $success_count, ['count' => $success_count]))->with('multi_error_messages', $errors);
}
return redirect()->route('suppliers.index')->with('multi_error_messages', $errors);
} else {
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.delete.bulk_success'));
}
}
}
+16 -10
View File
@@ -2,6 +2,14 @@
namespace App\Http\Controllers;
use App\Actions\Categories\DestroyCategoryAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssetModels;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasChildren;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Category;
@@ -143,20 +151,18 @@ class CategoriesController extends Controller
* @since [v1.0]
* @param int $categoryId
*/
public function destroy($categoryId) : RedirectResponse
public function destroy(Category $category): RedirectResponse
{
$this->authorize('delete', Category::class);
// Check if the category exists
if (is_null($category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count', 'models as models_count')->findOrFail($categoryId))) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found'));
try {
DestroyCategoryAction::run($category);
} catch (ItemStillHasChildren $e) {
return redirect()->route('categories.index')->with('error', trans('general.bulk_delete_associations.general_assoc_warning', ['item' => trans('general.category')]));
} catch (\Exception $e) {
report($e);
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.delete.error'));
}
if (! $category->isDeletable()) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=> $category->category_type]));
}
Storage::disk('public')->delete('categories'.'/'.$category->image);
$category->delete();
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.success'));
}
@@ -78,6 +78,7 @@ class MaintenancesController extends Controller
$maintenance->is_warranty = $request->input('is_warranty');
$maintenance->cost = $request->input('cost');
$maintenance->notes = $request->input('notes');
$maintenance->url = $request->input('url');
// Save the asset maintenance data
$maintenance->asset_id = $asset->id;
@@ -152,6 +153,7 @@ class MaintenancesController extends Controller
$maintenance->name = $request->input('name');
$maintenance->start_date = $request->input('start_date');
$maintenance->completion_date = $request->input('completion_date');
$maintenance->url = $request->input('url');
// Todo - put this in a getter/setter?
@@ -2,6 +2,14 @@
namespace App\Http\Controllers;
use App\Actions\Manufacturers\DeleteManufacturerAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasChildren;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasLicenses;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Actionlog;
use App\Models\Manufacturer;
@@ -157,32 +165,18 @@ class ManufacturersController extends Controller
* @param int $manufacturerId
* @since [v1.0]
*/
public function destroy($manufacturerId) : RedirectResponse
public function destroy(Manufacturer $manufacturer): RedirectResponse
{
$this->authorize('delete', Manufacturer::class);
if (is_null($manufacturer = Manufacturer::withTrashed()->withCount('models as models_count')->find($manufacturerId))) {
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.not_found'));
$this->authorize('delete', $manufacturer);
try {
DeleteManufacturerAction::run($manufacturer);
} catch (ItemStillHasChildren $e) {
return redirect()->route('manufacturers.index')->with('error', trans('general.bulk_delete_associations.general_assoc_warning', ['item' => trans('general.manufacturer')]));
} catch (\Exception $e) {
report($e);
return redirect()->route('manufacturers.index')->with('error', trans('general.something_went_wrong'));
}
if (! $manufacturer->isDeletable()) {
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.assoc_users'));
}
if ($manufacturer->image) {
try {
Storage::disk('public')->delete('manufacturers/'.$manufacturer->image);
} catch (\Exception $e) {
Log::info($e);
}
}
// Soft delete the manufacturer if active, permanent delete if is already deleted
if ($manufacturer->deleted_at === null) {
$manufacturer->delete();
} else {
$manufacturer->forceDelete();
}
// Redirect to the manufacturers management page
return redirect()->route('manufacturers.index')->with('success', trans('admin/manufacturers/message.delete.success'));
}
+2 -4
View File
@@ -436,10 +436,8 @@ class ReportsController extends Controller
// Open output stream
$handle = fopen('php://output', 'w');
stream_set_timeout($handle, 2000);
if ($request->filled('use_bom')) {
fprintf($handle, chr(0xEF).chr(0xBB).chr(0xBF));
}
fprintf($handle, chr(0xEF).chr(0xBB).chr(0xBF));
$header = [];
+39 -21
View File
@@ -2,10 +2,18 @@
namespace App\Http\Controllers;
use App\Actions\Suppliers\DestroySupplierAction;
use App\Exceptions\ItemStillHasAccessories;
use App\Exceptions\ItemStillHasComponents;
use App\Exceptions\ItemStillHasConsumables;
use App\Exceptions\ItemStillHasMaintenances;
use App\Exceptions\ItemStillHasAssets;
use App\Exceptions\ItemStillHasLicenses;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Supplier;
use Illuminate\Http\RedirectResponse;
use \Illuminate\Contracts\View\View;
use Illuminate\Support\MessageBag;
/**
* This controller handles all actions related to Suppliers for
@@ -118,30 +126,41 @@ class SuppliersController extends Controller
*
* @param int $supplierId
*/
public function destroy($supplierId) : RedirectResponse
public function destroy(Supplier $supplier): RedirectResponse
{
$this->authorize('delete', Supplier::class);
if (is_null($supplier = Supplier::with('maintenances', 'assets', 'licenses')->withCount('maintenances as maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->find($supplierId))) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
try {
DestroySupplierAction::run(supplier: $supplier);
} catch (ItemStillHasAssets $e) {
return redirect()->route('suppliers.index')->with('error', trans('general.bulk_delete_associations.assoc_assets', [
'asset_count' => (int) $supplier->assets_count, 'item' => trans('general.supplier')
]));
} catch (ItemStillHasMaintenances $e) {
return redirect()->route('suppliers.index')->with('error', trans('general.bulk_delete_associations.assoc_maintenances', [
'asset_maintenances_count' => $supplier->asset_maintenances_count, 'item' => trans('general.supplier')
]));
} catch (ItemStillHasLicenses $e) {
return redirect()->route('suppliers.index')->with('error', trans('general.bulk_delete_associations.assoc_licenses', [
'licenses_count' => (int) $supplier->licenses_count, 'item' => trans('general.supplier')
]));
} catch (ItemStillHasAccessories $e) {
return redirect()->route('suppliers.index')->with('error', trans('general.bulk_delete_associations.assoc_accessories', [
'accessories_count' => (int) $supplier->accessories_count, 'item' => trans('general.supplier')
]));
} catch (ItemStillHasConsumables $e) {
return redirect()->route('suppliers.index')->with('error', trans('general.bulk_delete_associations.assoc_consumables', [
'consumables_count' => (int) $supplier->consumables_count, 'item' => trans('general.supplier')
]));
} catch (ItemStillHasComponents $e) {
return redirect()->route('suppliers.index')->with('error', trans('general.bulk_delete_associations.assoc_components', [
'components_count' => (int) $supplier->components_count, 'item' => trans('general.supplier')
]));
} catch (\Exception $e) {
report($e);
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.error'));
}
if ($supplier->assets_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count]));
}
if ($supplier->maintenances_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['maintenances_count' => $supplier->maintenances_count]));
}
if ($supplier->licenses_count > 0) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count]));
}
$supplier->delete();
return redirect()->route('suppliers.index')->with('success',
trans('admin/suppliers/message.delete.success')
);
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.delete.success'));
}
/**
@@ -154,6 +173,5 @@ class SuppliersController extends Controller
{
$this->authorize('view', Supplier::class);
return view('suppliers/view', compact('supplier'));
}
}
+1
View File
@@ -26,6 +26,7 @@ class StoreAssetRequest extends ImageUploadRequest
public function prepareForValidation(): void
{
parent::prepareForValidation(); // call ImageUploadRequest thing
// Guard against users passing in an array for company_id instead of an integer.
// If the company_id is not an integer then we simply use what was
// provided to be caught by model level validation later.
+5 -10
View File
@@ -2,6 +2,7 @@
namespace App\Http\Traits;
use Illuminate\Validation\ValidationException;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Arr;
use Illuminate\Support\Collection;
@@ -38,20 +39,13 @@ trait ConvertsBase64ToFiles
if (!$base64Contents) {
return;
}
// autogenerate filenames
if ($filename == 'auto'){
$header = explode(';', $base64Contents, 2)[0];
// Grab the image type from the header while we're at it.
$filename = $key . '.' . substr($header, strpos($header, '/')+1);
}
// Generate a temporary path to store the Base64 contents
$tempFilePath = tempnam(sys_get_temp_dir(), $filename);
// Store the contents using a stream, or by decoding manually
// Store the contents using a stream, or throw an Error (which doesn't do anything?)
if (Str::startsWith($base64Contents, 'data:') && count(explode(',', $base64Contents)) > 1) {
$source = fopen($base64Contents, 'r');
$source = fopen($base64Contents, 'r'); // PHP has special processing for "data:" URL's
$destination = fopen($tempFilePath, 'w');
stream_copy_to_stream($source, $destination);
@@ -59,7 +53,8 @@ trait ConvertsBase64ToFiles
fclose($source);
fclose($destination);
} else {
file_put_contents($tempFilePath, base64_decode($base64Contents, true));
// TODO - to get a better error message here, can we maybe do something with modifying the errorBag?
throw new ValidationException("Need Base64 URL starting with 'data:'"); // This doesn't actually throw?
}
$uploadedFile = new UploadedFile($tempFilePath, $filename, null, null, true);
@@ -66,6 +66,7 @@ class MaintenancesTransformer
'id' => $assetmaintenance->supplier->id,
'name'=> e($assetmaintenance->supplier->name)
] : null,
'url' => ($assetmaintenance->url) ? e($assetmaintenance->url) : null,
'cost' => Helper::formatCurrencyOutput($assetmaintenance->cost),
'asset_maintenance_type' => e($assetmaintenance->asset_maintenance_type),
'start_date' => Helper::getFormattedDateObject($assetmaintenance->start_date, 'date'),
+84
View File
@@ -390,7 +390,91 @@ class Accessory extends SnipeModel
* BEGIN QUERY SCOPES
* -----------------------------------------------
**/
/**
* Query builder scope to search on text filters for complex Bootstrap Tables API
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $filter JSON array of search keys and terms
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeByFilter($query, $filter)
{
return $query->where(
function ($query) use ($filter) {
foreach ($filter as $fieldname => $search_val) {
if ($fieldname == 'name') {
$query->where('accessories.name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'notes') {
$query->where('accessories.notes', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'model_number') {
$query->where('accessories.model_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'order_number') {
$query->where('accessories.order_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'purchase_cost') {
$query->where('accessories.purchase_cost', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'location') {
$query->whereHas(
'location', function ($query) use ($search_val) {
$query->where('locations.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'manufacturer') {
$query->whereHas(
'manufacturer', function ($query) use ($search_val) {
$query->where('manufacturers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'supplier') {
$query->whereHas(
'supplier', function ($query) use ($search_val) {
$query->where('suppliers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'category') {
$query->whereHas(
'category', function ($query) use ($search_val) {
$query->where('categories.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'company') {
$query->whereHas(
'company', function ($query) use ($search_val) {
$query->where('companies.name', 'LIKE', '%'.$search_val.'%');
}
);
}
}
}
);
}
/**
* Query builder scope to order on created_by name
+4
View File
@@ -493,6 +493,10 @@ class Actionlog extends SnipeModel
return 'private_uploads/eula-pdfs/'.$this->filename;
}
if ($this->action_type == 'audit') {
return 'private_uploads/audits/'.$this->filename;
}
switch ($this->item_type) {
case Accessory::class:
return 'private_uploads/accessories/'.$this->filename;
+98 -34
View File
@@ -308,6 +308,54 @@ class Asset extends Depreciable
}
protected function lastAuditFormattedDate(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => Helper::getFormattedDateObject($this->last_audit_date, 'datetime', false)
);
}
protected function lastAuditDiff(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $this->warrantyExpires ? round((Carbon::now()->diffInDays($this->warrantyExpires))) : null,
);
}
protected function lastAuditDiffForHumans(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $attributes['last_audit_date'] ? Carbon::parse($attributes['last_audit_date'])->diffForHumans() : null,
);
}
protected function nextAuditFormattedDate(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => Helper::getFormattedDateObject($this->next_audit_date, 'date', false)
);
}
protected function nextAuditDiffInDays(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $attributes['next_audit_date'] ? Carbon::now()->diffInDays($attributes['next_audit_date']) : null,
);
}
protected function nextAuditDiffForHumans(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $attributes['next_audit_date'] ? Carbon::parse($attributes['next_audit_date'])->diffForHumans() : null,
);
}
protected function eolDate(): Attribute
{
@@ -326,6 +374,7 @@ class Asset extends Depreciable
}
protected function eolFormattedDate(): Attribute
{
return Attribute:: make(
@@ -350,6 +399,12 @@ class Asset extends Depreciable
}
protected function expectedCheckinFormattedDate(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => array_key_exists('expected_checkin', $attributes) ? Helper::getFormattedDateObject($attributes['expected_checkin'], 'date', false) : null,
);
}
/**
* Establishes the asset -> company relationship
@@ -1832,16 +1887,32 @@ class Asset extends Depreciable
);
}
if ($fieldname =='assigned_to') {
if ($fieldname == 'assigned_to') {
$query->whereHasMorph(
'assignedTo', [User::class], function ($query) use ($search_val) {
$query->where(
function ($query) use ($search_val) {
$query->where('users.first_name', 'LIKE', '%'.$search_val.'%')
->orWhere('users.last_name', 'LIKE', '%'.$search_val.'%');
->orWhere('users.last_name', 'LIKE', '%'.$search_val.'%')
->orWhere('users.username', 'LIKE', '%'.$search_val.'%');
}
);
}
)->orWhereHasMorph(
'assignedTo', [Location::class], function ($query) use ($search_val) {
$query->where('locations.name', 'LIKE', '%'.$search_val.'%');
}
)->orWhereHasMorph(
'assignedTo', [Asset::class], function ($query) use ($search_val) {
$query->where(
function ($query) use ($search_val) {
// Don't use the asset table prefix here because it will pull from the original asset,
// not the subselect we're doing here to get the assigned asset
$query->where('name', 'LIKE', '%'.$search_val.'%')
->orWhere('asset_tag', 'LIKE', '%'.$search_val.'%');
}
);
}
);
}
@@ -1881,51 +1952,44 @@ class Asset extends Depreciable
}
if ($fieldname == 'model') {
$query->where(
function ($query) use ($search_val) {
$query->whereHas(
'model', function ($query) use ($search_val) {
$query->where('models.name', 'LIKE', '%'.$search_val.'%');
}
);
}
$query->whereHas(
'model', function ($query) use ($search_val) {
$query->where('models.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'model_number') {
$query->where(
function ($query) use ($search_val) {
$query->whereHas(
'model', function ($query) use ($search_val) {
$query->where('models.model_number', 'LIKE', '%'.$search_val.'%');
}
);
}
$query->whereHas(
'model', function ($query) use ($search_val) {
$query->where('models.model_number', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'company') {
$query->where(
function ($query) use ($search_val) {
$query->whereHas(
'company', function ($query) use ($search_val) {
$query->where('companies.name', 'LIKE', '%'.$search_val.'%');
}
);
}
$query->whereHas(
'company', function ($query) use ($search_val) {
$query->where('companies.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'supplier') {
$query->where(
function ($query) use ($search_val) {
$query->whereHas(
'supplier', function ($query) use ($search_val) {
$query->where('suppliers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
$query->whereHas(
'supplier', function ($query) use ($search_val) {
$query->where('suppliers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'status_label') {
$query->whereHas(
'assetstatus', function ($query) use ($search_val) {
$query->where('status_labels.name', 'LIKE', '%'.$search_val.'%');
}
);
}
+51
View File
@@ -256,6 +256,57 @@ class AssetModel extends SnipeModel
* -----------------------------------------------
**/
/**
* Query builder scope to search on text filters for complex Bootstrap Tables API
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $filter JSON array of search keys and terms
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeByFilter($query, $filter)
{
return $query->where(
function ($query) use ($filter) {
foreach ($filter as $fieldname => $search_val) {
if ($fieldname == 'name') {
$query->where('models.name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'notes') {
$query->where('models.notes', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'model_number') {
$query->where('models.model_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'category') {
$query->whereHas(
'category', function ($query) use ($search_val) {
$query->where('categories.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'manufacturer') {
$query->whereHas(
'manufacturer', function ($query) use ($search_val) {
$query->where('manufacturers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
}
}
);
}
/**
* scopeInCategory
* Get all models that are in the array of category ids
+29
View File
@@ -290,6 +290,35 @@ class Category extends SnipeModel
* -----------------------------------------------
**/
/**
* Query builder scope to search on text filters for complex Bootstrap Tables API
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $filter JSON array of search keys and terms
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeByFilter($query, $filter)
{
return $query->where(
function ($query) use ($filter) {
foreach ($filter as $fieldname => $search_val) {
if ($fieldname == 'name') {
$query->where('categories.name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'category_type') {
$query->where('categories.category_type', 'LIKE', '%' . $search_val . '%');
}
}
}
);
}
/**
* Query builder scope for whether or not the category requires acceptance
*
+4 -1
View File
@@ -210,7 +210,10 @@ class CheckoutAcceptance extends Model
if (($data['qty'] != null) && ($data['qty'] > 1)) {
$pdf->writeHTML(trans('general.qty').': '.e($data['qty']), true, 0, true, 0, '');
}
$pdf->writeHTML(trans('general.assignee').': '.e($data['assigned_to']), true, 0, true, 0, '');
$pdf->writeHTML(trans('general.assignee').': '.e($data['assigned_to']) . ($data['employee_num'] ? ' ('.$data['employee_num'].')' : ''), true, 0, true, 0, '');
if ($data['email'] != null) {
$pdf->writeHTML(trans('general.email').': '.e($data['email']), true, 0, true, 0, '');
}
$pdf->Ln();
$pdf->writeHTML('<hr>', true, 0, true, 0, '');
+91
View File
@@ -321,6 +321,97 @@ class Component extends SnipeModel
* -----------------------------------------------
**/
/**
* Query builder scope to search on text filters for complex Bootstrap Tables API
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $filter JSON array of search keys and terms
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeByFilter($query, $filter)
{
return $query->where(
function ($query) use ($filter) {
foreach ($filter as $fieldname => $search_val) {
if ($fieldname == 'name') {
$query->where('components.name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'notes') {
$query->where('components.notes', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'model_number') {
$query->where('components.model_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'order_number') {
$query->where('components.order_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'serial') {
$query->where('components.serial', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'serial') {
$query->where('components.serial', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'purchase_cost') {
$query->where('components.purchase_cost', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'location') {
$query->whereHas(
'location', function ($query) use ($search_val) {
$query->where('locations.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'manufacturer') {
$query->whereHas(
'manufacturer', function ($query) use ($search_val) {
$query->where('manufacturers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'supplier') {
$query->whereHas(
'supplier', function ($query) use ($search_val) {
$query->where('suppliers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'category') {
$query->whereHas(
'category', function ($query) use ($search_val) {
$query->where('categories.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'company') {
$query->whereHas(
'company', function ($query) use ($search_val) {
$query->where('companies.name', 'LIKE', '%'.$search_val.'%');
}
);
}
}
}
);
}
/**
* Query builder scope to order on company
+93
View File
@@ -345,6 +345,99 @@ class Consumable extends SnipeModel
* -----------------------------------------------
**/
/**
* Query builder scope to search on text filters for complex Bootstrap Tables API
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $filter JSON array of search keys and terms
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeByFilter($query, $filter)
{
return $query->where(
function ($query) use ($filter) {
foreach ($filter as $fieldname => $search_val) {
if ($fieldname == 'name') {
$query->where('consumables.name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'notes') {
$query->where('consumables.notes', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'model_number') {
$query->where('consumables.model_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'order_number') {
$query->where('consumables.order_number', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'item_no') {
$query->where('consumables.item_no', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'serial') {
$query->where('consumables.serial', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'purchase_cost') {
$query->where('consumables.purchase_cost', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'location') {
$query->whereHas(
'location', function ($query) use ($search_val) {
$query->where('locations.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'manufacturer') {
$query->whereHas(
'manufacturer', function ($query) use ($search_val) {
$query->where('manufacturers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'supplier') {
$query->whereHas(
'supplier', function ($query) use ($search_val) {
$query->where('suppliers.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'category') {
$query->whereHas(
'category', function ($query) use ($search_val) {
$query->where('categories.name', 'LIKE', '%'.$search_val.'%');
}
);
}
if ($fieldname == 'company') {
$query->whereHas(
'company', function ($query) use ($search_val) {
$query->where('companies.name', 'LIKE', '%'.$search_val.'%');
}
);
}
}
}
);
}
/**
* Query builder scope to order on company
*
+1 -1
View File
@@ -760,7 +760,7 @@ class License extends Depreciable
->orWhere(function ($query) {
$query->whereDate('expiration_date', '<=', Carbon::now());
})
->whereNull('deleted_at');
->whereNull('licenses.deleted_at');
}
/**
+2
View File
@@ -38,6 +38,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild
'completion_date' => 'date_format:Y-m-d|nullable|after_or_equal:start_date',
'notes' => 'string|nullable',
'cost' => 'numeric|nullable|gte:0|max:99999999999999999.99',
'url' => 'nullable|url|max:255',
];
@@ -57,6 +58,7 @@ class Maintenance extends SnipeModel implements ICompanyableChild
'asset_maintenance_time',
'notes',
'cost',
'url',
];
use Searchable;
+3 -3
View File
@@ -32,7 +32,7 @@ class SnipeModel extends Model
protected function expiresDiffInDays(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $attributes['expiration_date'] ? Carbon::now()->diffInDays($attributes['expiration_date']) : null,
get: fn(mixed $value, array $attributes) => array_key_exists('expiration_date', $attributes) ? Carbon::now()->diffInDays($attributes['expiration_date']) : null,
);
}
@@ -40,14 +40,14 @@ class SnipeModel extends Model
protected function expiresDiffForHumans(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $attributes['expiration_date'] ? Carbon::parse($attributes['expiration_date'])->diffForHumans() : null,
get: fn(mixed $value, array $attributes) => array_key_exists('expiration_date', $attributes) ? Carbon::parse($attributes['expiration_date'])->diffForHumans() : null,
);
}
protected function expiresFormattedDate(): Attribute
{
return Attribute:: make(
get: fn(mixed $value, array $attributes) => $attributes['expiration_date'] ? Helper::getFormattedDateObject($attributes['expiration_date'], 'date', false) : null,
get: fn(mixed $value, array $attributes) => array_key_exists('expiration_date', $attributes) ? Helper::getFormattedDateObject($attributes['expiration_date'], 'date', false) : null,
);
}
+135
View File
@@ -863,6 +863,141 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return new \stdClass;
}
/**
* Query builder scope to search on text filters for complex Bootstrap Tables API
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $filter JSON array of search keys and terms
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeByFilter($query, $filter)
{
return $query->where(
function ($query) use ($filter) {
foreach ($filter as $fieldname => $search_val) {
if ($fieldname == 'first_name') {
$query->where('users.first_name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'last_name') {
$query->where('users.last_name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'display_name') {
$query->where('users.display_name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'name') {
$query->where('users.last_name', 'LIKE', '%' . $search_val . '%')
->orWhere('users.first_name', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'username') {
$query->where('users.username', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'email') {
$query->where('users.email', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'phone') {
$query->where('users.phone', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'mobile') {
$query->where('users.mobile', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'phone') {
$query->where('users.phone', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'jobtitle') {
$query->where('users.jobtitle', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'created_at') {
$query->where('users.created_at', '=', '%' . $search_val . '%');
}
if ($fieldname == 'updated_at') {
$query->where('users.updated_at', '=', '%' . $search_val . '%');
}
if ($fieldname == 'start_date') {
$query->where('users.start_date', '=', '%' . $search_val . '%');
}
if ($fieldname == 'end_date') {
$query->where('users.end_date', '=', '%' . $search_val . '%');
}
if ($fieldname == 'employee_num') {
$query->where('users.employee_num', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'locale') {
$query->where('users.locale', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'address') {
$query->where('users.address', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'state') {
$query->where('users.state', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'zip') {
$query->where('users.zip', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'country') {
$query->where('users.country', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'vip') {
$query->where('users.vip', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'remote') {
$query->where('users.remote', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'start_date') {
$query->where('users.purchase_date', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'notes') {
$query->where('users.notes', 'LIKE', '%' . $search_val . '%');
}
if ($fieldname == 'location') {
$query->whereHas(
'location', function ($query) use ($search_val) {
$query->where('locations.name', 'LIKE', '%' . $search_val . '%');
}
);
}
if ($fieldname == 'company') {
$query->whereHas(
'company', function ($query) use ($search_val) {
$query->where('companies.name', 'LIKE', '%' . $search_val . '%');
}
);
}
}
}
);
}
/**
* Query builder scope to search user by name with spaces in it.
* We don't use the advancedTextSearch() scope because that searches
+3 -3
View File
@@ -53,7 +53,7 @@ class AssetModelPresenter extends Presenter
],
[
'field' => 'manufacturer',
'searchable' => false,
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.manufacturer'),
@@ -62,7 +62,7 @@ class AssetModelPresenter extends Presenter
],
[
'field' => 'model_number',
'searchable' => false,
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/models/table.modelnumber'),
@@ -130,7 +130,7 @@ class AssetModelPresenter extends Presenter
],
[
'field' => 'category',
'searchable' => false,
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.category'),
+7 -2
View File
@@ -14,6 +14,11 @@ class CategoryPresenter extends Presenter
public static function dataTableLayout()
{
$layout = [
[
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
],
[
'field' => 'id',
'searchable' => false,
@@ -92,7 +97,7 @@ class CategoryPresenter extends Presenter
'formatter' => 'usersLinkObjFormatter',
], [
'field' => 'created_at',
'searchable' => true,
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('general.created_at'),
@@ -100,7 +105,7 @@ class CategoryPresenter extends Presenter
'formatter' => 'dateDisplayFormatter',
], [
'field' => 'updated_at',
'searchable' => true,
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('general.updated_at'),
+1 -1
View File
@@ -131,7 +131,7 @@ class ComponentPresenter extends Presenter
'class' => 'text-right',
], [
'field' => 'total_cost',
'searchable' => true,
'searchable' => false,
'sortable' => true,
'title' => trans('general.total_cost'),
'footerFormatter' => 'sumFormatterQuantity',
+6
View File
@@ -111,6 +111,12 @@ class MaintenancesPresenter extends Presenter
'sortable' => true,
'title' => trans('admin/maintenances/form.completion_date'),
'formatter' => 'dateDisplayFormatter',
], [
'field' => 'url',
'searchable' => true,
'sortable' => true,
'title' => trans('general.url'),
'formatter' => 'externalLinkFormatter',
], [
'field' => 'notes',
'searchable' => true,
+5 -1
View File
@@ -14,7 +14,11 @@ class ManufacturerPresenter extends Presenter
public static function dataTableLayout()
{
$layout = [
[
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
],
[
'field' => 'id',
'searchable' => false,
+5
View File
@@ -13,6 +13,11 @@ class SupplierPresenter extends Presenter
public static function dataTableLayout()
{
$layout = [
[
'field' => 'checkbox',
'checkbox' => true,
'titleTooltip' => trans('general.select_all_none'),
],
[
'field' => 'id',
'searchable' => false,
+6
View File
@@ -232,6 +232,12 @@ return [
'note' => '',
'display' => true,
],
[
'permission' => 'licenses.checkin',
'label' => 'Checkin ',
'note' => '',
'display' => true,
],
[
'permission' => 'licenses.keys',
'label' => 'View License Keys',
+5 -5
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v8.3.3',
'full_app_version' => 'v8.3.3 - build 20061-g884d2a955',
'build_version' => '20061',
'app_version' => 'v8.3.4',
'full_app_version' => 'v8.3.4 - build 20218-g3ab2e2011',
'build_version' => '20218',
'prerelease_version' => '',
'hash_version' => 'g884d2a955',
'full_hash' => 'v8.3.3-154-g884d2a955',
'hash_version' => 'g3ab2e2011',
'full_hash' => 'v8.3.4-149-g3ab2e2011',
'branch' => 'master',
);
@@ -31,6 +31,7 @@ class MaintenanceFactory extends Factory
'start_date' => $this->faker->date(),
'is_warranty' => $this->faker->boolean(),
'notes' => $this->faker->paragraph(),
'url' => $this->faker->url(),
];
}
}
@@ -22,7 +22,7 @@ return new class extends Migration
public function down(): void
{
Schema::table('action_logs', function (Blueprint $table) {
$table->dropIndex('deleted_at');
$table->dropIndex(['deleted_at']);
});
}
};
@@ -0,0 +1,32 @@
<?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('maintenances', function (Blueprint $table) {
if (!Schema::hasColumn('maintenances', 'url')) {
$table->text('url')->after('name')->nullable()->default(null);
}
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('maintenances', function (Blueprint $table) {
if (Schema::hasColumn('maintenances', 'url')) {
$table->dropColumn('url');
}
});
}
};
@@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\Storage;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
$assetmodelfiles = Storage::allFiles('private_uploads/assetmodels');
foreach ($assetmodelfiles as $file) {
Storage::writeStream('private_uploads/models/' . basename($file),
Storage::readStream($file)
);
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};
+66 -38
View File
@@ -26,6 +26,7 @@
"jquery-ui": "^1.14.1",
"jquery-validation": "^1.21.0",
"jquery.iframe-transport": "^1.0.0",
"jspdf": "^3.0.3",
"jspdf-autotable": "^5.0.2",
"less": "^4.2.2",
"less-loader": "^6.0",
@@ -2193,6 +2194,12 @@
"@types/node": "*"
}
},
"node_modules/@types/pako": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/pako/-/pako-2.0.4.tgz",
"integrity": "sha512-VWDCbrLeVXJM9fihYodcLiIv0ku+AlOa/TQ1SvYOaBuyrSKgEcro95LJyIsJ4vSo6BXIxOKxiJAat04CmST9Fw==",
"license": "MIT"
},
"node_modules/@types/parse-json": {
"version": "4.0.2",
"dev": true,
@@ -2258,6 +2265,13 @@
"dev": true,
"license": "MIT"
},
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"license": "MIT",
"optional": true
},
"node_modules/@types/ws": {
"version": "8.5.10",
"dev": true,
@@ -2742,16 +2756,6 @@
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
"dev": true
},
"node_modules/atob": {
"version": "2.1.2",
"license": "(MIT OR Apache-2.0)",
"bin": {
"atob": "bin/atob.js"
},
"engines": {
"node": ">= 4.5.0"
}
},
"node_modules/autoprefixer": {
"version": "10.4.19",
"dev": true,
@@ -3343,16 +3347,6 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/btoa": {
"version": "1.2.1",
"license": "(MIT OR Apache-2.0)",
"bin": {
"btoa": "bin/btoa.js"
},
"engines": {
"node": ">= 0.4.0"
}
},
"node_modules/buffer": {
"version": "4.9.2",
"dev": true,
@@ -3649,11 +3643,17 @@
}
},
"node_modules/cipher-base": {
"version": "1.0.4",
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.7.tgz",
"integrity": "sha512-Mz9QMT5fJe7bKI7MH31UilT5cEK5EHHRCccw/YRFsRY47AuNgaV6HY3rscp0/I4Q+tTW/5zoqpSeRRI54TkDWA==",
"license": "MIT",
"dependencies": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
"inherits": "^2.0.4",
"safe-buffer": "^5.2.1",
"to-buffer": "^1.2.2"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/ckeditor": {
@@ -4617,10 +4617,14 @@
}
},
"node_modules/dompurify": {
"version": "2.5.8",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-2.5.8.tgz",
"integrity": "sha512-o1vSNgrmYMQObbSSvF/1brBYEQPHhV1+gsmrusO7/GXtp1T9rCS8cXFqVxK/9crT1jA6Ccv+5MTSjBNqr7Sovw==",
"optional": true
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz",
"integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==",
"license": "(MPL-2.0 OR Apache-2.0)",
"optional": true,
"optionalDependencies": {
"@types/trusted-types": "^2.0.7"
}
},
"node_modules/domutils": {
"version": "2.8.0",
@@ -5106,6 +5110,23 @@
"version": "2.1.0",
"license": "MIT"
},
"node_modules/fast-png": {
"version": "6.4.0",
"resolved": "https://registry.npmjs.org/fast-png/-/fast-png-6.4.0.tgz",
"integrity": "sha512-kAqZq1TlgBjZcLr5mcN6NP5Rv4V2f22z00c3g8vRrwkcqjerx7BEhPbOnWCPqaHUl2XWQBJQvOT/FQhdMT7X/Q==",
"license": "MIT",
"dependencies": {
"@types/pako": "^2.0.3",
"iobuffer": "^5.3.2",
"pako": "^2.1.0"
}
},
"node_modules/fast-png/node_modules/pako": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/pako/-/pako-2.1.0.tgz",
"integrity": "sha512-w+eufiZ1WuJYgPXbV/PO3NCMEc3xqylkKHzp8bxp1uW4qaSNQUkwmLLEc3kKsfz8lpV1F8Ht3U1Cm+9Srog2ug==",
"license": "(MIT AND Zlib)"
},
"node_modules/fast-safe-stringify": {
"version": "2.1.1",
"license": "MIT"
@@ -6233,6 +6254,12 @@
"node": ">= 0.10"
}
},
"node_modules/iobuffer": {
"version": "5.4.0",
"resolved": "https://registry.npmjs.org/iobuffer/-/iobuffer-5.4.0.tgz",
"integrity": "sha512-DRebOWuqDvxunfkNJAlc3IzWIPD5xVxwUNbHr7xKB8E6aLJxIPfNX3CoMJghcFjpv6RWQsrcJbghtEwSPoJqMA==",
"license": "MIT"
},
"node_modules/ion-rangeslider": {
"version": "2.3.1",
"license": "MIT",
@@ -6769,19 +6796,19 @@
}
},
"node_modules/jspdf": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-2.5.2.tgz",
"integrity": "sha512-myeX9c+p7znDWPk0eTrujCzNjT+CXdXyk7YmJq5nD5V7uLLKmSXnlQ/Jn/kuo3X09Op70Apm0rQSnFWyGK8uEQ==",
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/jspdf/-/jspdf-3.0.3.tgz",
"integrity": "sha512-eURjAyz5iX1H8BOYAfzvdPfIKK53V7mCpBTe7Kb16PaM8JSXEcUQNBQaiWMI8wY5RvNOPj4GccMjTlfwRBd+oQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.23.2",
"atob": "^2.1.2",
"btoa": "^1.2.1",
"@babel/runtime": "^7.26.9",
"fast-png": "^6.2.0",
"fflate": "^0.8.1"
},
"optionalDependencies": {
"canvg": "^3.0.6",
"canvg": "^3.0.11",
"core-js": "^3.6.0",
"dompurify": "^2.5.4",
"dompurify": "^3.2.4",
"html2canvas": "^1.0.0-rc.5"
}
},
@@ -10272,9 +10299,10 @@
"license": "MIT"
},
"node_modules/to-buffer": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
"integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
"license": "MIT",
"dependencies": {
"isarray": "^2.0.5",
"safe-buffer": "^5.2.1",
+1
View File
@@ -46,6 +46,7 @@
"jquery-ui": "^1.14.1",
"jquery-validation": "^1.21.0",
"jquery.iframe-transport": "^1.0.0",
"jspdf": "^3.0.3",
"jspdf-autotable": "^5.0.2",
"less": "^4.2.2",
"less-loader": "^6.0",
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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,3 +1,3 @@
.skin-contrast .main-header .navbar{background-color:#001f3f}.skin-contrast .main-header .navbar .nav>li>a{color:#fff}.skin-contrast .main-header .navbar .nav .open>a,.skin-contrast .main-header .navbar .nav .open>a:focus,.skin-contrast .main-header .navbar .nav .open>a:hover,.skin-contrast .main-header .navbar .nav>.active>a,.skin-contrast .main-header .navbar .nav>li>a:active,.skin-contrast .main-header .navbar .nav>li>a:focus,.skin-contrast .main-header .navbar .nav>li>a:hover,.skin-contrast .main-header .navbar .sidebar-toggle:hover{background:rgba(0,0,0,.1);color:#f6f6f6}.skin-contrast .main-header .navbar .sidebar-toggle{color:#fff}.skin-contrast .main-header .navbar .sidebar-toggle:hover{background-color:#001226}@media (max-width:767px){.skin-contrast .main-header .navbar .dropdown-menu li.divider{background-color:hsla(0,0%,100%,.1)}.skin-contrast .main-header .navbar .dropdown-menu li a{color:#fff}.skin-contrast .main-header .navbar .dropdown-menu li a:hover{background:#001226}}.skin-contrast .main-header li.user-header{background-color:#001f3f}.skin-contrast .content-header{background:transparent}.skin-contrast .left-side,.skin-contrast .main-sidebar,.skin-contrast .wrapper{background-color:#222d32}.skin-contrast .user-panel>.info,.skin-contrast .user-panel>.info>a{color:#fff}.skin-contrast .sidebar-menu>li.header{background:#1a2226;color:#4b646f}.skin-contrast .sidebar-menu>li>a{border-left:3px solid transparent}.skin-contrast .sidebar-menu>li.active>a,.skin-contrast .sidebar-menu>li:hover>a{background:#1e282c;border-left-color:#001f3f;color:#fff}.skin-contrast .sidebar-menu>li>.treeview-menu{background:#2c3b41;margin:0 1px}.skin-contrast .sidebar a{color:#b8c7ce}.skin-contrast .sidebar a:hover{text-decoration:none}.skin-contrast .treeview-menu>li>a{color:#8aa4af}.skin-contrast .treeview-menu>li.active>a,.skin-contrast .treeview-menu>li>a:hover{color:#fff}.skin-contrast .sidebar-form{border:1px solid #374850;border-radius:3px;margin:10px}.skin-contrast .sidebar-form .btn,.skin-contrast .sidebar-form input[type=text]{background-color:#374850;border:1px solid transparent;box-shadow:none;height:35px;transition:all .3s ease-in-out}.skin-contrast .sidebar-form input[type=text]{border-bottom-left-radius:2px;border-bottom-right-radius:0;border-top-left-radius:2px;border-top-right-radius:0;color:#666}.skin-contrast .sidebar-form input[type=text]:focus,.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-contrast .sidebar-form .btn{border-bottom-left-radius:0;border-bottom-right-radius:2px;border-top-left-radius:0;border-top-right-radius:2px;color:#999}.skin-contrast.layout-top-nav .main-header>.logo .logo-variant{background-color:none}.btn .btn-primary:link,.btn.btn-primary,.btn:hover .btn-primary:link,.btn:hover.btn-primary{background-color:#00060c;border-color:#000;color:#fff}.btn:hovera.btn-primary:hover,.btna.btn-primary:hover{background-color:#000;border-color:#000;color:#fff}.btn.btn-white:link,.btn:hover.btn-white:link{background-color:#00060c;color:#fff}.btn.btn-white:hover,.btn:hover.btn-white:hover{background-color:#000;color:#fff}a.btn.btn-link.text-left{border:1px solid #000;color:#001f3f}a,a.btn.btn-link.text-left:hover,a:hover{color:#001f3f}a:hover{text-decoration:underline}a:visited{color:#001f3f}a.btn:hover{color:#fff;text-decoration:underline}.text-primary{color:#000}.skin-contrast .treeview-menu>li>a{color:#fff}.bg-teal{background-color:#1b6a6a!important}.bg-orange{background-color:#995400!important}.bg-purple{background-color:#3a3767!important}.bg-maroon{background-color:#7d1038!important}.pagination>li>a{color:#00060c!important}.pagination>.active>a{background-color:#001f3f;color:#fff!important}btn-success{background-color:#000d07}input::-webkit-input-placeholder{color:#b5bbc8!important}input::-moz-placeholder{color:#b5bbc8!important}input::-ms-input-placeholder{color:#b5bbc8!important}.select2-default,.select2-selection__placeholder{color:#37383c!important}.callout.callout-info{background-color:#23536f!important}.fixed-table-container tbody .selected td{background-color:#fff8af}.search-highlight,.search-highlight:hover{background-color:#e9d15b}
.skin-contrast .main-header .navbar{background-color:#001f3f}.skin-contrast .main-header .navbar .nav>li>a{color:#fff}.skin-contrast .main-header .navbar .nav .open>a,.skin-contrast .main-header .navbar .nav .open>a:focus,.skin-contrast .main-header .navbar .nav .open>a:hover,.skin-contrast .main-header .navbar .nav>.active>a,.skin-contrast .main-header .navbar .nav>li>a:active,.skin-contrast .main-header .navbar .nav>li>a:focus,.skin-contrast .main-header .navbar .nav>li>a:hover,.skin-contrast .main-header .navbar .sidebar-toggle:hover{background:rgba(0,0,0,.1);color:#f6f6f6}.skin-contrast .main-header .navbar .sidebar-toggle{color:#fff}.skin-contrast .main-header .navbar .sidebar-toggle:hover{background-color:#001226}@media (max-width:767px){.skin-contrast .main-header .navbar .dropdown-menu li.divider{background-color:hsla(0,0%,100%,.1)}.skin-contrast .main-header .navbar .dropdown-menu li a{color:#fff}.skin-contrast .main-header .navbar .dropdown-menu li a:hover{background:#001226}}.skin-contrast .main-header li.user-header{background-color:#001f3f}.skin-contrast .content-header{background:transparent}.skin-contrast .left-side,.skin-contrast .main-sidebar,.skin-contrast .wrapper{background-color:#222d32}.skin-contrast .user-panel>.info,.skin-contrast .user-panel>.info>a{color:#fff}.skin-contrast .sidebar-menu>li.header{background:#1a2226;color:#4b646f}.skin-contrast .sidebar-menu>li>a{border-left:3px solid transparent}.skin-contrast .sidebar-menu>li.active>a,.skin-contrast .sidebar-menu>li:hover>a{background:#1e282c;border-left-color:#001f3f;color:#fff}.skin-contrast .sidebar-menu>li>.treeview-menu{background:#2c3b41;margin:0 1px}.skin-contrast .sidebar a{color:#b8c7ce}.skin-contrast .sidebar a:hover{text-decoration:none}.skin-contrast .treeview-menu>li>a{color:#8aa4af}.skin-contrast .treeview-menu>li.active>a,.skin-contrast .treeview-menu>li>a:hover{color:#fff}.skin-contrast .sidebar-form{border:1px solid #374850;border-radius:3px;margin:10px}.skin-contrast .sidebar-form .btn,.skin-contrast .sidebar-form input[type=text]{background-color:#374850;border:1px solid transparent;box-shadow:none;height:35px;transition:all .3s ease-in-out}.skin-contrast .sidebar-form input[type=text]{border-bottom-left-radius:2px;border-bottom-right-radius:0;border-top-left-radius:2px;border-top-right-radius:0;color:#666}.skin-contrast .sidebar-form input[type=text]:focus,.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-contrast .sidebar-form .btn{border-bottom-left-radius:0;border-bottom-right-radius:2px;border-top-left-radius:0;border-top-right-radius:2px;color:#999}.skin-contrast.layout-top-nav .main-header>.logo .logo-variant{background-color:none}.btn .btn-default:link:hover,.btn .btn-default:link:visited,.btn.btn-default:hover,.btn.btn-default:visited,.btn:hover .btn-default:link:hover,.btn:hover .btn-default:link:visited,.btn:hover.btn-default:hover,.btn:hover.btn-default:visited{color:#00060c}.btn .btn-primary:link,.btn.btn-primary,.btn:hover .btn-primary:link,.btn:hover.btn-primary{background-color:#00060c;border-color:#000;color:#fff}.btn:hovera.btn-primary:hover,.btna.btn-primary:hover{background-color:#000;border-color:#000;color:#fff}.btn.btn-white:link,.btn:hover.btn-white:link{background-color:#00060c;color:#fff}.btn.btn-white:hover,.btn:hover.btn-white:hover{background-color:#000;color:#fff}a.btn.btn-link.text-left{border:1px solid #000;color:#001f3f}a,a.btn.btn-link.text-left:hover,a:hover{color:#001f3f}a:hover{text-decoration:underline}a:visited{color:#001f3f}a.btn:hover{color:#fff;text-decoration:underline}a.btn:visited{color:#fff;text-decoration:none}.text-primary{color:#000}.skin-contrast .treeview-menu>li>a{color:#fff}.bg-teal{background-color:#1b6a6a!important}.bg-orange{background-color:#995400!important}.bg-purple{background-color:#3a3767!important}.bg-maroon{background-color:#7d1038!important}.pagination>li>a{color:#00060c!important}.pagination>.active>a{background-color:#001f3f;color:#fff!important}.btn-success{background-color:#000d07}input::-webkit-input-placeholder{color:#b5bbc8!important}input::-moz-placeholder{color:#b5bbc8!important}input::-ms-input-placeholder{color:#b5bbc8!important}.select2-default,.select2-selection__placeholder{color:#37383c!important}.callout.callout-info{background-color:#23536f!important}.fixed-table-container tbody .selected td{background-color:#fff8af}.search-highlight,.search-highlight:hover{background-color:#e9d15b}
/*# sourceMappingURL=skin-contrast.css.map*/
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -1 +1 @@
.skin-contrast .main-header .navbar{background-color:#001f3f}.skin-contrast .main-header .navbar .nav>li>a{color:#fff}.skin-contrast .main-header .navbar .nav .open>a,.skin-contrast .main-header .navbar .nav .open>a:focus,.skin-contrast .main-header .navbar .nav .open>a:hover,.skin-contrast .main-header .navbar .nav>.active>a,.skin-contrast .main-header .navbar .nav>li>a:active,.skin-contrast .main-header .navbar .nav>li>a:focus,.skin-contrast .main-header .navbar .nav>li>a:hover,.skin-contrast .main-header .navbar .sidebar-toggle:hover{background:rgba(0,0,0,.1);color:#f6f6f6}.skin-contrast .main-header .navbar .sidebar-toggle{color:#fff}.skin-contrast .main-header .navbar .sidebar-toggle:hover{background-color:#001226}@media (max-width:767px){.skin-contrast .main-header .navbar .dropdown-menu li.divider{background-color:hsla(0,0%,100%,.1)}.skin-contrast .main-header .navbar .dropdown-menu li a{color:#fff}.skin-contrast .main-header .navbar .dropdown-menu li a:hover{background:#001226}}.skin-contrast .main-header li.user-header{background-color:#001f3f}.skin-contrast .content-header{background:0 0}.skin-contrast .left-side,.skin-contrast .main-sidebar,.skin-contrast .wrapper{background-color:#222d32}.skin-contrast .user-panel>.info,.skin-contrast .user-panel>.info>a{color:#fff}.skin-contrast .sidebar-menu>li.header{background:#1a2226;color:#4b646f}.skin-contrast .sidebar-menu>li>a{border-left:3px solid transparent}.skin-contrast .sidebar-menu>li.active>a,.skin-contrast .sidebar-menu>li:hover>a{background:#1e282c;border-left-color:#001f3f;color:#fff}.skin-contrast .sidebar-menu>li>.treeview-menu{background:#2c3b41;margin:0 1px}.skin-contrast .sidebar a{color:#b8c7ce}.skin-contrast .sidebar a:hover{text-decoration:none}.skin-contrast .treeview-menu>li>a{color:#8aa4af}.skin-contrast .treeview-menu>li.active>a,.skin-contrast .treeview-menu>li>a:hover{color:#fff}.skin-contrast .sidebar-form{border:1px solid #374850;border-radius:3px;margin:10px}.skin-contrast .sidebar-form .btn,.skin-contrast .sidebar-form input[type=text]{background-color:#374850;border:1px solid transparent;box-shadow:none;height:35px;transition:all .3s ease-in-out}.skin-contrast .sidebar-form input[type=text]{border-bottom-left-radius:2px;border-bottom-right-radius:0;border-top-left-radius:2px;border-top-right-radius:0;color:#666}.skin-contrast .sidebar-form input[type=text]:focus,.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-contrast .sidebar-form .btn{border-bottom-left-radius:0;border-bottom-right-radius:2px;border-top-left-radius:0;border-top-right-radius:2px;color:#999}.skin-contrast.layout-top-nav .main-header>.logo .logo-variant{background-color:none}.btn .btn-primary:link,.btn.btn-primary,.btn:hover .btn-primary:link,.btn:hover.btn-primary{background-color:#00060c;border-color:#000;color:#fff}.btn:hovera.btn-primary:hover,.btna.btn-primary:hover{background-color:#000;border-color:#000;color:#fff}.btn.btn-white:link,.btn:hover.btn-white:link{background-color:#00060c;color:#fff}.btn.btn-white:hover,.btn:hover.btn-white:hover{background-color:#000;color:#fff}a.btn.btn-link.text-left{border:1px solid #000;color:#001f3f}a,a.btn.btn-link.text-left:hover,a:hover{color:#001f3f}a:hover{text-decoration:underline}a:visited{color:#001f3f}a.btn:hover{color:#fff;text-decoration:underline}.text-primary{color:#000}.skin-contrast .treeview-menu>li>a{color:#fff}.bg-teal{background-color:#1b6a6a!important}.bg-orange{background-color:#995400!important}.bg-purple{background-color:#3a3767!important}.bg-maroon{background-color:#7d1038!important}.pagination>li>a{color:#00060c!important}.pagination>.active>a{background-color:#001f3f;color:#fff!important}btn-success{background-color:#000d07}input::-webkit-input-placeholder{color:#b5bbc8!important}input::-moz-placeholder{color:#b5bbc8!important}input::-ms-input-placeholder{color:#b5bbc8!important}.select2-default,.select2-selection__placeholder{color:#37383c!important}.callout.callout-info{background-color:#23536f!important}.fixed-table-container tbody .selected td{background-color:#fff8af}.search-highlight,.search-highlight:hover{background-color:#e9d15b}
.skin-contrast .main-header .navbar{background-color:#001f3f}.skin-contrast .main-header .navbar .nav>li>a{color:#fff}.skin-contrast .main-header .navbar .nav .open>a,.skin-contrast .main-header .navbar .nav .open>a:focus,.skin-contrast .main-header .navbar .nav .open>a:hover,.skin-contrast .main-header .navbar .nav>.active>a,.skin-contrast .main-header .navbar .nav>li>a:active,.skin-contrast .main-header .navbar .nav>li>a:focus,.skin-contrast .main-header .navbar .nav>li>a:hover,.skin-contrast .main-header .navbar .sidebar-toggle:hover{background:rgba(0,0,0,.1);color:#f6f6f6}.skin-contrast .main-header .navbar .sidebar-toggle{color:#fff}.skin-contrast .main-header .navbar .sidebar-toggle:hover{background-color:#001226}@media (max-width:767px){.skin-contrast .main-header .navbar .dropdown-menu li.divider{background-color:hsla(0,0%,100%,.1)}.skin-contrast .main-header .navbar .dropdown-menu li a{color:#fff}.skin-contrast .main-header .navbar .dropdown-menu li a:hover{background:#001226}}.skin-contrast .main-header li.user-header{background-color:#001f3f}.skin-contrast .content-header{background:0 0}.skin-contrast .left-side,.skin-contrast .main-sidebar,.skin-contrast .wrapper{background-color:#222d32}.skin-contrast .user-panel>.info,.skin-contrast .user-panel>.info>a{color:#fff}.skin-contrast .sidebar-menu>li.header{background:#1a2226;color:#4b646f}.skin-contrast .sidebar-menu>li>a{border-left:3px solid transparent}.skin-contrast .sidebar-menu>li.active>a,.skin-contrast .sidebar-menu>li:hover>a{background:#1e282c;border-left-color:#001f3f;color:#fff}.skin-contrast .sidebar-menu>li>.treeview-menu{background:#2c3b41;margin:0 1px}.skin-contrast .sidebar a{color:#b8c7ce}.skin-contrast .sidebar a:hover{text-decoration:none}.skin-contrast .treeview-menu>li>a{color:#8aa4af}.skin-contrast .treeview-menu>li.active>a,.skin-contrast .treeview-menu>li>a:hover{color:#fff}.skin-contrast .sidebar-form{border:1px solid #374850;border-radius:3px;margin:10px}.skin-contrast .sidebar-form .btn,.skin-contrast .sidebar-form input[type=text]{background-color:#374850;border:1px solid transparent;box-shadow:none;height:35px;transition:all .3s ease-in-out}.skin-contrast .sidebar-form input[type=text]{border-bottom-left-radius:2px;border-bottom-right-radius:0;border-top-left-radius:2px;border-top-right-radius:0;color:#666}.skin-contrast .sidebar-form input[type=text]:focus,.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{background-color:#fff;color:#666}.skin-contrast .sidebar-form input[type=text]:focus+.input-group-btn .btn{border-left-color:#fff}.skin-contrast .sidebar-form .btn{border-bottom-left-radius:0;border-bottom-right-radius:2px;border-top-left-radius:0;border-top-right-radius:2px;color:#999}.skin-contrast.layout-top-nav .main-header>.logo .logo-variant{background-color:none}.btn .btn-default:link:hover,.btn .btn-default:link:visited,.btn.btn-default:hover,.btn.btn-default:visited,.btn:hover .btn-default:link:hover,.btn:hover .btn-default:link:visited,.btn:hover.btn-default:hover,.btn:hover.btn-default:visited{color:#00060c}.btn .btn-primary:link,.btn.btn-primary,.btn:hover .btn-primary:link,.btn:hover.btn-primary{background-color:#00060c;border-color:#000;color:#fff}.btn:hovera.btn-primary:hover,.btna.btn-primary:hover{background-color:#000;border-color:#000;color:#fff}.btn.btn-white:link,.btn:hover.btn-white:link{background-color:#00060c;color:#fff}.btn.btn-white:hover,.btn:hover.btn-white:hover{background-color:#000;color:#fff}a.btn.btn-link.text-left{border:1px solid #000;color:#001f3f}a,a.btn.btn-link.text-left:hover,a:hover{color:#001f3f}a:hover{text-decoration:underline}a:visited{color:#001f3f}a.btn:hover{color:#fff;text-decoration:underline}a.btn:visited{color:#fff;text-decoration:none}.text-primary{color:#000}.skin-contrast .treeview-menu>li>a{color:#fff}.bg-teal{background-color:#1b6a6a!important}.bg-orange{background-color:#995400!important}.bg-purple{background-color:#3a3767!important}.bg-maroon{background-color:#7d1038!important}.pagination>li>a{color:#00060c!important}.pagination>.active>a{background-color:#001f3f;color:#fff!important}.btn-success{background-color:#000d07}input::-webkit-input-placeholder{color:#b5bbc8!important}input::-moz-placeholder{color:#b5bbc8!important}input::-ms-input-placeholder{color:#b5bbc8!important}.select2-default,.select2-selection__placeholder{color:#37383c!important}.callout.callout-info{background-color:#23536f!important}.fixed-table-container tbody .selected td{background-color:#fff8af}.search-highlight,.search-highlight:hover{background-color:#e9d15b}
+7 -7
View File
@@ -1,9 +1,9 @@
{
"/js/dist/all.js": "/js/dist/all.js?id=5c191843e0bb9292ec6b7f0a3c5765b3",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=bf1a348eae3e60c62b8879953f7df14c",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=146086d653897e2557af5e68f6f8c56f",
"/css/build/overrides.css": "/css/build/overrides.css?id=3f6ab7e6902cca7d96e637b82dc95e65",
"/css/build/app.css": "/css/build/app.css?id=5876cf8fb09a66f8f9e0b2472c9cc9f8",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=f712d11cfca345b58c1d8a35df03d38d",
"/css/build/overrides.css": "/css/build/overrides.css?id=fec94887d3bd4899176e7172e315c961",
"/css/build/app.css": "/css/build/app.css?id=1b2aad9b78c526c9ac324a147a4848e6",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=bdf169bc2141f453390614c138cdce95",
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=e1e6e1c64cf14fc350585aaeb0e42f6b",
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=08ae1b3e66008966ce5d600ea3ad04a2",
@@ -15,11 +15,11 @@
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=71905ff04c78d92dc6f0b8354b458ffd",
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=d68df5bc23ddddc710f7acf2201b2caf",
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=436c77b84b2797f9683a7cdc4f8f6b8d",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=8c61ef8889d392838fb977c7a1b1f6bb",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=fbd34e1e2d119358e781195c3fe26b69",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=68a92d85c8e351dfb38a835307f126ec",
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=cbb20ad6182b658f34117bf96a621b63",
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=84e2ee950ae04444988b37038e5a3951",
"/css/dist/all.css": "/css/dist/all.css?id=88a000a091cb26a138368945df92ab83",
"/css/dist/all.css": "/css/dist/all.css?id=ebce085e83406391a6003079f8a304b0",
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
"/js/select2/i18n/af.js": "/js/select2/i18n/af.js?id=4f6fcd73488ce79fae1b7a90aceaecde",
@@ -93,12 +93,12 @@
"/js/dist/bootstrap-table-locale-all.min.js": "/js/dist/bootstrap-table-locale-all.min.js?id=d300041b9e5038b45b68e036add83be4",
"/js/dist/bootstrap-table-en-US.min.js": "/js/dist/bootstrap-table-en-US.min.js?id=6d0de12d91548ba2cd80b868838ce5fa",
"/js/dist/Chart.min.js": "/js/dist/Chart.min.js?id=9b1ae20c4c7048d6e4a1b2e1aee7fb31",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=146086d653897e2557af5e68f6f8c56f",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=f712d11cfca345b58c1d8a35df03d38d",
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=bf1a348eae3e60c62b8879953f7df14c",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=84e2ee950ae04444988b37038e5a3951",
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=cbb20ad6182b658f34117bf96a621b63",
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=68a92d85c8e351dfb38a835307f126ec",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=8c61ef8889d392838fb977c7a1b1f6bb",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=fbd34e1e2d119358e781195c3fe26b69",
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=436c77b84b2797f9683a7cdc4f8f6b8d",
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=d68df5bc23ddddc710f7acf2201b2caf",
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=71905ff04c78d92dc6f0b8354b458ffd",
+37
View File
@@ -1264,4 +1264,41 @@ caption.tableCaption {
input[name="columnsSearch"] {
width: 120px;
}
.callout.callout-legend {
background-color: #f4f4f4;
border-left: 5px solid #959495;
padding: 15px 30px 15px 15px;
font-size: 100%;
border-radius: 0px;
}
.callout.callout-legend h4 {
font-size: 16px;
font-weight: bold;
margin-top: 5px;
margin-bottom: 0px;
}
.callout.callout-legend a {
color: #333333;
text-decoration: none;
cursor: pointer;
}
p.callout-subtext {
margin-top: 5px;
}
p.callout-subtext a:hover, p.callout-subtext a:visited, p.callout-subtext a:link {
color: #31708f;
text-decoration: none;
}
/**
This just hides the padding on the right side of the mark tag for a less weird visual experience
*/
mark {
padding-right: 0px;
}
+16 -2
View File
@@ -61,13 +61,21 @@
.btn, .btn:hover {
&.btn-default, .btn-default:link {
&:hover {
color: darken(@navy, 10%)
}
&:visited {
color: darken(@navy, 10%)
}
}
&.btn-primary, .btn-primary:link {
background-color: darken(@navy, 10%);
border-color: darken(@navy, 20%);
color: #fff;
}
&a.btn-primary:hover {
background-color: darken(@navy, 20%);
border-color: darken(@navy, 20%);
@@ -109,6 +117,11 @@ a.btn {
color: #fff;
text-decoration: underline;
}
&:visited {
color: #fff;
text-decoration: none;
}
}
.text-primary {
@@ -144,7 +157,7 @@ a.btn {
color: #FFF!important;
}
btn-success {
.btn-success {
background-color: darken(@green, 30%);
}
@@ -168,6 +181,7 @@ input::-ms-input-placeholder { /* IE 10+ */
background-color: darken(@blue, 20%)!important;
}
.fixed-table-container tbody .selected td {
background-color: #fff8af;
}
@@ -18,9 +18,11 @@ return array(
),
'delete' => array(
'confirm' => 'crwdns631:0crwdne631:0',
'error' => 'crwdns632:0crwdne632:0',
'success' => 'crwdns633:0crwdne633:0'
'confirm' => 'crwdns631:0crwdne631:0',
'error' => 'crwdns632:0crwdne632:0',
'success' => 'crwdns13884:0crwdne13884:0',
'bulk_success' => 'crwdns13886:0crwdne13886:0',
'partial_success' => 'crwdns13888:0crwdne13888:0',
)
);
@@ -5,7 +5,7 @@ return [
'manage' => 'crwdns6501:0crwdne6501:0',
'field' => 'crwdns1487:0crwdne1487:0',
'about_fieldsets_title' => 'crwdns1488:0crwdne1488:0',
'about_fieldsets_text' => 'crwdns13746:0crwdne13746:0',
'about_fieldsets_text' => 'crwdns13838:0crwdne13838:0',
'custom_format' => 'crwdns6505:0crwdne6505:0',
'encrypt_field' => 'crwdns1792:0crwdne1792:0',
'encrypt_field_help' => 'crwdns1683:0crwdne1683:0',
@@ -22,9 +22,11 @@ return array(
),
'delete' => array(
'confirm' => 'crwdns901:0crwdne901:0',
'confirm' => 'crwdns901:0crwdne901:0',
'error' => 'crwdns1126:0crwdne1126:0',
'success' => 'crwdns903:0crwdne903:0'
'success' => 'crwdns13890:0crwdne13890:0',
'bulk_success' => 'crwdns13892:0crwdne13892:0',
'partial_success' => 'crwdns13894:0crwdne13894:0',
)
);
@@ -37,7 +37,7 @@ return [
'backups_clean_helptext' => "crwdns12714:0crwdne12714:0",
'backups_upload' => 'crwdns6327:0crwdne6327:0',
'backups_path' => 'crwdns6329:0crwdne6329:0',
'backups_restore_warning' => 'crwdns13156:0crwdne13156:0',
'backups_restore_warning' => 'crwdns13840:0crwdne13840:0',
'backups_logged_out' => 'crwdns6774:0crwdne6774:0',
'backups_large' => 'crwdns6335:0crwdne6335:0',
'barcode_settings' => 'crwdns1295:0crwdne1295:0',
@@ -20,9 +20,9 @@ return array(
'confirm' => 'crwdns867:0crwdne867:0',
'error' => 'crwdns868:0crwdne868:0',
'success' => 'crwdns869:0crwdne869:0',
'assoc_assets' => 'crwdns1959:0crwdne1959:0',
'assoc_licenses' => 'crwdns1960:0crwdne1960:0',
'assoc_maintenances' => 'crwdns13582:0crwdne13582:0',
'not_found' => 'crwdns13842:0crwdne13842:0',
'bulk_success' => 'crwdns13844:0crwdne13844:0',
'partial_success' => 'crwdns13882:0crwdne13882:0',
)
);
+19
View File
@@ -1,6 +1,7 @@
<?php
return [
'show_all' => 'crwdns13848:0crwdne13848:0',
'2FA_reset' => 'crwdns12148:0crwdne12148:0',
'accessories' => 'crwdns1200:0crwdne1200:0',
'activated' => 'crwdns1540:0crwdne1540:0',
@@ -628,6 +629,24 @@ return [
'notes' => 'crwdns12878:0crwdne12878:0',
],
'bulk_delete_associations' => [
'general_assoc_warning' => 'crwdns13850:0crwdne13850:0',
'assoc_assets' => 'crwdns13852:0crwdne13852:0',
'asset_models' => 'crwdns13854:0crwdne13854:0',
'assoc_maintenances' => 'crwdns13856:0crwdne13856:0',
'assoc_accessories' => 'crwdns13858:0crwdne13858:0',
'assoc_consumables' => 'crwdns13860:0crwdne13860:0',
'assoc_components' => 'crwdns13862:0crwdne13862:0',
'assoc_licenses' => 'crwdns13864:0crwdne13864:0',
'assoc_assets_no_count' => 'crwdns13866:0crwdne13866:0',
'asset_models_no_count' => 'crwdns13868:0crwdne13868:0',
'assoc_maintenances_no_count' => 'crwdns13870:0crwdne13870:0',
'assoc_accessories_no_count' => 'crwdns13872:0crwdne13872:0',
'assoc_consumables_no_count' => 'crwdns13874:0crwdne13874:0',
'assoc_components_no_count' => 'crwdns13876:0crwdne13876:0',
'assoc_licenses_no_count' => 'crwdns13878:0crwdne13878:0',
],
'breadcrumb_button_actions' => [
'edit_item' => 'crwdns12914:0crwdne12914:0',
'checkout_item' => 'crwdns12916:0crwdne12916:0',
@@ -18,9 +18,11 @@ return array(
),
'delete' => array(
'confirm' => 'Is jy seker jy wil hierdie kategorie uitvee?',
'error' => 'Daar was \'n probleem met die verwydering van die kategorie. Probeer asseblief weer.',
'success' => 'Die kategorie is suksesvol verwyder.'
'confirm' => 'Is jy seker jy wil hierdie kategorie uitvee?',
'error' => 'Daar was \'n probleem met die verwydering van die kategorie. Probeer asseblief weer.',
'success' => 'Category was deleted successfully.',
'bulk_success' => 'Categories were deleted successfully.',
'partial_success' => 'Category deleted successfully. See additional information below. | :count categories were deleted successfully. See additional information below.',
)
);
@@ -5,7 +5,7 @@ return [
'manage' => 'Manage',
'field' => 'veld',
'about_fieldsets_title' => 'Oor Fieldsets',
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
'about_fieldsets_text' => 'Veldstelle stel jou in staat om groepe van persoonlike velde te skep wat gereeld hergebruik word vir spesifieke tipe bates.',
'custom_format' => 'Custom Regex format...',
'encrypt_field' => 'Enkripteer die waarde van hierdie veld in die databasis',
'encrypt_field_help' => 'WAARSKUWING: Om \'n veld te enkripteer, maak dit onondersoekbaar.',
@@ -22,9 +22,11 @@ return array(
),
'delete' => array(
'confirm' => 'Is jy seker jy wil hierdie vervaardiger uitvee?',
'confirm' => 'Is jy seker jy wil hierdie vervaardiger uitvee?',
'error' => 'Daar was \'n probleem met die verwydering van die vervaardiger. Probeer asseblief weer.',
'success' => 'Die vervaardiger is suksesvol verwyder.'
'success' => 'Manufacturer deleted successfully.',
'bulk_success' => 'Manufacturers deleted successfully.',
'partial_success' => 'Manufacturer deleted successfully. See additional information below. | :count manufacturers were deleted successfully. See additional information below.',
)
);
@@ -37,7 +37,7 @@ return [
'backups_clean_helptext' => "This can be useful if you're changing between database versions",
'backups_upload' => 'Upload Backup',
'backups_path' => 'Backups on the server are stored in <code>:path</code>',
'backups_restore_warning' => 'Use the restore button <small><span class="btn btn-xs btn-warning"><i class="text-white fas fa-retweet" aria-hidden="true"></i></span></small> to restore from a previous backup. (This does not currently work with S3 file storage or Docker.)<br><br>Your <strong>entire :app_name database and any uploaded files will be completely replaced</strong> by what\'s in the backup file ',
'backups_restore_warning' => 'Use the restore button <small><span class="btn btn-xs btn-warning"><i class="text-white fas fa-retweet" aria-hidden="true"></i></span></small> to restore from a previous backup. (This does not currently work with S3 file storage.)<br><br>Your <strong>entire :app_name database and any uploaded files will be completely replaced</strong> by what\'s in the backup file ',
'backups_logged_out' => 'All existing users, including you, will be logged out once your restore is complete.',
'backups_large' => 'Very large backups may time out on the restore attempt and may still need to be run via command line. ',
'barcode_settings' => 'Barcode-instellings',
@@ -20,9 +20,9 @@ return array(
'confirm' => 'Is jy seker jy wil hierdie verskaffer uitvee?',
'error' => 'Daar was \'n probleem met die verwydering van die verskaffer. Probeer asseblief weer.',
'success' => 'Verskaffer is suksesvol verwyder.',
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
'not_found' => 'Supplier not found.',
'bulk_success' => 'Suppliers were deleted successfully.',
'partial_success' => 'Supplier deleted successfully. See additional information below. | :count suppliers were deleted successfully. See additional information below.',
)
);
+19
View File
@@ -1,6 +1,7 @@
<?php
return [
'show_all' => 'Show All',
'2FA_reset' => '2FA reset',
'accessories' => 'bykomstighede',
'activated' => 'geaktiveer',
@@ -629,6 +630,24 @@ return [
'notes' => 'Add a note',
],
'bulk_delete_associations' => [
'general_assoc_warning' => ':item_name still has associated items. Please remove them before deleting this :item.',
'assoc_assets' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
'asset_models' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your asset models to no longer reference this :item and try again.',
'assoc_maintenances' => ':item_name is currently associated with :maintenance_count maintenance(s) and cannot be deleted. Please update your maintenances to no longer reference this :item and try again.',
'assoc_accessories' => ':item_name is currently associated with :accessory_count accessory(ies) and cannot be deleted. Please update your accessories to no longer reference this :item and try again.',
'assoc_consumables' => ':item_name is currently associated with :consumable_count consumable(s) and cannot be deleted. Please update your consumables to no longer reference this :item and try again.',
'assoc_components' => ':item_name is currently associated with :component_count component(s) and cannot be deleted. Please update your components to no longer reference this :item and try again.',
'assoc_licenses' => ':item_name is currently associated with :license_count license(s) and cannot be deleted. Please update your licenses to no longer reference this :item and try again.',
'assoc_assets_no_count' => ':item_name is currently associated with other assets and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
'asset_models_no_count' => ':item_name is currently associated with other asset models and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
'assoc_maintenances_no_count' => ':item_name is currently associated with other maintenances and cannot be deleted. Please update your maintenances to no longer reference this :item and try again.',
'assoc_accessories_no_count' => ':item_name is currently associated with other accessories and cannot be deleted. Please update your accessories to no longer reference this :item and try again.',
'assoc_consumables_no_count' => ':item_name is currently associated with other consumables and cannot be deleted. Please update your consumables to no longer reference this :item and try again.',
'assoc_components_no_count' => ':item_name is currently associated with other components and cannot be deleted. Please update your components to no longer reference this :item and try again.',
'assoc_licenses_no_count' => ':item_name is currently associated with other licenses and cannot be deleted. Please update your licenses to no longer reference this :item and try again.',
],
'breadcrumb_button_actions' => [
'edit_item' => 'Edit :name',
'checkout_item' => 'Checkout :name',
@@ -18,9 +18,11 @@ return array(
),
'delete' => array(
'confirm' => 'Are you sure you wish to delete this category?',
'error' => 'There was an issue deleting the category. Please try again.',
'success' => 'The category was deleted successfully.'
'confirm' => 'Are you sure you wish to delete this category?',
'error' => 'There was an issue deleting the category. Please try again.',
'success' => 'Category was deleted successfully.',
'bulk_success' => 'Categories were deleted successfully.',
'partial_success' => 'Category deleted successfully. See additional information below. | :count categories were deleted successfully. See additional information below.',
)
);
@@ -5,7 +5,7 @@ return [
'manage' => 'Manage',
'field' => 'Field',
'about_fieldsets_title' => 'About Fieldsets',
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used for specific asset model types.',
'about_fieldsets_text' => 'Fieldsets allow you to create groups of custom fields that are frequently re-used used for specific asset model types.',
'custom_format' => 'Custom Regex format...',
'encrypt_field' => 'Encrypt the value of this field in the database',
'encrypt_field_help' => 'WARNING: Encrypting a field makes it unsearchable.',
@@ -22,9 +22,11 @@ return array(
),
'delete' => array(
'confirm' => 'Are you sure you wish to delete this manufacturer?',
'confirm' => 'Are you sure you wish to delete this manufacturer?',
'error' => 'There was an issue deleting the manufacturer. Please try again.',
'success' => 'The Manufacturer was deleted successfully.'
'success' => 'Manufacturer deleted successfully.',
'bulk_success' => 'Manufacturers deleted successfully.',
'partial_success' => 'Manufacturer deleted successfully. See additional information below. | :count manufacturers were deleted successfully. See additional information below.',
)
);
@@ -37,7 +37,7 @@ return [
'backups_clean_helptext' => "This can be useful if you're changing between database versions",
'backups_upload' => 'Upload Backup',
'backups_path' => 'Backups on the server are stored in <code>:path</code>',
'backups_restore_warning' => 'Use the restore button <small><span class="btn btn-xs btn-warning"><i class="text-white fas fa-retweet" aria-hidden="true"></i></span></small> to restore from a previous backup. (This does not currently work with S3 file storage or Docker.)<br><br>Your <strong>entire :app_name database and any uploaded files will be completely replaced</strong> by what\'s in the backup file ',
'backups_restore_warning' => 'Use the restore button <small><span class="btn btn-xs btn-warning"><i class="text-white fas fa-retweet" aria-hidden="true"></i></span></small> to restore from a previous backup. (This does not currently work with S3 file storage.)<br><br>Your <strong>entire :app_name database and any uploaded files will be completely replaced</strong> by what\'s in the backup file ',
'backups_logged_out' => 'All existing users, including you, will be logged out once your restore is complete.',
'backups_large' => 'Very large backups may time out on the restore attempt and may still need to be run via command line. ',
'barcode_settings' => 'Barcode Settings',
@@ -20,9 +20,9 @@ return array(
'confirm' => 'Are you sure you wish to delete this supplier?',
'error' => 'There was an issue deleting the supplier. Please try again.',
'success' => 'Supplier was deleted successfully.',
'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
'assoc_maintenances' => 'This supplier is currently associated with :maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
'not_found' => 'Supplier not found.',
'bulk_success' => 'Suppliers were deleted successfully.',
'partial_success' => 'Supplier deleted successfully. See additional information below. | :count suppliers were deleted successfully. See additional information below.',
)
);
+19
View File
@@ -1,6 +1,7 @@
<?php
return [
'show_all' => 'Show All',
'2FA_reset' => '2FA reset',
'accessories' => 'መለዋወጫዎች',
'activated' => 'Activated',
@@ -629,6 +630,24 @@ return [
'notes' => 'Add a note',
],
'bulk_delete_associations' => [
'general_assoc_warning' => ':item_name still has associated items. Please remove them before deleting this :item.',
'assoc_assets' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
'asset_models' => ':item_name is currently associated with :asset_count asset(s) and cannot be deleted. Please update your asset models to no longer reference this :item and try again.',
'assoc_maintenances' => ':item_name is currently associated with :maintenance_count maintenance(s) and cannot be deleted. Please update your maintenances to no longer reference this :item and try again.',
'assoc_accessories' => ':item_name is currently associated with :accessory_count accessory(ies) and cannot be deleted. Please update your accessories to no longer reference this :item and try again.',
'assoc_consumables' => ':item_name is currently associated with :consumable_count consumable(s) and cannot be deleted. Please update your consumables to no longer reference this :item and try again.',
'assoc_components' => ':item_name is currently associated with :component_count component(s) and cannot be deleted. Please update your components to no longer reference this :item and try again.',
'assoc_licenses' => ':item_name is currently associated with :license_count license(s) and cannot be deleted. Please update your licenses to no longer reference this :item and try again.',
'assoc_assets_no_count' => ':item_name is currently associated with other assets and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
'asset_models_no_count' => ':item_name is currently associated with other asset models and cannot be deleted. Please update your assets to no longer reference this :item and try again.',
'assoc_maintenances_no_count' => ':item_name is currently associated with other maintenances and cannot be deleted. Please update your maintenances to no longer reference this :item and try again.',
'assoc_accessories_no_count' => ':item_name is currently associated with other accessories and cannot be deleted. Please update your accessories to no longer reference this :item and try again.',
'assoc_consumables_no_count' => ':item_name is currently associated with other consumables and cannot be deleted. Please update your consumables to no longer reference this :item and try again.',
'assoc_components_no_count' => ':item_name is currently associated with other components and cannot be deleted. Please update your components to no longer reference this :item and try again.',
'assoc_licenses_no_count' => ':item_name is currently associated with other licenses and cannot be deleted. Please update your licenses to no longer reference this :item and try again.',
],
'breadcrumb_button_actions' => [
'edit_item' => 'Edit :name',
'checkout_item' => 'Checkout :name',
@@ -18,9 +18,11 @@ return array(
),
'delete' => array(
'confirm' => 'هل أنت متأكد أنك تريد حذف هذا التصنيف؟',
'error' => 'حدث خطأ أثناء محاولة حذف التصنيف. الرجاء المحاولة مرة أخرى.',
'success' => 'تم حذف التصنيف بنجاح.'
'confirm' => 'هل أنت متأكد أنك تريد حذف هذا التصنيف؟',
'error' => 'حدث خطأ أثناء محاولة حذف التصنيف. الرجاء المحاولة مرة أخرى.',
'success' => 'Category was deleted successfully.',
'bulk_success' => 'Categories were deleted successfully.',
'partial_success' => 'Category deleted successfully. See additional information below. | :count categories were deleted successfully. See additional information below.',
)
);

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