Compare commits

...

260 Commits

Author SHA1 Message Date
snipe d511d90a2f Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 06:50:42 -08:00
snipe 54d6cafda9 Bumped hash 2018-02-21 06:49:36 -08:00
snipe a730cd1c51 Fixed - better handle admin routes when user is not logged in
Redirect to login instead of just showing forbidden
2018-02-21 05:51:49 -08:00
snipe cccd75fc42 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 05:48:02 -08:00
snipe dbc16a6c9b Bumped hash 2018-02-21 05:47:12 -08:00
snipe 6ffad6043f Fixed issue where bootstrap tables didn’t use a default page size 2018-02-21 05:44:41 -08:00
snipe 4e398950a0 Merge branch 'develop' 2018-02-21 05:34:02 -08:00
snipe f5e51897e3 Added - sort by color on status labels 2018-02-21 05:29:50 -08:00
snipe 698ea36cc2 Added - Order location by manager 2018-02-21 05:09:40 -08:00
snipe 0cf9cdd3b1 Make department columns sortable 2018-02-21 05:04:20 -08:00
snipe 42c8de5620 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 04:44:48 -08:00
snipe ba4f63bca3 Bumped version 2018-02-21 04:43:52 -08:00
snipe 4ed2ef6298 Merge branch 'develop' 2018-02-21 04:42:03 -08:00
snipe d28c2af7de Fixed bootstrap table issue if per page was set to 10 2018-02-21 04:41:44 -08:00
snipe 1e8c32fbdb Fixed - missing table prefix for location parent search 2018-02-21 04:33:47 -08:00
snipe 97bd87773c Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 02:40:23 -08:00
snipe b560828173 Bumped hash 2018-02-21 02:18:14 -08:00
snipe 0d7a43ab38 Fixed orderby parent location name 2018-02-21 02:17:18 -08:00
snipe 7865fbea7e Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-21 01:27:11 -08:00
snipe 5fcbf9091e Bumped version 2018-02-21 01:23:19 -08:00
snipe fedd2b638c Merge branch 'develop' 2018-02-21 01:20:48 -08:00
snipe 22f44e342f Fixed incorrect next audit date if asset override 2018-02-21 01:18:21 -08:00
snipe f7eb013935 Reverse order on activity report 2018-02-20 15:42:44 -08:00
snipe 1c28f893e7 Fixed #5027 - remove link to non-existant reports page 2018-02-20 14:44:29 -08:00
snipe 195dfd752d Updated translations 2018-02-20 14:41:12 -08:00
snipe cc788d3b62 Added Slovenian 2018-02-20 14:37:22 -08:00
snipe e54021e7be Added Venzuelan spanish 2018-02-20 14:37:12 -08:00
snipe 918db39eba Merge branch 'develop' 2018-02-19 18:06:58 -08:00
snipe 213fe2ecea Fixed #5044 - incorrect env values for SSL DB paths 2018-02-19 18:03:50 -08:00
snipe 6e70352d0b Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-17 01:05:20 -08:00
snipe d2403cdadb Added image preview for uploads 2018-02-17 00:51:22 -08:00
snipe 9a4f5e0ba8 Bumped hash 2018-02-16 22:10:06 -08:00
snipe 502e4d672a Use image upload partial in asset edit/create 2018-02-16 22:08:49 -08:00
snipe 99205bf72e Merge branch 'develop' 2018-02-16 21:39:15 -08:00
snipe b3d673b0aa Fixed #5037 - use line breaks in notes in table view 2018-02-16 21:38:56 -08:00
snipe baf51eb430 Merge branch 'develop' 2018-02-16 21:19:03 -08:00
snipe d8fc50c351 Fixed #5033 - use PHP’s max filesize for image uploads 2018-02-16 21:17:41 -08:00
snipe ba5057181e Check for model in asset view 2018-02-16 18:04:11 -08:00
snipe 4c4dee0bf1 Use dropifexists for rollback 2018-02-16 17:45:40 -08:00
snipe 589c3a2be3 Fixed #4668 - wrong gate on manufacturer save 2018-02-16 17:45:27 -08:00
snipe 991f182f89 Added drop table to migration 2018-02-16 15:36:33 -08:00
snipe f44b03f5a9 Updated sticky table header extenion 2018-02-16 15:36:21 -08:00
snipe 5fd50040d3 Fixed weird migration 2018-02-16 15:31:47 -08:00
snipe 5302108556 Update to master 2018-02-16 13:27:03 -08:00
snipe 592c62de75 Merge branch 'develop'
# Conflicts:
#	README.md
#	config/version.php
2018-02-16 13:26:53 -08:00
snipe 27c1bc0271 Bumped hash 2018-02-16 13:24:47 -08:00
snipe 3744a68daf Features/better table options (#5018)
* Added CSS for table toolbar

* Use maintenances API for table listings

* NIcer layout for allowed_columns in maintenances API

* Fixed #5014 - bootstrap cookie issues

* Fixed #5015 - bug when saving settings

* Refactored datatable code to use data attributes

* Updated dashboard with new table code

* Added - Order by group user count

* Updated groups to use new table attributes

* New license listing table code

* More bootstrap table implementations

* More BS table refactoring

* Improved bootstrap assigned assets

* New bootstrap for reports

* Misc BS fixes

* FIxed small issue with asset history display

* Removed multisort option

* JS refactor
2018-02-16 13:22:55 -08:00
dl1l c209b7bb5d Update edit.blade.php (#5019) 2018-02-15 14:59:54 -08:00
snipe f04493c1ab Added firstname_lastname as possible username format 2018-02-13 20:31:51 -08:00
snipe 62edf14893 Refactored method to generate usernames from full names 2018-02-13 20:31:11 -08:00
snipe 0d11e32523 Fixed issue where group with no permissions would crash view page 2018-02-13 17:14:30 -08:00
snipe 5484b06df8 Fixed #4923 - invalid check for location object in Ldap Sync 2018-02-13 17:06:42 -08:00
snipe 9f3116e4e3 Added - Deep linking in Bootstrap tabs 2018-02-13 17:04:50 -08:00
snipe f144d671ff Fixed #4988 - incorrect variable name in asset checkout API method 2018-02-12 19:13:33 -08:00
snipe b294635e17 Updated packages 2018-02-08 09:29:12 -08:00
snipe 36234cc0e8 Add @seanmcilvenna as a contributor 2018-02-08 09:29:12 -08:00
snipe 5c87003196 Added code triage badge 2018-02-08 09:29:12 -08:00
Sean McIlvenna cc5d36f8be Addng "Category" column to "view assets" and re-organizing columns (#4970) 2018-02-05 17:36:35 -06:00
README Bot 1359a4f88a Add CodeTriage badge to snipe/snipe-it (#4968)
Adds a badge showing the number of people helping this repo on CodeTriage.

[![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)

## What is CodeTriage?

CodeTriage is an Open Source app that is designed to make contributing to Open Source projects easier. It works by sending subscribers a few open issues in their inbox. If subscribers get busy, there is an algorithm that backs off issue load so they do not get overwhelmed

[Read more about the CodeTriage project](https://www.codetriage.com/what).

## Why am I getting this PR?

Your project was picked by the human, @schneems. They selected it from the projects submitted to https://www.codetriage.com and hand edited the PR. How did your project get added to [CodeTriage](https://www.codetriage.com/what)? Roughly 4 months ago, [@imjennyli](https://github.com/imjennyli) added this project to CodeTriage in order to start contributing. Since then, 8 people have subscribed to help this repo.

## What does adding a badge accomplish?

Adding a badge invites people to help contribute to your project. It also lets developers know that others are invested in the longterm success and maintainability of the project.

You can see an example of a CodeTriage badge on these popular OSS READMEs:

- [![](https://www.codetriage.com/rails/rails/badges/users.svg)](https://www.codetriage.com/rails/rails) https://github.com/rails/rails
- [![](https://www.codetriage.com/crystal-lang/crystal/badges/users.svg)](https://www.codetriage.com/crystal-lang/crystal) https://github.com/crystal-lang/crystal

## Have a question or comment?

While I am a bot, this PR was manually reviewed and monitored by a human - @schneems. My job is writing commit messages and handling PR logistics.

If you have any questions, you can reply back to this PR and they will be answered by @schneems. If you do not want a badge right now, no worries, close the PR, you will not hear from me again.

Thanks for making your project Open Source! Any feedback is greatly appreciated.
2018-02-05 15:22:52 -06:00
snipe 1e1362bdbc Merge branch 'develop' 2018-02-02 09:42:50 -06:00
snipe 813106efd3 Default to only changing default location in bulk edit 2018-02-02 09:42:34 -06:00
snipe 08d129c2ea Fixed #4951 - updating asset location in bulk edit 2018-02-02 09:36:40 -06:00
snipe 8491e57258 Merge branch 'develop' 2018-02-02 09:32:00 -06:00
snipe d86fb098a8 Fixed sort ordering on dashboard 2018-02-02 09:31:43 -06:00
snipe e21f8e46d4 Merge branch 'develop' 2018-02-01 17:18:16 -06:00
snipe b3a6ec2804 Fixed #4938 - default sort order 2018-02-01 17:17:56 -06:00
snipe 0034938c04 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-02-01 16:32:13 -06:00
snipe d2587337e4 Fixed #4952 - ignore show_archived setting when drilling down into specific ID 2018-02-01 16:31:32 -06:00
snipe 8b2045523d Bumped hash 2018-02-01 15:55:33 -06:00
snipe e7e10c24be Add departments to usr export 2018-02-01 15:54:49 -06:00
snipe f06852f48d Merge branch 'develop' 2018-01-25 13:17:11 -06:00
snipe 2f9fff7130 Do not try to show depreciation report if no depreciations are set up 2018-01-25 13:16:49 -06:00
snipe 0b788f64f7 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-25 11:07:18 -08:00
snipe facf1d42f7 Sigh. 2018-01-25 11:06:37 -08:00
snipe e77aae703b Bumped hash 2018-01-25 11:03:45 -08:00
snipe 76f52dd89b Fixed #4872 - Check for assigned in depreciation table 2018-01-25 11:02:46 -08:00
snipe 0e980f7229 Hotfix: Disabling the event dispatcher broke model validation. (#4912) (#4915)
* Hotfix: Disabling the event dispatcher broke model validation.

This resulted in invalid data being imported.  Reenable the event dispatcher for now--this causes double logs, but at least validates properly.

* Actually disable the event dispatcher.

* Sign in where necessary to fix the importer unit test.  This catches the issues found manually in 4912
2018-01-25 10:29:06 -08:00
Daniel Meltzer 2f5d550df6 Hotfix: Disabling the event dispatcher broke model validation. (#4912)
* Hotfix: Disabling the event dispatcher broke model validation.

This resulted in invalid data being imported.  Reenable the event dispatcher for now--this causes double logs, but at least validates properly.

* Actually disable the event dispatcher.

* Sign in where necessary to fix the importer unit test.  This catches the issues found manually in 4912
2018-01-25 10:10:56 -08:00
snipe 3acf5f76fe Merge branch 'develop' 2018-01-25 03:35:30 -08:00
snipe 4be8ae7f3d Fuckery. 2018-01-25 03:34:52 -08:00
snipe 029dd43ecd Merge branch 'develop' 2018-01-25 03:01:35 -08:00
snipe cf8feb37e1 Fixed crash if no model associated
This should never be triggered. Bad data is getting in somehow.
2018-01-25 03:00:54 -08:00
snipe 648531f4cc Merge branch 'develop' 2018-01-25 00:26:17 -08:00
snipe 11505d5d06 Fix crash if no asset model
(This should never happen, but shouldn’t crash if/when it does)
2018-01-25 00:25:43 -08:00
snipe 1d04897b32 Order by default location 2018-01-24 14:27:12 -08:00
snipe eddcc0fbbd Fixed cookie issue on hardware 2018-01-24 14:23:19 -08:00
snipe bd80a77b78 Added default location to asset listing 2018-01-24 14:23:12 -08:00
snipe edc30a31c1 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-24 11:02:46 -08:00
snipe f5636f325d Bumped hash 2018-01-24 11:01:51 -08:00
snipe 426bf3803b Merge branch 'develop' 2018-01-24 11:00:40 -08:00
snipe 739d3c72b7 Fixed #4902 - include last name in checkin email 2018-01-24 10:59:34 -08:00
snipe 60c38a0c47 Added setting to choose what appears in model select list - Fixes #4879 2018-01-24 10:43:46 -08:00
snipe 9566fbd3cd Fixed borked down() migrations 2018-01-24 10:41:49 -08:00
Anh DAO-DUY e41ee1bcf8 Fix upload images problem with Docker (#4906)
Some folders were missing in this script file (Docker installation).
Missing folders caused errors while uploading some images.
2018-01-24 09:13:03 -08:00
Tim Bishop bc14f225af Only use location currency if it's actually set. (#4904)
This changes the depreciation report to only use the currency on a
location if it's actually set to something. Previously, if an asset had
a location it would use the currency even if it was blank rather than
falling back to the default.
2018-01-24 08:55:51 -08:00
snipe 07148c1503 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-24 08:29:25 -08:00
snipe fcb5eea951 Bumped hash 2018-01-24 08:28:53 -08:00
snipe 7a4bf26733 Merge branch 'develop' 2018-01-24 08:25:36 -08:00
snipe 2c2910d1dd Handle shitty edge cases where an asset has no model without crashing 2018-01-24 08:16:05 -08:00
snipe 1dae7a2fe4 Fixed #3636 - removed thread_id (we don’t use this anymore) 2018-01-24 08:00:28 -08:00
snipe e19ab329bd Add @tdb as a contributor 2018-01-24 07:13:24 -08:00
snipe 922cb90cb3 Add @CronKz as a contributor 2018-01-24 07:12:59 -08:00
snipe 765295136a Added - ability to add custom footer text, hide user’s manual/support links 2018-01-24 07:02:30 -08:00
snipe 7579333ad3 Disallow LDAP settings if in demo mode 2018-01-24 05:50:31 -08:00
snipe 543ea28b72 Added qty to asset components - fixed #4876 2018-01-24 05:25:01 -08:00
snipe fefd6d60f6 Fixed #4899 - sorting in user history 2018-01-24 04:48:00 -08:00
snipe a7b8b4bf55 Added: ability to change actual location from bulk edit assets 2018-01-24 04:38:25 -08:00
snipe 7cafa194c1 Fix for counts 2018-01-24 04:26:15 -08:00
snipe b37f78dbbf Fixed #4858 - wrong params for id count 2018-01-24 04:24:45 -08:00
snipe e20cd42cc2 More parse error fixes 2018-01-24 03:42:49 -08:00
snipe 7b99f81f72 Fixed parse error on hardware blade 2018-01-24 03:38:29 -08:00
snipe f1bbdc9e59 Revert PR #4845 2018-01-24 03:32:45 -08:00
Richard Hofman 5219fb63a1 Add --base_dn option to LdapSync command. (#4888) 2018-01-23 18:15:36 -08:00
CronKz dcc379c3fa Adding missing translations. (#4896) 2018-01-23 18:13:55 -08:00
vcordes79 0fb8dc3418 check if user is allowed to view assets (#4845) 2018-01-23 18:10:05 -08:00
vcordes79 f4e9d245d0 Status labels (#4895)
* fix statuslabels

* fix statuslabels
2018-01-23 18:08:54 -08:00
snipe c75a2051ff Hide mfg button if no permissions to create 2018-01-22 14:02:23 -08:00
CronKz 691ec164b1 Added Translations (#4880) 2018-01-22 13:14:52 -08:00
vcordes79 7b596c750d API for (dis)associating fields with fieldsets (#4881)
* start work on fields in fieldset api

* revert CustomFieldsetsController

* fieldset associate / disassociate api

* fix variable names and payload

* fix variable name
2018-01-22 13:14:04 -08:00
Tim Bishop b346556caa Allow manager_id to be fillable. (#4882)
The API UsersController accepts manager_id, but calls the following:

$user->fill($request->all());

This results in manager_id being ignored. I can't see any problem with
allowing a user's manager to be modified using the API, so this change
allows it.
2018-01-22 13:12:02 -08:00
snipe 93ec7068df Removed a few additional unused badges 2018-01-20 08:54:49 -08:00
snipe 5f65f993a0 Small refactor for AssetPresenter method 2018-01-20 08:52:50 -08:00
snipe a9441521a4 Small refactor for Setting method 2018-01-20 08:52:50 -08:00
snipe 2dede67ae9 Removed unusued badges 2018-01-20 08:52:49 -08:00
Daniel Meltzer 6bf17e7d47 Reset the item between rows of import to avoid stale data. (#4868) 2018-01-20 08:40:01 -08:00
snipe a3240da707 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-20 07:47:54 -08:00
snipe a28fee1ff4 Bumped hash 2018-01-20 07:47:07 -08:00
snipe 57e5af2f69 Removed console logging from JS 2018-01-20 07:42:48 -08:00
snipe 8d3a214475 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-20 04:56:36 -08:00
snipe 58eedce6fe Updated language files 2018-01-20 04:53:04 -08:00
snipe f91704a372 Added Ukrianian to language dropdown 2018-01-20 04:49:40 -08:00
snipe f53c68e040 Bumped hash 2018-01-20 04:40:26 -08:00
snipe 99e55f84f0 Fixed misc UI permissions elements 2018-01-20 04:39:31 -08:00
snipe 798ea75f3d Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-20 04:00:26 -08:00
snipe 913e6a5709 Bumped hash 2018-01-20 03:59:42 -08:00
snipe 34f6d5ab45 Fixed #4671 - corrected component checkin gate 2018-01-20 03:58:59 -08:00
snipe 86c0194e9a Fixed #4628 and #4590 - Illegal mix of collations for operation error when searching on some languages 2018-01-20 03:08:27 -08:00
Brady Wetherington dfb2b9b569 Major overhaul for modals, and a fix for #4820 (#4866)
Changes how the various modals work, and allows for specifying
category_type when inline-creating categories.
2018-01-20 00:42:29 -08:00
snipe 7fae380ab6 Fixed #4300 - Fix for illegal character type in action log 2018-01-20 00:27:45 -08:00
snipe 4ca8272efc Merge branch 'develop' 2018-01-20 00:21:03 -08:00
snipe 5d4bbc393e Fixed #4837 - link phone numbers 2018-01-20 00:20:45 -08:00
snipe 984275ff05 Merge branch 'develop' 2018-01-19 23:47:54 -08:00
snipe e6f70f2ab7 Fixed #4821 - add username to user selection dropdown 2018-01-19 23:47:37 -08:00
snipe f7de252f67 Wrong branch. :( 2018-01-19 23:46:42 -08:00
snipe 532b299c40 Fixed #4821 - add username to user selection dropdown 2018-01-19 23:46:12 -08:00
snipe 5dcc63dc74 Merge branch 'develop' 2018-01-19 20:49:20 -08:00
snipe 6eb8acf319 Swich to panel box for dashboard message 2018-01-19 20:49:02 -08:00
snipe 862251ab36 Change label to stale 2018-01-19 20:45:25 -08:00
snipe 95a9742571 Fixed #4768 - adds dashboard message option to settings 2018-01-19 20:43:55 -08:00
snipe 81d0921782 Merge branch 'develop' 2018-01-19 19:18:43 -08:00
snipe 0fa556da1d Exempt ready for dev and bounty tags from stale collection 2018-01-19 19:16:35 -08:00
snipe 05bc238c9a Merge branch 'develop' 2018-01-19 18:17:38 -08:00
snipe 782813ab49 Check for valid category before checking acceptance 2018-01-19 18:17:23 -08:00
snipe cbca126d9d Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-19 17:53:15 -08:00
snipe a9ffe8d210 Bumped hash 2018-01-19 17:52:40 -08:00
snipe c242abb42e Added Company policy to fix company deletion issue 2018-01-19 17:51:28 -08:00
snipe 2c722ffc4f Fixed issue template with correct path to storage logs 2018-01-19 16:31:01 -08:00
snipe 484c47cef8 Added stale.yml to auto-close stale issues 2018-01-19 16:23:28 -08:00
snipe f38dc37152 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-17 19:31:09 -08:00
snipe 6133f09056 Bumped hash 2018-01-17 19:30:31 -08:00
snipe 2a959edeba Added - Setting to allow archived assets in List All 2018-01-17 19:18:48 -08:00
snipe 8995d689b8 Fixed #4817 - [BREAKING API CHANGE] - changed user API response from firstname, lastname to first_name, last_name 2018-01-17 13:25:11 -08:00
snipe f08bec6c78 Merge branch 'develop' 2018-01-17 13:12:58 -08:00
snipe d920d91786 Fixed #4593 - do not require model_id to update asset custom fields via API 2018-01-17 13:12:32 -08:00
snipe e35b3745eb Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-17 12:41:51 -08:00
snipe e8252d9468 Bumped hash 2018-01-17 12:41:11 -08:00
snipe 8fff6a1a06 Update asset location based on user checkout in bulk checkout 2018-01-17 12:39:49 -08:00
snipe 0eff821928 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-17 12:12:33 -08:00
snipe 9e605e0f79 Bumped hash 2018-01-17 12:11:39 -08:00
snipe 8fb991110e Fixed #4652 - asset not correctly checking out to user on creation 2018-01-17 12:10:28 -08:00
snipe b383ebee48 Add @fordster78 as a contributor 2018-01-17 10:59:00 -08:00
fordster78 138313dcb9 Setup changes (#4813)
* Add Asset Tag settings to Setup

* Add Locale Settings to Setup

* Add multiple company support to setup

* Changed the locale label name from 'site_name' to locale
Added default value for language to 'en' and multiple companies support
to 0 (false)
Switched out the old Input facade to the preferred $request->input
method for the setup page.
2018-01-17 10:58:03 -08:00
snipe f254958db9 Check if db_column foield already exists 2018-01-17 06:48:14 -08:00
snipe 09eff88679 Merge branch 'develop' 2018-01-17 06:28:11 -08:00
snipe 24b356dba4 Fixed typos in default blade that cause components to not show up for non-superadmins 2018-01-17 06:27:23 -08:00
snipe 91bca5fcba Fixed #4844 - use input value for ids in user bulk edit 2018-01-17 06:15:52 -08:00
vcordes79 96a469db36 allow changing user activated field via api (#4843) 2018-01-17 05:38:10 -08:00
snipe 9ab05e7037 Add @vcordes79 as a contributor 2018-01-17 05:36:15 -08:00
vcordes79 52a99faf68 fix phone number update in api (#4842) 2018-01-17 05:33:55 -08:00
vcordes79 94cf1f8741 Fixes #4829 - add fields api (#4840)
* add fields api

* change route names
2018-01-17 05:31:57 -08:00
snipe e2a8f9b790 Merge branch 'develop' 2018-01-17 03:27:03 -08:00
snipe 409f5cc4fd Added - display asset model category on hardware view page 2018-01-16 16:26:24 -08:00
snipe 3b5e4c44eb Fixed depreciation report not showing assigned to 2018-01-16 07:46:34 -08:00
snipe 69a7ea63e2 Pass nopages to dashboard stuff 2018-01-16 07:37:20 -08:00
snipe aac379daeb If nopages is passed, hide page numbers
This seems weird since we’re checking for a negative, but there are only a few spots where we wouldn’t want page numbers, namely the dashboard sruff
2018-01-16 07:37:06 -08:00
snipe 1d3472b5c4 Truncate the checkout_requests field on seed 2018-01-16 07:36:14 -08:00
snipe 66a590b774 Account for user’s that have been deleted in the requested list 2018-01-16 07:36:03 -08:00
snipe dc4472e9e9 Misc export table fixes 2018-01-15 21:03:46 -08:00
snipe 6bfd428c2e Use real status label names, even if deployed 2018-01-15 21:03:26 -08:00
snipe f4623bd277 Add user group membership to user view page 2018-01-15 20:31:10 -08:00
snipe 1f04d7aafd Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-11 15:27:17 -08:00
snipe 78efeec368 Bumped hash 2018-01-11 15:24:37 -08:00
snipe 5b15a2fc0a Merge branch 'develop' 2018-01-11 15:23:27 -08:00
snipe 68f1fa0340 Added - ability to sort by asset count in models 2018-01-11 15:21:51 -08:00
snipe 9293f17707 Moved search scope lower to fix weird (possible Laravel) bug w/prepared statements 2018-01-11 15:17:34 -08:00
snipe a4b32e2328 Improved - use presenters on model detail 2018-01-11 15:17:10 -08:00
snipe d109ca30e2 Improved - allow searching on most detail views with additional tables 2018-01-11 15:16:53 -08:00
snipe 3b4a651dd9 Allow counts in mfg sorting 2018-01-11 15:16:23 -08:00
snipe a4ac53e2e9 Improved - Using presenters for column headers in location detail 2018-01-11 15:16:09 -08:00
snipe cf1b5a7685 Added- sort by count in manufacturer listing 2018-01-11 15:13:32 -08:00
snipe 0789eb8b07 Improved - using presenters for column headers in manufacturer detail 2018-01-11 15:12:48 -08:00
snipe 7f674fdd35 Require implicit search 2018-01-11 13:18:06 -08:00
snipe 500aa37e3c Fixed switchable attributes on table headers 2018-01-11 13:17:55 -08:00
snipe efe668d26d Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-01-10 22:59:02 -08:00
snipe 90db97b980 Merge branch 'features/fixes_4792_ajax_tables_on_license_view' into develop 2018-01-10 22:57:44 -08:00
snipe bc3d27fac6 Bumped hash 2018-01-10 22:57:22 -08:00
snipe 55b9f1207d Updated bootstrap tables 2018-01-10 22:53:54 -08:00
snipe 2bbb6001a8 Added location to seats transformer 2018-01-10 20:36:27 -08:00
snipe af7b7664c5 Added license seat location method 2018-01-10 20:34:44 -08:00
snipe c31362655c Refactored BS tables include for clearer separation of simple v not simple 2018-01-10 20:34:36 -08:00
snipe c6a956382f Fixed #4784 - cookie not always being set correctly for ajax tables 2018-01-10 20:04:41 -08:00
snipe bab0bda174 Added custom formatter for license seats (WIP) 2018-01-10 18:58:55 -08:00
snipe bb52a8417c Switch view code to AJAX table 2018-01-10 18:58:41 -08:00
snipe e3d7be23cb Added new seats controller method 2018-01-10 18:47:57 -08:00
snipe 3d5545494e Added new seats transformer 2018-01-10 18:47:40 -08:00
snipe 7f1a535b30 Added new seats API route 2018-01-10 18:47:27 -08:00
snipe 254234b0dc Fixed #4787 - don’t try to display category if it is invalid
This shouldn’t be needed, but in case data got weird (manual editing, etc)
2018-01-10 06:33:59 -08:00
snipe 3566f37981 Merge branch 'develop' 2018-01-10 06:25:06 -08:00
snipe e6259eb6e1 Fixed #4774 - show assets assigned to assets in asset view
Todo: Fix text search on the asset to asset tab. It’s currently broken so I’ve disabled it.
2018-01-10 05:44:11 -08:00
snipe eeb3d1eb42 Use language strings for tab text 2018-01-10 05:42:34 -08:00
snipe 79295f6434 Use dataTableLayout for table 2018-01-10 05:33:45 -08:00
snipe 285e4e2e52 Allow bulk language update in user edit 2018-01-10 05:33:26 -08:00
snipe 5587b64d64 Fixed #4770 - broken licenses, etc on company view, added users and components 2018-01-10 03:52:21 -08:00
snipe f0f2a5aa67 Workaround for #4784 - make changes tab always visible
Not sure why the cookie isn’t cookie-ing
2018-01-10 01:56:24 -08:00
Brady Wetherington 061317866b Changes to Models in the asset-edit screen maintain chosen values (#4781)
Fixed for #2195
2018-01-09 23:45:20 -08:00
snipe 65ffc01583 Merge branch 'develop' 2018-01-09 20:19:50 -08:00
snipe f5f7a63a23 Production assets 2018-01-09 20:19:04 -08:00
snipe b6a7fd1cec Run production assets - because modern web development. Sigh. 2018-01-09 20:18:49 -08:00
snipe 6245f92e16 Merge branch 'develop' 2018-01-09 20:12:44 -08:00
snipe 0abab2107c Fixed #4779 - show selected filename on filepicker 2018-01-09 20:12:07 -08:00
snipe afc7116260 Fixed #4778 - added notes to asset model view 2018-01-09 20:00:06 -08:00
Geoff Young 0b3d2b46e0 Add attributes to delete asset file button (#4336)
This adds attributes to the delete file buttons on the View Asset page.
The attributes will fill the confirmation modal that prompts users
before deleting. They also activate a tooltip on the button.
2018-01-03 17:25:50 -08:00
Brandon Daniel Bailey f786e07179 Allow auto increment through the API (#4690)
* Allow auto incrementing asset_id from the API when the setting is enabled

* Cleaned up the if else statement

* Added prefix to the orWhereRaw which causes a database error if the configuration uses a prefix

* Auto incrementing through the API
2018-01-03 17:24:32 -08:00
Daniel Meltzer b2469bb34f Fix double create log on import. (#4706)
* Fix double create log on import.

* Fix code error causing component importer to implode.

* More component importer oldities
2018-01-03 17:22:02 -08:00
Brandon Daniel Bailey b721bfcc84 Added prefix to the orWhereRaw which causes a database error if the configuration uses a prefix (#4703) 2017-12-28 20:09:36 -08:00
Daniel Meltzer f16ce09a7a Importer again (#4702)
* If a user id is provided in the name column of an import, we should assume that it is a user id and check out to it.

* Fix build of vue files.  The location is public/js/build, not public/build

* Ensure a status type is set before allowing submission of an import.

Also expand the status text label to change color based on success/failure.

Fixes #4658

* Use right key to lookup emails when importing users.  Fixes 4619.

* Import serial for components, and make unique matches based on the serial as well as the name.  Fixes #4569

* Set the location_id when importing an item properly.

This moves as well to using the Asset::checkout() method, which should consolidate the logic into a useful spot.
Fixes #4563 (I think)

* Production assets.

* Case insensitive field map guessing and repopulate when changingin import type.
2017-12-28 20:08:45 -08:00
snipe bbe9df306b Merge branch 'develop' 2017-12-26 17:33:06 -08:00
snipe 1bd7392531 Account for audits on deleted assets 2017-12-26 17:32:45 -08:00
snipe 2002dfca17 Merge branch 'develop' 2017-12-26 17:13:49 -08:00
snipe 38c2ecbd0c Fixed migration use 2017-12-26 17:13:26 -08:00
snipe ce97faa8d4 Merge branch 'develop' 2017-12-26 17:11:40 -08:00
snipe 31ca4bff8c Break audit date denorm migrations into two separate migrations 2017-12-26 17:11:08 -08:00
snipe 6f9033b2fd Merge branch 'develop' 2017-12-26 16:49:42 -08:00
snipe 8864f81402 Fixed manufacturer error on printable user page
Manufacturer is not required for accessories, so need to account for that
2017-12-26 16:49:01 -08:00
snipe 71ba1af647 Fixed button class on asset view 2017-12-26 16:48:28 -08:00
snipe b894a4c19a Merge branch 'develop' 2017-12-20 12:36:45 -08:00
snipe c3a44f25fd Fixed #4663 - duplicate manufacturer name in selectlist 2017-12-20 12:32:55 -08:00
snipe 1f36e7997f Bumped version 2017-12-20 03:31:43 -08:00
snipe 33b5c26da5 Bumped hashcount 2017-12-19 22:16:31 -08:00
snipe e5a7e6619f Merge branch 'develop' 2017-12-19 22:15:51 -08:00
snipe d2e2c1c05f Stub and 404 registration routes 2017-12-19 22:14:51 -08:00
snipe 557b8b0ded Merge branch 'develop' 2017-12-19 20:57:46 -08:00
snipe 37d4cf3afb Fixed #4647 - requestable model button not clickable 2017-12-19 20:48:26 -08:00
snipe b716db225f Added “new” buttons for manufacturer and category in asset model creation 2017-12-19 20:30:46 -08:00
snipe fbe093705d Fixed #4640 - add username to user detail 2017-12-19 13:42:34 -08:00
snipe db278e9109 Merge branch 'develop' 2017-12-19 00:48:44 -08:00
snipe 88798435f6 Fixed inefficient query for inventory alerts 2017-12-19 00:32:39 -08:00
snipe 6220f0d8a5 Merge branch 'develop'
# Conflicts:
#	config/version.php
2017-12-15 18:57:21 -08:00
snipe 30716b349b Bumped dev hash 2017-12-15 18:55:56 -08:00
snipe 7a8c8233a2 Fixes #4639 2017-12-15 18:54:38 -08:00
616 changed files with 14869 additions and 22083 deletions
+45
View File
@@ -838,6 +838,51 @@
"contributions": [
"doc"
]
},
{
"login": "vcordes79",
"name": "vcordes79",
"avatar_url": "https://avatars1.githubusercontent.com/u/10672546?v=4",
"profile": "https://github.com/vcordes79",
"contributions": [
"code"
]
},
{
"login": "fordster78",
"name": "fordster78",
"avatar_url": "https://avatars3.githubusercontent.com/u/27958330?v=4",
"profile": "https://github.com/fordster78",
"contributions": [
"code"
]
},
{
"login": "CronKz",
"name": "CronKz",
"avatar_url": "https://avatars0.githubusercontent.com/u/34064225?v=4",
"profile": "https://github.com/CronKz",
"contributions": [
"code"
]
},
{
"login": "tdb",
"name": "Tim Bishop",
"avatar_url": "https://avatars1.githubusercontent.com/u/585486?v=4",
"profile": "https://github.com/tdb",
"contributions": [
"code"
]
},
{
"login": "seanmcilvenna",
"name": "Sean McIlvenna",
"avatar_url": "https://avatars2.githubusercontent.com/u/5384694?v=4",
"profile": "https://www.seanmcilvenna.com",
"contributions": [
"code"
]
}
]
}
+1 -1
View File
@@ -29,7 +29,7 @@
- If a stacktrace is provided in the error, include that too.
- Any errors that appear in your browser's error console.
- Confirm whether the error is reproducible on the demo: https://snipeitapp.com/demo.
- Include any additional information you can find in `app/storage/logs` and your webserver's logs.
- Include any additional information you can find in `storage/logs` and your webserver's logs.
- Include what you've done so far in the installation, and if you got any error messages along the way.
- Indicate whether or not you've manually edited any data directly in the database
+19
View File
@@ -0,0 +1,19 @@
# Number of days of inactivity before an issue becomes stale
daysUntilStale: 60
# Number of days of inactivity before a stale issue is closed
daysUntilClose: 7
# Issues with these labels will never be considered stale
exemptLabels:
- pinned
- security
- ready for dev
- bounty
# Label to use when marking an issue as stale
staleLabel: stale
# Comment to post when marking an issue as stale. Set to `false` to disable
markComment: >
This issue has been automatically marked as stale because it has not had
recent activity. It will be closed if no further activity occurs. Thank you
for your contributions!
# Comment to post when closing a stale issue. Set to `false` to disable
closeComment: false
+5 -3
View File
@@ -1,5 +1,6 @@
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=develop)](https://travis-ci.org/snipe/snipe-it) [![Stories in Ready](https://badge.waffle.io/snipe/snipe-it.png?label=ready+for+dev&title=Ready+for+development)](http://waffle.io/snipe/snipe-it) [![Maintenance](https://img.shields.io/maintenance/yes/2017.svg)]() [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Zenhub](https://img.shields.io/badge/Shipping_faster_with-ZenHub-5e60ba.svg)](https://zenhub.io) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-90-orange.svg?style=flat-square)](#contributors)
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=master)](https://travis-ci.org/snipe/snipe-it) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-94-orange.svg?style=flat-square)](#contributors)
[![Open Source Helpers](https://www.codetriage.com/snipe/snipe-it/badges/users.svg)](https://www.codetriage.com/snipe/snipe-it)
## Snipe-IT - Open Source Asset Management System
@@ -68,7 +69,8 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars2.githubusercontent.com/u/857740?v=3" width="110px;"/><br /><sub>Gil Rutkowski</sub>](http://FlashingCursor.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [<img src="https://avatars3.githubusercontent.com/u/129360?v=3" width="110px;"/><br /><sub>Desmond Morris</sub>](http://www.desmondmorris.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [<img src="https://avatars2.githubusercontent.com/u/52936?v=3" width="110px;"/><br /><sub>Nick Peelman</sub>](http://peelman.us)<br />[💻](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [<img src="https://avatars0.githubusercontent.com/u/53161?v=3" width="110px;"/><br /><sub>Abraham Vegh</sub>](https://abrahamvegh.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [<img src="https://avatars0.githubusercontent.com/u/2818680?v=3" width="110px;"/><br /><sub>Mohamed Rashid</sub>](https://github.com/rashivkp)<br />[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [<img src="https://avatars3.githubusercontent.com/u/1509456?v=3" width="110px;"/><br /><sub>Kasey</sub>](http://hinchk.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [<img src="https://avatars2.githubusercontent.com/u/10522541?v=3" width="110px;"/><br /><sub>Brett</sub>](https://github.com/BrettFagerlund)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
| [<img src="https://avatars2.githubusercontent.com/u/16108587?v=3" width="110px;"/><br /><sub>Jason Spriggs</sub>](http://jasonspriggs.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [<img src="https://avatars2.githubusercontent.com/u/1134568?v=3" width="110px;"/><br /><sub>Nate Felton</sub>](http://n8felton.wordpress.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [<img src="https://avatars2.githubusercontent.com/u/14036694?v=3" width="110px;"/><br /><sub>Manasses Ferreira</sub>](http://homepages.dcc.ufmg.br/~manassesferreira)<br />[💻](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [<img src="https://avatars0.githubusercontent.com/u/15913949?v=3" width="110px;"/><br /><sub>Steve</sub>](https://github.com/steveelwood)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [<img src="https://avatars1.githubusercontent.com/u/3361683?v=3" width="110px;"/><br /><sub>matc</sub>](http://twitter.com/matc)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [<img src="https://avatars3.githubusercontent.com/u/7405702?v=3" width="110px;"/><br /><sub>Cole R. Davis</sub>](http://www.davisracingteam.com)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [<img src="https://avatars2.githubusercontent.com/u/10167681?v=3" width="110px;"/><br /><sub>gibsonjoshua55</sub>](https://github.com/gibsonjoshua55)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
| [<img src="https://avatars2.githubusercontent.com/u/2809241?v=4" width="110px;"/><br /><sub>Robin Temme</sub>](https://github.com/zwerch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [<img src="https://avatars0.githubusercontent.com/u/6961695?v=4" width="110px;"/><br /><sub>Iman</sub>](https://github.com/imanghafoori1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [<img src="https://avatars1.githubusercontent.com/u/6551003?v=4" width="110px;"/><br /><sub>Richard Hofman</sub>](https://github.com/richardhofman6)<br />[💻](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [<img src="https://avatars0.githubusercontent.com/u/3697569?v=4" width="110px;"/><br /><sub>gizzmojr</sub>](https://github.com/gizzmojr)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") | [<img src="https://avatars3.githubusercontent.com/u/404729?v=4" width="110px;"/><br /><sub>Jenny Li</sub>](https://github.com/imjennyli)<br />[📖](https://github.com/snipe/snipe-it/commits?author=imjennyli "Documentation") | [<img src="https://avatars0.githubusercontent.com/u/869227?v=4" width="110px;"/><br /><sub>Geoff Young</sub>](https://github.com/GeoffYoung)<br />[💻](https://github.com/snipe/snipe-it/commits?author=GeoffYoung "Code") | [<img src="https://avatars3.githubusercontent.com/u/1068477?v=4" width="110px;"/><br /><sub>Elliot Blackburn</sub>](http://www.elliotblackburn.com)<br />[📖](https://github.com/snipe/snipe-it/commits?author=BlueHatbRit "Documentation") |
| [<img src="https://avatars1.githubusercontent.com/u/6357451?v=4" width="110px;"/><br /><sub>Tõnis Ormisson</sub>](http://andmemasin.eu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TonisOrmisson "Code") | [<img src="https://avatars0.githubusercontent.com/u/449411?v=4" width="110px;"/><br /><sub>Nicolai Essig</sub>](http://www.nicolai-essig.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thakilla "Code") | [<img src="https://avatars1.githubusercontent.com/u/14809698?v=4" width="110px;"/><br /><sub>Danielle</sub>](https://github.com/techincolor)<br />[📖](https://github.com/snipe/snipe-it/commits?author=techincolor "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/18545156?v=4" width="110px;"/><br /><sub>Lawrence</sub>](https://github.com/TheVakman)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=TheVakman "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3ATheVakman "Bug reports") | [<img src="https://avatars1.githubusercontent.com/u/22473767?v=4" width="110px;"/><br /><sub>uknzaeinozpas</sub>](https://github.com/uknzaeinozpas)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Tests") [💻](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Code") | [<img src="https://avatars3.githubusercontent.com/u/422752?v=4" width="110px;"/><br /><sub>Ryan</sub>](https://github.com/Gelob)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Gelob "Documentation") |
| [<img src="https://avatars1.githubusercontent.com/u/6357451?v=4" width="110px;"/><br /><sub>Tõnis Ormisson</sub>](http://andmemasin.eu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TonisOrmisson "Code") | [<img src="https://avatars0.githubusercontent.com/u/449411?v=4" width="110px;"/><br /><sub>Nicolai Essig</sub>](http://www.nicolai-essig.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thakilla "Code") | [<img src="https://avatars1.githubusercontent.com/u/14809698?v=4" width="110px;"/><br /><sub>Danielle</sub>](https://github.com/techincolor)<br />[📖](https://github.com/snipe/snipe-it/commits?author=techincolor "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/18545156?v=4" width="110px;"/><br /><sub>Lawrence</sub>](https://github.com/TheVakman)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=TheVakman "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3ATheVakman "Bug reports") | [<img src="https://avatars1.githubusercontent.com/u/22473767?v=4" width="110px;"/><br /><sub>uknzaeinozpas</sub>](https://github.com/uknzaeinozpas)<br />[⚠️](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Tests") [💻](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Code") | [<img src="https://avatars3.githubusercontent.com/u/422752?v=4" width="110px;"/><br /><sub>Ryan</sub>](https://github.com/Gelob)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Gelob "Documentation") | [<img src="https://avatars1.githubusercontent.com/u/10672546?v=4" width="110px;"/><br /><sub>vcordes79</sub>](https://github.com/vcordes79)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vcordes79 "Code") |
| [<img src="https://avatars3.githubusercontent.com/u/27958330?v=4" width="110px;"/><br /><sub>fordster78</sub>](https://github.com/fordster78)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fordster78 "Code") | [<img src="https://avatars0.githubusercontent.com/u/34064225?v=4" width="110px;"/><br /><sub>CronKz</sub>](https://github.com/CronKz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=CronKz "Code") | [<img src="https://avatars1.githubusercontent.com/u/585486?v=4" width="110px;"/><br /><sub>Tim Bishop</sub>](https://github.com/tdb)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tdb "Code") | [<img src="https://avatars2.githubusercontent.com/u/5384694?v=4" width="110px;"/><br /><sub>Sean McIlvenna</sub>](https://www.seanmcilvenna.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=seanmcilvenna "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
+57 -47
View File
@@ -16,7 +16,7 @@ class LdapSync extends Command
*
* @var string
*/
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--summary} {--json_summary}';
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--summary} {--json_summary}';
/**
* The console command description.
@@ -67,36 +67,25 @@ class LdapSync extends Command
$summary = array();
try {
$results = Ldap::findLdapUsers();
} catch (\Exception $e) {
if ($this->option('json_summary')) {
try {
if ($this->option('base_dn') != '') {
$search_base = $this->option('base_dn');
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
} else {
$search_base = null;
}
$results = Ldap::findLdapUsers($search_base);
} catch (\Exception $e) {
if ($this->option('json_summary')) {
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
$this->info(json_encode($json_summary));
}
LOG::error($e);
return [];
}
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
$ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray();
$ldap_ou_lengths = array();
foreach ($ldap_ou_locations as $location) {
$ldap_ou_lengths[] = strlen($location["ldap_ou"]);
}
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
if (sizeof($ldap_ou_locations) > 0) {
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
}
// Inject location information fields
for ($i = 0; $i < $results["count"]; $i++) {
$results[$i]["ldap_location_override"] = false;
$results[$i]["location_id"] = 0;
}
/* Determine which location to assign users to by default. */
$location = NULL;
if ($this->option('location')!='') {
$location = Location::where('name', '=', $this->option('location'))->first();
@@ -106,40 +95,61 @@ class LdapSync extends Command
$location = Location::where('id', '=', $this->option('location_id'))->first();
LOG::debug('Location ID '.$this->option('location_id').' passed');
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
} else {
$location = NULL;
}
}
if (!isset($location)) {
LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.
foreach ($ldap_ou_locations as $ldap_loc) {
$location_users = Ldap::findLdapUsers($ldap_loc["ldap_ou"]);
$usernames = array();
for ($i = 0; $i < $location_users["count"]; $i++) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc["id"];
$usernames[] = $location_users[$i][$ldap_result_username][0];
/* Process locations with explicitly defined OUs, if doing a full import. */
if ($this->option('base_dn')=='') {
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
$ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray();
$ldap_ou_lengths = array();
foreach ($ldap_ou_locations as $location) {
$ldap_ou_lengths[] = strlen($location["ldap_ou"]);
}
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
if (sizeof($ldap_ou_locations) > 0) {
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
}
// Inject location information fields
for ($i = 0; $i < $results["count"]; $i++) {
$results[$i]["ldap_location_override"] = false;
$results[$i]["location_id"] = 0;
}
// Grab subsets based on location-specific DNs, and overwrite location for these users.
foreach ($ldap_ou_locations as $ldap_loc) {
$location_users = Ldap::findLdapUsers($ldap_loc["ldap_ou"]);
$usernames = array();
for ($i = 0; $i < $location_users["count"]; $i++) {
$location_users[$i]["ldap_location_override"] = true;
$location_users[$i]["location_id"] = $ldap_loc["id"];
$usernames[] = $location_users[$i][$ldap_result_username][0];
}
}
$global_count = $results['count'];
$results = array_merge($location_users, $results);
$results['count'] = $global_count;
// Delete located users from the general group.
foreach ($results as $key => $generic_entry) {
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
unset($results[$key]);
}
}
$global_count = $results['count'];
$results = array_merge($location_users, $results);
$results['count'] = $global_count;
}
}
/* Create user account entries in Snipe-IT */
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
$pass = bcrypt($tmp_pass);
for ($i = 0; $i < $results["count"]; $i++) {
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
@@ -179,7 +189,7 @@ class LdapSync extends Command
if ($item['ldap_location_override'] == true) {
$user->location_id = $item['location_id'];
} else if ($location) {
} elseif ((isset($location)) && (!empty($location))) {
$user->location_id = e($location->id);
}
@@ -207,9 +217,9 @@ class LdapSync extends Command
if ($this->option('summary')) {
for ($x = 0; $x < count($summary); $x++) {
if ($summary[$x]['status']=='error') {
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was not imported: '.$summary[$x]['note']);
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was not imported: '.$summary[$x]['note']);
} else {
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].' was '.strtoupper($summary[$x]['createorupdate']).'.');
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was '.strtoupper($summary[$x]['createorupdate']).'.');
}
}
} else if ($this->option('json_summary')) {
+69 -12
View File
@@ -460,19 +460,19 @@ class Helper
*/
public static function checkLowInventory()
{
$consumables = Consumable::with('users')->whereNotNull('min_amt')->get();
$accessories = Accessory::with('users')->whereNotNull('min_amt')->get();
$components = Component::with('assets')->whereNotNull('min_amt')->get();
$consumables = Consumable::withCount('consumableAssignments')->whereNotNull('min_amt')->get();
$accessories = Accessory::withCount('users')->whereNotNull('min_amt')->get();
$components = Component::withCount('assets')->whereNotNull('min_amt')->get();
$avail_consumables = 0;
$items_array = array();
$all_count = 0;
foreach ($consumables as $consumable) {
$avail = $consumable->numRemaining();
$avail = $consumable->qty - $consumable->consumable_assignment_count; //$consumable->numRemaining();
if ($avail < ($consumable->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($consumable->qty > 0) {
$percent = number_format((($consumable->numRemaining() / $consumable->qty) * 100), 0);
$percent = number_format((($avail / $consumable->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -481,7 +481,7 @@ class Helper
$items_array[$all_count]['name'] = $consumable->name;
$items_array[$all_count]['type'] = 'consumables';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining']=$consumable->numRemaining();
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt']=$consumable->min_amt;
$all_count++;
}
@@ -490,11 +490,11 @@ class Helper
}
foreach ($accessories as $accessory) {
$avail = $accessory->numRemaining();
$avail = $accessory->qty - $accessory->users_count;
if ($avail < ($accessory->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($accessory->qty > 0) {
$percent = number_format((($accessory->numRemaining() / $accessory->qty) * 100), 0);
$percent = number_format((($avail / $accessory->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -503,7 +503,7 @@ class Helper
$items_array[$all_count]['name'] = $accessory->name;
$items_array[$all_count]['type'] = 'accessories';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining']=$accessory->numRemaining();
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt']=$accessory->min_amt;
$all_count++;
}
@@ -511,10 +511,10 @@ class Helper
}
foreach ($components as $component) {
$avail = $component->numRemaining();
$avail = $component->qty - $component->assets_count;
if ($avail < ($component->min_amt) + \App\Models\Setting::getSettings()->alert_threshold) {
if ($component->qty > 0) {
$percent = number_format((($component->numRemaining() / $component->qty) * 100), 0);
$percent = number_format((($avail / $component->qty) * 100), 0);
} else {
$percent = 100;
}
@@ -523,7 +523,7 @@ class Helper
$items_array[$all_count]['name'] = $component->name;
$items_array[$all_count]['type'] = 'components';
$items_array[$all_count]['percent'] = $percent;
$items_array[$all_count]['remaining']=$component->numRemaining();
$items_array[$all_count]['remaining'] = $avail;
$items_array[$all_count]['min_amt']=$component->min_amt;
$all_count++;
}
@@ -731,5 +731,62 @@ class Helper
}
// Nicked from Drupal :)
// Returns a file size limit in bytes based on the PHP upload_max_filesize
// and post_max_size
public static function file_upload_max_size() {
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = Helper::parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = $post_max_size;
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = Helper::parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = $upload_max;
}
}
return $max_size;
}
public static function file_upload_max_size_readable() {
static $max_size = -1;
if ($max_size < 0) {
// Start with post_max_size.
$post_max_size = Helper::parse_size(ini_get('post_max_size'));
if ($post_max_size > 0) {
$max_size = ini_get('post_max_size');
}
// If upload_max_size is less, then reduce. Except if upload_max_size is
// zero, which indicates no limit.
$upload_max = Helper::parse_size(ini_get('upload_max_filesize'));
if ($upload_max > 0 && $upload_max < $max_size) {
$max_size = ini_get('upload_max_filesize');
}
}
return $max_size;
}
public static function parse_size($size) {
$unit = preg_replace('/[^bkmgtpezy]/i', '', $size); // Remove the non-unit characters from the size.
$size = preg_replace('/[^0-9\.]/', '', $size); // Remove the non-numeric characters from the size.
if ($unit) {
// Find the position of the unit in the ordered string which is the power of magnitude to multiply a kilobyte by.
return round($size * pow(1024, stripos('bkmgtpezy', $unit[0])));
}
else {
return round($size);
}
}
}
@@ -40,10 +40,24 @@ class AssetMaintenancesController extends Controller
$maintenances = $maintenances->TextSearch(e($request->input('search')));
}
if ($request->has('asset_id')) {
$maintenances->where('asset_id', '=', $request->input('asset_id'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes','user_id'];
$allowed_columns = [
'id',
'title',
'asset_maintenance_time',
'asset_maintenance_type',
'cost',
'start_date',
'completion_date',
'notes',
'user_id'
];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
@@ -30,20 +30,21 @@ class AssetModelsController extends Controller
public function index(Request $request)
{
$this->authorize('view', AssetModel::class);
$allowed_columns = ['id','image','name','model_number','eol','notes','created_at','manufacturer'];
$allowed_columns = ['id','image','name','model_number','eol','notes','created_at','manufacturer','assets_count'];
$assetmodels = AssetModel::select(['models.id','models.image','models.name','model_number','eol','models.notes','models.created_at','category_id','manufacturer_id','depreciation_id','fieldset_id', 'models.deleted_at'])
->with('category','depreciation', 'manufacturer','fieldset')
->withCount('assets');
if ($request->has('search')) {
$assetmodels->TextSearch($request->input('search'));
}
if ($request->has('status')) {
$assetmodels->onlyTrashed();
}
if ($request->has('search')) {
$assetmodels->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
@@ -60,6 +61,7 @@ class AssetModelsController extends Controller
}
$total = $assetmodels->count();
$assetmodels = $assetmodels->skip($offset)->take($limit)->get();
return (new AssetModelsTransformer)->transformAssetModels($assetmodels, $total);
@@ -192,6 +194,7 @@ class AssetModelsController extends Controller
'models.category_id',
])->with('manufacturer','category');
$settings = \App\Models\Setting::getSettings();
if ($request->has('search')) {
$assetmodels = $assetmodels->SearchByManufacturerOrCat($request->input('search'));
@@ -200,8 +203,24 @@ class AssetModelsController extends Controller
$assetmodels = $assetmodels->OrderCategory('ASC')->OrderManufacturer('ASC')->orderby('models.name', 'asc')->orderby('models.model_number', 'asc')->paginate(50);
foreach ($assetmodels as $assetmodel) {
$assetmodel->use_text = (($assetmodel->category) ? e($assetmodel->category->name) : '').': '.(($assetmodel->manufacturer) ? e($assetmodel->manufacturer->name) : '').' '.$assetmodel->present()->modelName;
$assetmodel->use_image = ($assetmodel->image) ? url('/').'/uploads/models/'.$assetmodel->image : null;
$assetmodel->use_text = '';
if ($settings->modellistCheckedValue('category')) {
$assetmodel->use_text .= (($assetmodel->category) ? e($assetmodel->category->name).' - ' : '');
}
if ($settings->modellistCheckedValue('manufacturer')) {
$assetmodel->use_text .= (($assetmodel->manufacturer) ? e($assetmodel->manufacturer->name).' ' : '');
}
$assetmodel->use_text .= e($assetmodel->name);
if (($settings->modellistCheckedValue('model_number')) && ($assetmodel->model_number!='')) {
$assetmodel->use_text .= ' (#'.e($assetmodel->model_number).')';
}
$assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? url('/').'/uploads/models/'.$assetmodel->image : null;
}
return (new SelectlistTransformer)->transformSelectlist($assetmodels);
+54 -32
View File
@@ -54,7 +54,9 @@ class AssetsController extends Controller
*/
public function index(Request $request)
{
$this->authorize('index', Asset::class);
$settings = Setting::getSettings();
$allowed_columns = [
'id',
@@ -78,30 +80,28 @@ class AssetsController extends Controller
];
$filter = array();
if ($request->has('filter')) {
$filter = json_decode($request->input('filter'));
}
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
foreach ($all_custom_fields as $field) {
$allowed_columns[]=$field->db_column_name();
}
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")->with(
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
if (count($filter) > 0) {
$assets->ByFilter($filter);
} elseif ($request->has('search')) {
$assets->TextSearch($request->input('search'));
}
// These are used by the API to query against specific ID numbers
// These are used by the API to query against specific ID numbers.
// They are also used by the individual searches on detail pages like
// locations, etc.
if ($request->has('status_id')) {
$assets->where('assets.status_id', '=', $request->input('status_id'));
}
@@ -116,12 +116,18 @@ class AssetsController extends Controller
if ($request->has('location_id')) {
$assets->where('assets.location_id', '=', $request->input('location_id'));
// dd($assets->toSql());
}
if ($request->has('supplier_id')) {
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
}
if (($request->has('assigned_to')) && ($request->has('assigned_type'))) {
$assets->where('assets.assigned_to', '=', $request->input('assigned_to'))
->where('assets.assigned_type', '=', $request->input('assigned_type'));
}
if ($request->has('company_id')) {
$assets->where('assets.company_id', '=', $request->input('company_id'));
}
@@ -140,7 +146,6 @@ class AssetsController extends Controller
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
// This is used by the sidenav, mostly
// We switched from using query scopes here because of a Laravel bug
@@ -193,11 +198,27 @@ class AssetsController extends Controller
$assets->where('assets.assigned_to', '>', '0');
break;
default:
// terrible workaround for complex-query Laravel bug in fulltext
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.archived', '=', 0);
});
if ((!$request->has('status_id')) && ($settings->show_archived_in_list!='1')) {
// terrible workaround for complex-query Laravel bug in fulltext
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id")
->where('status_alias.archived', '=', 0);
});
// If there is a status ID, don't take show_archived_in_list into consideration
} else {
$assets->join('status_labels AS status_alias',function ($join) {
$join->on('status_alias.id', "=", "assets.status_id");
});
}
}
if (count($filter) > 0) {
$assets->ByFilter($filter);
} elseif ($request->has('search')) {
$assets->TextSearch($request->input('search'));
}
@@ -229,6 +250,8 @@ class AssetsController extends Controller
break;
case 'location':
$assets->OrderLocation($order);
case 'rtd_location':
$assets->OrderRtdLocation($order);
break;
case 'status_label':
$assets->OrderStatus($order);
@@ -243,7 +266,8 @@ class AssetsController extends Controller
$assets->orderBy($column_sort, $order);
break;
}
$total = $assets->count();
$assets = $assets->skip($offset)->take($limit)->get();
return (new AssetsTransformer)->transformAssets($assets, $total);
@@ -344,7 +368,7 @@ class AssetsController extends Controller
$asset->model_id = $request->get('model_id');
$asset->order_number = $request->get('order_number');
$asset->notes = $request->get('notes');
$asset->asset_tag = $request->get('asset_tag');
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
$asset->user_id = Auth::id();
$asset->archived = '0';
$asset->physical = '1';
@@ -436,26 +460,24 @@ class AssetsController extends Controller
($request->has('company_id')) ?
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
if ($request->has('model_id')) {
if (($model = AssetModel::find($request->get('model_id'))) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
if ($request->has($field->convertUnicodeDbSlug())) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
}
// Update custom fields
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
if ($request->has($field->convertUnicodeDbSlug())) {
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
}
}
}
if ($asset->save()) {
if ($request->get('assigned_user')) {
$target = User::find(request('assigned_user'));
$location = $target->location_id;
} elseif ($request->get('assigned_asset')) {
$target = Asset::find(request('assigned_asset'));
$location = $target->location_id;
} elseif ($request->get('assigned_location')) {
$target = Location::find(request('assigned_location'));
if (($request->has('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
$location = $target->location_id;
} elseif (($request->has('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
$location = $target->location_id;
} elseif (($request->has('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
$location = $target->id;
}
@@ -535,7 +557,7 @@ class AssetsController extends Controller
$error_payload['target_type'] = 'location';
} elseif (request('checkout_to_type')=='asset') {
$target = Asset::where('id','!=',$assetId)->find(request('assigned_asset'));
$target = Asset::where('id','!=',$asset_id)->find(request('assigned_asset'));
$asset->location_id = $target->rtd_location_id;
// Override with the asset's location_id if it has one
if ($target->location_id!='') {
@@ -35,10 +35,7 @@ class CompaniesController extends Controller
'components_count',
];
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users')
->withCount('users')->withCount('assets')
->withCount('licenses')->withCount('accessories')
->withCount('consumables')->withCount('components');
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users');
if ($request->has('search')) {
$companies->TextSearch($request->input('search'));
@@ -31,6 +31,10 @@ class ComponentsController extends Controller
$components = $components->TextSearch($request->input('search'));
}
if ($request->has('company_id')) {
$components->where('company_id','=',$request->input('company_id'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
@@ -2,11 +2,14 @@
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
use Validator;
use Illuminate\Validation\Rule;
class CustomFieldsController extends Controller
{
@@ -27,6 +30,81 @@ class CustomFieldsController extends Controller
$total = count($fields);
return (new CustomFieldsTransformer)->transformCustomFields($fields, $total);
}
/**
* Shows the given field
* @author [V. Cordes] [<volker@fdatek.de>]
* @param int $id
* @since [v4.1.10]
* @return View
*/
public function show($id)
{
$this->authorize('show', CustomField::class);
if ($field = CustomField::find($id)) {
return (new CustomFieldsTransformer)->transformCustomField($field);
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/custom_fields/message.field.invalid')), 200);
}
/**
* Update the specified field
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
$this->authorize('edit', CustomField::class);
$field = CustomField::findOrFail($id);
$data = $request->all();
$validator = Validator::make($data, $field->validationRules());
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
}
$field->fill($data);
if ($field->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $field, trans('admin/custom_fields/message.field.update.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $field->getErrors()));
}
/**
* Store a newly created field.
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$this->authorize('create', CustomField::class);
$field = new CustomField;
$data = $request->all();
$validator = Validator::make($data, $field->validationRules());
if ($validator->fails()) {
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
}
$field->fill($data);
if ($field->save()) {
return response()->json(Helper::formatStandardApiResponse('success', $field, trans('admin/custom_fields/message.field.create.success')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $field->getErrors()));
}
public function postReorder(Request $request, $id)
{
$fieldset = CustomFieldset::find($id);
@@ -47,6 +125,38 @@ class CustomFieldsController extends Controller
}
public function associate(Request $request, $field_id)
{
$this->authorize('edit', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset_id = $request->input('fieldset_id');
foreach ($field->fieldset as $fieldset) {
if ($fieldset->id == $fieldset_id) {
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
}
$fieldset = CustomFieldset::findOrFail($fieldset_id);
$fieldset->fields()->attach($field->id, ["required" => ($request->input('required') == "on"), "order" => $request->input('order', $fieldset->fields->count())]);
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
public function disassociate(Request $request, $field_id)
{
$this->authorize('edit', CustomFieldset::class);
$field = CustomField::findOrFail($field_id);
$fieldset_id = $request->input('fieldset_id');
foreach ($field->fieldset as $fieldset) {
if ($fieldset->id == $fieldset_id) {
$fieldset->fields()->detach($field->id);
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
}
$fieldset = CustomFieldset::findOrFail($fieldset_id);
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
/**
* Delete a custom field.
@@ -62,7 +172,7 @@ class CustomFieldsController extends Controller
if ($field->fieldset->count() >0) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Field is in use.'));
}
$field->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/custom_fields/message.field.delete.success')));
@@ -126,7 +126,7 @@ class CustomFieldsetsController extends Controller
{
$this->authorize('delete', CustomFieldset::class);
$fieldset = CustomFieldset::findOrFail($id);
$modelsCount = $fieldset->models->count();
$fieldsCount = $fieldset->fields->count();
@@ -141,7 +141,23 @@ class CustomFieldsetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, 'Unspecified error'));
}
/**
* Return JSON containing a list of fields belonging to a fieldset.
*
* @author [V. Cordes] [<volker@fdatek.de>]
* @since [v4.1.10]
* @param $fieldsetId
* @return string JSON
*/
public function fields($id)
{
$this->authorize('view', CustomFieldset::class);
$set = CustomFieldset::findOrFail($id);
$fields = $set->fields->get();
return (new CustomFieldsTransformer)->transformCustomFields($fields, $fields->count());
}
}
@@ -22,17 +22,17 @@ class DepartmentsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Department::class);
$allowed_columns = ['id','name','image'];
$allowed_columns = ['id','name','image','users_count'];
$departments = Department::select([
'id',
'name',
'location_id',
'company_id',
'manager_id',
'created_at',
'updated_at',
'image'
'departments.id',
'departments.name',
'departments.location_id',
'departments.company_id',
'departments.manager_id',
'departments.created_at',
'departments.updated_at',
'departments.image'
])->with('users')->with('location')->with('manager')->with('company')->withCount('users');
if ($request->has('search')) {
@@ -43,7 +43,18 @@ class DepartmentsController extends Controller
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$departments->orderBy($sort, $order);
switch ($request->input('sort')) {
case 'location':
$departments->OrderLocation($order);
break;
case 'manager':
$departments->OrderManager($order);
break;
default:
$departments->orderBy($sort, $order);
break;
}
$total = $departments->count();
$departments = $departments->skip($offset)->take($limit)->get();
@@ -20,7 +20,7 @@ class GroupsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Group::class);
$allowed_columns = ['id','name','created_at'];
$allowed_columns = ['id','name','created_at', 'users_count'];
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users');
@@ -5,7 +5,9 @@ namespace App\Http\Controllers\Api;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\LicenseSeatsTransformer;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\Company;
class LicensesController extends Controller
@@ -23,9 +25,6 @@ class LicensesController extends Controller
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier')->withCount('freeSeats'));
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
if ($request->has('company_id')) {
$licenses->where('company_id','=',$request->input('company_id'));
@@ -71,6 +70,12 @@ class LicensesController extends Controller
$licenses->where('supplier_id','=',$request->input('supplier_id'));
}
if ($request->has('search')) {
$licenses = $licenses->TextSearch($request->input('search'));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -92,7 +97,8 @@ class LicensesController extends Controller
$licenses = $licenses->orderBy($sort, $order);
break;
}
$total = $licenses->count();
@@ -162,4 +168,38 @@ class LicensesController extends Controller
{
//
}
/**
* Get license seat listing
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v1.0]
* @param int $licenseId
* @return \Illuminate\Contracts\View\View
*/
public function seats(Request $request, $licenseId)
{
if ($license = License::find($licenseId)) {
$seats = LicenseSeat::where('license_id', $licenseId)->with('license', 'user', 'asset');
$offset = request('offset', 0);
$limit = request('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$total = $seats->count();
$seats = $seats->skip($offset)->take($limit)->get();
if ($seats) {
return (new LicenseSeatsTransformer)->transformLicenseSeats($seats, $total);
}
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/licenses/message.does_not_exist')), 200);
}
}
@@ -23,8 +23,8 @@ class LocationsController extends Controller
$this->authorize('view', Location::class);
$allowed_columns = [
'id','name','address','address2','city','state','country','zip','created_at',
'updated_at','parent_id', 'manager_id','image',
'assigned_assets_count','users_count','assets_count'];
'updated_at','manager_id','image',
'assigned_assets_count','users_count','assets_count','currency'];
$locations = Location::with('parent', 'manager', 'childLocations')->select([
'locations.id',
@@ -49,11 +49,25 @@ class LocationsController extends Controller
$locations = $locations->TextSearch($request->input('search'));
}
$offset = $request->input('offset', 0);
$limit = $request->input('limit', 50);
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
$locations->orderBy($sort, $order);
switch ($request->input('sort')) {
case 'parent':
$locations->OrderParent($order);
break;
case 'manager':
$locations->OrderManager($order);
break;
default:
$locations->orderBy($sort, $order);
break;
}
$total = $locations->count();
$locations = $locations->skip($offset)->take($limit)->get();
@@ -22,7 +22,7 @@ class ManufacturersController extends Controller
public function index(Request $request)
{
$this->authorize('view', Manufacturer::class);
$allowed_columns = ['id','name','url','support_url','support_email','support_phone','created_at','updated_at','image'];
$allowed_columns = ['id','name','url','support_url','support_email','support_phone','created_at','updated_at','image', 'assets_count', 'consumables_count', 'components_count', 'licenses_count'];
$manufacturers = Manufacturer::select(
array('id','name','url','support_url','support_email','support_phone','created_at','updated_at','image')
@@ -42,11 +42,15 @@ class ReportsController extends Controller
$allowed_columns = [
'id',
'created_at'
'created_at',
'target_id',
'user_id',
'action_type',
'note'
];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
$offset = request('offset', 0);
$limit = request('limit', 50);
$total = $actionlogs->count();
@@ -22,7 +22,7 @@ class StatuslabelsController extends Controller
public function index(Request $request)
{
$this->authorize('view', Statuslabel::class);
$allowed_columns = ['id','name','created_at', 'assets_count'];
$allowed_columns = ['id','name','created_at', 'assets_count','color'];
$statuslabels = Statuslabel::withCount('assets');
+12 -6
View File
@@ -58,11 +58,6 @@ class UsersController extends Controller
$users = Company::scopeCompanyables($users);
if ($request->has('search')) {
$users = $users->TextSearch($request->input('search'));
}
if (($request->has('deleted')) && ($request->input('deleted')=='true')) {
$users = $users->GetDeleted();
}
@@ -83,6 +78,10 @@ class UsersController extends Controller
$users = $users->where('users.department_id','=',$request->input('department_id'));
}
if ($request->has('search')) {
$users = $users->TextSearch($request->input('search'));
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
$offset = request('offset', 0);
$limit = request('limit', 20);
@@ -111,6 +110,8 @@ class UsersController extends Controller
$users = $users->orderBy($sort, $order);
break;
}
$total = $users->count();
$users = $users->skip($offset)->take($limit)->get();
return (new UsersTransformer)->transformUsers($users, $total);
@@ -131,6 +132,7 @@ class UsersController extends Controller
$users = User::select(
[
'users.id',
'users.username',
'users.employee_num',
'users.first_name',
'users.last_name',
@@ -159,8 +161,12 @@ class UsersController extends Controller
}
$name_str .= e($user->first_name);
if ($user->username!='') {
$name_str .= ' ('.e($user->username).')';
}
if ($user->employee_num!='') {
$name_str .= ' (#'.e($user->employee_num).')';
$name_str .= ' - #'.e($user->employee_num);
}
$user->use_text = $name_str;
@@ -63,85 +63,6 @@ class AssetMaintenancesController extends Controller
}
/**
* Generates the JSON response for asset maintenances listing view.
*
* @see AssetMaintenancesController::getIndex() method that generates view
* @author Vincent Sposato <vincent.sposato@gmail.com>
* @version v1.0
* @since [v1.8]
* @return String JSON
*/
public function getDatatable(Request $request)
{
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin');
if (Input::has('search')) {
$maintenances = $maintenances->TextSearch(e($request->input('search')));
}
$offset = request('offset', 0);
$limit = request('limit', 50);
$allowed_columns = ['id','title','asset_maintenance_time','asset_maintenance_type','cost','start_date','completion_date','notes','user_id'];
$order = Input::get('order') === 'asc' ? 'asc' : 'desc';
$sort = in_array(Input::get('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
switch ($sort) {
case 'user_id':
$maintenances = $maintenances->OrderAdmin($order);
break;
default:
$maintenances = $maintenances->orderBy($sort, $order);
break;
}
$maintenancesCount = $maintenances->count();
$maintenances = $maintenances->skip($offset)->take($limit)->get();
$rows = array();
$settings = Setting::getSettings();
foreach ($maintenances as $maintenance) {
$actions = '';
if (Gate::allows('update', Asset::class)) {
$actions .= Helper::generateDatatableButton('edit', route('maintenances.edit', $maintenance->id));
$actions .= Helper::generateDatatableButton(
'delete',
route('maintenances.destroy', $maintenance->id),
$enabled = true,
trans('admin/asset_maintenances/message.delete.confirm'),
$maintenance->title
);
}
if (($maintenance->cost) && (isset($maintenance->asset)) && ($maintenance->asset->location) && ($maintenance->asset->location->currency!='')) {
$maintenance_cost = $maintenance->asset->location->currency.$maintenance->cost;
} else {
$maintenance_cost = $settings->default_currency.$maintenance->cost;
}
$rows[] = array(
'id' => $maintenance->id,
'asset_name' => ($maintenance->asset) ? (string)link_to_route('maintenances.show', $maintenance->asset->present()->Name(), ['maintenance' => $maintenance->asset->id]) : 'Deleted Asset' ,
'title' => $maintenance->title,
'notes' => $maintenance->notes,
'supplier' => ($maintenance->supplier) ? (string)link_to_route('suppliers.show', $maintenance->supplier->name, ['maintenance'=>$maintenance->supplier->id]) : 'Deleted Supplier',
'cost' => $maintenance_cost,
'asset_maintenance_type' => e($maintenance->asset_maintenance_type),
'start_date' => $maintenance->start_date,
'asset_maintenance_time' => $maintenance->asset_maintenance_time,
'completion_date' => $maintenance->completion_date,
'user_id' => ($maintenance->admin) ? (string)link_to_route('users.show', $maintenance->admin->present()->fullName(), ['user'=>$maintenance->admin->id]) : '',
'actions' => $actions,
'company' => ($maintenance->asset->company) ? $maintenance->asset->company->name : ''
);
}
$data = array('total' => $maintenancesCount, 'rows' => $rows);
return $data;
}
/**
* Returns a form view to create a new asset maintenance.
@@ -265,9 +186,7 @@ class AssetMaintenancesController extends Controller
// Get Supplier List
// Render the view
return view('asset_maintenances/edit')
->with('asset_list', Helper::detailedAssetList())
->with('selectedAsset', null)
->with('supplier_list', Helper::suppliersList())
->with('assetMaintenanceType', $assetMaintenanceType)
->with('item', $assetMaintenance);
+10 -2
View File
@@ -40,6 +40,7 @@ class AssetModelsController extends Controller
*/
public function index()
{
$this->authorize('index', AssetModel::class);
return view('models/index');
}
@@ -52,6 +53,7 @@ class AssetModelsController extends Controller
*/
public function create()
{
$this->authorize('create', AssetModel::class);
$category_type = 'asset';
return view('models/edit')->with('category_type',$category_type)
->with('depreciation_list', Helper::depreciationList())
@@ -69,6 +71,7 @@ class AssetModelsController extends Controller
public function store(ImageUploadRequest $request)
{
$this->authorize('create', AssetModel::class);
// Create a new asset model
$model = new AssetModel;
@@ -124,7 +127,8 @@ class AssetModelsController extends Controller
*/
public function apiStore(Request $request)
{
//COPYPASTA!!!! FIXME
//COPYPASTA!!!! FIXME
$this->authorize('create', AssetModel::class);
$model = new AssetModel;
$settings=Input::all();
@@ -162,6 +166,7 @@ class AssetModelsController extends Controller
*/
public function edit($modelId = null)
{
$this->authorize('edit', AssetModel::class);
if ($item = AssetModel::find($modelId)) {
$category_type = 'asset';
$view = View::make('models/edit', compact('item','category_type'));
@@ -185,6 +190,7 @@ class AssetModelsController extends Controller
*/
public function update(ImageUploadRequest $request, $modelId = null)
{
$this->authorize('edit', AssetModel::class);
// Check if the model exists
if (is_null($model = AssetModel::find($modelId))) {
// Redirect to the models management page
@@ -255,6 +261,7 @@ class AssetModelsController extends Controller
*/
public function destroy($modelId)
{
$this->authorize('delete', AssetModel::class);
// Check if the model exists
if (is_null($model = AssetModel::find($modelId))) {
return redirect()->route('models.index')->with('error', trans('admin/models/message.not_found'));
@@ -291,7 +298,7 @@ class AssetModelsController extends Controller
*/
public function getRestore($modelId = null)
{
$this->authorize('create', AssetModel::class);
// Get user information
$model = AssetModel::withTrashed()->find($modelId);
@@ -322,6 +329,7 @@ class AssetModelsController extends Controller
*/
public function show($modelId = null)
{
$this->authorize('view', AssetModel::class);
$model = AssetModel::withTrashed()->find($modelId);
if (isset($model->id)) {
+24 -1
View File
@@ -575,6 +575,7 @@ class AssetsController extends Controller
$data['log_id'] = $logaction->id;
$data['first_name'] = get_class($target) == User::class ? $target->first_name : '';
$data['last_name'] = get_class($target) == User::class ? $target->last_name : '';
$data['item_name'] = $asset->present()->name();
$data['checkin_date'] = $logaction->created_at;
$data['item_tag'] = $asset->asset_tag;
@@ -1088,7 +1089,7 @@ class AssetsController extends Controller
\Log::debug($request->input('ids'));
if (($request->has('ids')) && (count($request->input('ids') > 0))) {
if (($request->has('ids')) && (count($request->input('ids')) > 0)) {
$assets = $request->input('ids');
if (($request->has('purchase_date'))
|| ($request->has('purchase_cost'))
@@ -1129,9 +1130,17 @@ class AssetsController extends Controller
if ($request->has('warranty_months')) {
$update_array['warranty_months'] = $request->input('warranty_months');
}
if ($request->has('rtd_location_id')) {
$update_array['rtd_location_id'] = $request->input('rtd_location_id');
if (($request->has('update_real_loc'))
&& (($request->input('update_real_loc')) == '1'))
{
$update_array['location_id'] = $request->input('rtd_location_id');
}
}
if ($request->has('status_id')) {
$update_array['status_id'] = $request->input('status_id');
}
@@ -1198,9 +1207,14 @@ class AssetsController extends Controller
$user = User::find(e(Input::get('assigned_to')));
$admin = Auth::user();
if (!$user) {
return redirect()->route('hardware/bulkcheckout')->withInput()->with('error', trans('admin/hardware/message.checkout.user_does_not_exist'));
}
if (!is_array(Input::get('selected_assets'))) {
return redirect()->route('hardware/bulkcheckout')->withInput()->with('error', trans('admin/hardware/message.checkout.no_assets_selected'));
}
$asset_ids = array_filter(Input::get('selected_assets'));
if ((Input::has('checkout_at')) && (Input::get('checkout_at')!= date("Y-m-d"))) {
@@ -1215,6 +1229,7 @@ class AssetsController extends Controller
$expected_checkin = '';
}
$errors = [];
DB::transaction(function () use ($user, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids) {
@@ -1223,6 +1238,14 @@ class AssetsController extends Controller
$this->authorize('checkout', $asset);
$error = $asset->checkOut($user, $admin, $checkout_at, $expected_checkin, e(Input::get('note')), null);
if ($user->location_id!='') {
$asset->location_id = $user->location_id;
$asset->unsetEventDispatcher();
$asset->save();
}
if ($error) {
array_merge_recursive($errors, $asset->getErrors()->toArray());
}
@@ -12,4 +12,12 @@ class RegisterController extends Controller
{
$this->middleware('guest');
}
public function showRegistrationForm() {
abort(404,'Page not found');
}
public function register() {
abort(404,'Page not found');
}
}
@@ -40,6 +40,7 @@ class CategoriesController extends Controller
public function index()
{
// Show the page
$this->authorize('view', Category::class);
return view('categories/index');
}
@@ -55,6 +56,7 @@ class CategoriesController extends Controller
public function create()
{
// Show the page
$this->authorize('create', Category::class);
$category_types= Helper::categoryTypeList();
return view('categories/edit')->with('item', new Category)
->with('category_types', $category_types);
@@ -71,6 +73,7 @@ class CategoriesController extends Controller
*/
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Category::class);
$category = new Category();
$category->name = $request->input('name');
$category->category_type = $request->input('category_type');
@@ -110,6 +113,7 @@ class CategoriesController extends Controller
*/
public function edit($categoryId = null)
{
$this->authorize('edit', Category::class);
if (is_null($item = Category::find($categoryId))) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
}
@@ -132,7 +136,7 @@ class CategoriesController extends Controller
*/
public function update(ImageUploadRequest $request, $categoryId = null)
{
// Check if the blog post exists
$this->authorize('edit', Category::class);
if (is_null($category = Category::find($categoryId))) {
// Redirect to the categories management page
return redirect()->to('admin/categories')->with('error', trans('admin/categories/message.does_not_exist'));
@@ -198,6 +202,7 @@ class CategoriesController extends Controller
*/
public function destroy($categoryId)
{
$this->authorize('delete', Category::class);
// Check if the category exists
if (is_null($category = Category::find($categoryId))) {
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found'));
@@ -231,6 +236,7 @@ class CategoriesController extends Controller
*/
public function show($id)
{
$this->authorize('view', Category::class);
if ($category = Category::find($id)) {
if ($category->category_type=='asset') {
@@ -335,7 +335,7 @@ class ComponentsController extends Controller
return redirect()->route('components.index')->with('error',
trans('admin/components/message.not_found'));
}
$this->authorize('checkin', $component_assets);
$this->authorize('checkin', $component);
return view('components/checkin', compact('component_assets','component','asset'));
}
@@ -40,6 +40,7 @@ class LocationsController extends Controller
public function index()
{
// Grab all the locations
$this->authorize('view', Location::class);
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
// Show the page
@@ -57,6 +58,7 @@ class LocationsController extends Controller
*/
public function create()
{
$this->authorize('create', Location::class);
$locations = Location::orderBy('name', 'ASC')->get();
$location_options_array = Location::getLocationHierarchy($locations);
@@ -80,6 +82,7 @@ class LocationsController extends Controller
*/
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Location::class);
$location = new Location();
$location->name = $request->input('name');
$location->parent_id = $request->input('parent_id', null);
@@ -122,6 +125,7 @@ class LocationsController extends Controller
*/
public function apiStore(Request $request)
{
$this->authorize('create', Location::class);
$new['currency']=Setting::first()->default_currency;
// create a new location instance
@@ -158,6 +162,7 @@ class LocationsController extends Controller
*/
public function edit($locationId = null)
{
$this->authorize('edit', Location::class);
// Check if the location exists
if (is_null($item = Location::find($locationId))) {
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
@@ -186,6 +191,7 @@ class LocationsController extends Controller
*/
public function update(ImageUploadRequest $request, $locationId = null)
{
$this->authorize('edit', Location::class);
// Check if the location exists
if (is_null($location = Location::find($locationId))) {
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
@@ -252,6 +258,7 @@ class LocationsController extends Controller
*/
public function destroy($locationId)
{
$this->authorize('delete', Location::class);
if (is_null($location = Location::find($locationId))) {
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.not_found'));
}
@@ -67,7 +67,7 @@ class ManufacturersController extends Controller
public function store(ImageUploadRequest $request)
{
$this->authorize('edit', Manufacturer::class);
$this->authorize('create', Manufacturer::class);
$manufacturer = new Manufacturer;
$manufacturer->name = $request->input('name');
$manufacturer->user_id = Auth::user()->id;
+9
View File
@@ -29,4 +29,13 @@ class ModalController extends Controller
function user() {
return view('modals.user');
}
function category() {
return view('modals.category');
}
function manufacturer() {
return view('modals.manufacturer');
}
}
+4 -2
View File
@@ -7,6 +7,7 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\CustomField;
use App\Models\Depreciation;
use App\Models\License;
use App\Models\Setting;
use Carbon\Carbon;
@@ -221,11 +222,12 @@ class ReportsController extends Controller
public function getDeprecationReport()
{
$depreciations = Depreciation::get();
// Grab all the assets
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'location', 'assetlog', 'company', 'model.category', 'model.depreciation')
->orderBy('created_at', 'DESC')->get();
return view('reports/depreciation', compact('assets'));
return view('reports/depreciation', compact('assets'))->with('depreciations',$depreciations);
}
/**
@@ -624,7 +626,7 @@ class ReportsController extends Controller
}
if ($request->has('category')) {
$row[] = ($asset->model->category) ? $asset->model->category->name : '';
$row[] = (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : '';
}
if ($request->has('manufacturer')) {
+28 -13
View File
@@ -67,7 +67,7 @@ class SettingsController extends Controller
$start_settings['url_config'] = url('/');
$start_settings['real_url'] = $pageURL;
// Curl the .env file to make sure it's not accessible via a browser
$ch = curl_init($protocol . $host.'/.env');
curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
@@ -150,28 +150,31 @@ class SettingsController extends Controller
$user = new User;
$user->first_name = $data['first_name']= e(Input::get('first_name'));
$user->last_name = e(Input::get('last_name'));
$user->email = $data['email'] = e(Input::get('email'));
$user->first_name = $data['first_name']= $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->email = $data['email'] = $request->input('email');
$user->activated = 1;
$permissions = array('superuser' => 1);
$user->permissions = json_encode($permissions);
$user->username = $data['username'] = e(Input::get('username'));
$user->password = bcrypt(Input::get('password'));
$data['password'] = Input::get('password');
$user->username = $data['username'] = $request->input('username');
$user->password = bcrypt($request->input('password'));
$data['password'] = $request->input('password');
$settings = new Setting;
$settings->site_name = e(Input::get('site_name'));
$settings->alert_email = e(Input::get('email'));
$settings->full_multiple_companies_support = $request->input('full_multiple_companies_support', 0);
$settings->site_name = $request->input('site_name');
$settings->alert_email = $request->input('email');
$settings->alerts_enabled = 1;
$settings->pwd_secure_min = 10;
$settings->brand = 1;
$settings->locale = 'en';
$settings->default_currency = 'USD';
$settings->locale = $request->input('locale', 'en');
$settings->default_currency = $request->input('default_currency', "USD");
$settings->user_id = 1;
$settings->email_domain = e(Input::get('email_domain'));
$settings->email_format = e(Input::get('email_format'));
$settings->email_domain = $request->input('email_domain');
$settings->email_format = $request->input('email_format');
$settings->next_auto_tag_base = 1;
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
if ((!$user->isValid()) || (!$settings->isValid())) {
@@ -311,8 +314,18 @@ class SettingsController extends Controller
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->modellist_displays = '';
if (($request->has('show_in_model_list')) && (count($request->input('show_in_model_list')) > 0))
{
$setting->modellist_displays = implode(',', $request->input('show_in_model_list'));
}
$setting->full_multiple_companies_support = $request->input('full_multiple_companies_support', '0');
$setting->load_remote = $request->input('load_remote', '0');
$setting->show_archived_in_list = $request->input('show_archived_in_list', '0');
$setting->dashboard_message = $request->input('dashboard_message');
$setting->email_domain = $request->input('email_domain');
$setting->email_format = $request->input('email_format');
$setting->username_format = $request->input('username_format');
@@ -370,6 +383,8 @@ class SettingsController extends Controller
$setting->brand = $request->input('brand', '1');
$setting->header_color = $request->input('header_color');
$setting->support_footer = $request->input('support_footer');
$setting->footer_text = $request->input('footer_text');
$setting->show_url_in_emails = $request->input('show_url_in_emails', '0');
@@ -32,12 +32,13 @@ class StatuslabelsController extends Controller
public function index()
{
$this->authorize('view', Statuslabel::class);
return view('statuslabels.index', compact('statuslabels'));
}
public function show($id)
{
$this->authorize('view', Statuslabel::class);
if ($statuslabel = Statuslabel::find($id)) {
return view('statuslabels.view')->with('statuslabel', $statuslabel);
}
@@ -55,6 +56,7 @@ class StatuslabelsController extends Controller
public function create()
{
// Show the page
$this->authorize('create', Statuslabel::class);
$item = new Statuslabel;
$use_statuslabel_type = $item->getStatuslabelType();
$statuslabel_types = Helper::statusTypeList();
@@ -72,6 +74,7 @@ class StatuslabelsController extends Controller
public function store(Request $request)
{
$this->authorize('create', Statuslabel::class);
// create a new model instance
$statusLabel = new Statuslabel();
@@ -106,6 +109,7 @@ class StatuslabelsController extends Controller
*/
public function apiStore(Request $request)
{
$this->authorize('create', Statuslabel::class);
$statuslabel = new Statuslabel();
if (!$request->has('statuslabel_types')) {
return JsonResponse::create(["error" => trans('validation.statuslabel_type')], 500);
@@ -137,6 +141,7 @@ class StatuslabelsController extends Controller
*/
public function edit($statuslabelId = null)
{
$this->authorize('update', Statuslabel::class);
// Check if the Statuslabel exists
if (is_null($item = Statuslabel::find($statuslabelId))) {
// Redirect to the blogs management page
@@ -159,6 +164,7 @@ class StatuslabelsController extends Controller
*/
public function update(Request $request, $statuslabelId = null)
{
$this->authorize('update', Statuslabel::class);
// Check if the Statuslabel exists
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
// Redirect to the blogs management page
@@ -197,6 +203,7 @@ class StatuslabelsController extends Controller
*/
public function destroy($statuslabelId)
{
$this->authorize('delete', Statuslabel::class);
// Check if the Statuslabel exists
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.not_found'));
@@ -33,6 +33,7 @@ class SuppliersController extends Controller
public function index()
{
// Grab all the suppliers
$this->authorize('view', Supplier::class);
$suppliers = Supplier::orderBy('created_at', 'DESC')->get();
// Show the page
@@ -47,6 +48,7 @@ class SuppliersController extends Controller
*/
public function create()
{
$this->authorize('create', Supplier::class);
return view('suppliers/edit')->with('item', new Supplier);
}
@@ -59,6 +61,7 @@ class SuppliersController extends Controller
*/
public function store(ImageUploadRequest $request)
{
$this->authorize('create', Supplier::class);
// Create a new supplier
$supplier = new Supplier;
// Save the location data
@@ -100,6 +103,7 @@ class SuppliersController extends Controller
*/
public function apiStore(Request $request)
{
$this->authorize('create', Supplier::class);
$supplier = new Supplier;
$supplier->name = $request->input('name');
$supplier->user_id = Auth::id();
@@ -118,6 +122,7 @@ class SuppliersController extends Controller
*/
public function edit($supplierId = null)
{
$this->authorize('edit', Supplier::class);
// Check if the supplier exists
if (is_null($item = Supplier::find($supplierId))) {
// Redirect to the supplier page
@@ -137,6 +142,7 @@ class SuppliersController extends Controller
*/
public function update($supplierId = null, ImageUploadRequest $request)
{
$this->authorize('edit', Supplier::class);
// Check if the supplier exists
if (is_null($supplier = Supplier::find($supplierId))) {
// Redirect to the supplier page
@@ -207,6 +213,7 @@ class SuppliersController extends Controller
*/
public function destroy($supplierId)
{
$this->authorize('delete', Supplier::class);
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets','licenses')->find($supplierId))) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
}
+10 -3
View File
@@ -431,7 +431,7 @@ class UsersController extends Controller
public function postBulkEdit(Request $request)
{
$this->authorize('update', User::class);
if ((!Input::has('ids')) || (count(Input::has('ids')) == 0)) {
if ((!Input::has('ids')) || (count(Input::input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
} else {
@@ -461,7 +461,7 @@ class UsersController extends Controller
public function postBulkEditSave(Request $request)
{
$this->authorize('update', User::class);
if ((!Input::has('ids')) || (count(Input::has('ids')) == 0)) {
if ((!Input::has('ids')) || (count(Input::input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
} else {
@@ -480,6 +480,11 @@ class UsersController extends Controller
if ($request->has('company_id')) {
$update_array['company_id'] = $request->input('company_id');
}
if ($request->has('locale')) {
$update_array['locale'] = $request->input('locale');
}
if ($request->has('manager_id')) {
@@ -1063,7 +1068,7 @@ class UsersController extends Controller
// Open output stream
$handle = fopen('php://output', 'w');
User::with('assets', 'accessories', 'consumables', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) {
User::with('assets', 'accessories', 'consumables', 'department', 'licenses', 'manager', 'groups', 'userloc', 'company','throttle')->orderBy('created_at', 'DESC')->chunk(500, function($users) use($handle) {
$headers=[
// strtolower to prevent Excel from trying to open it as a SYLK file
strtolower(trans('general.id')),
@@ -1075,6 +1080,7 @@ class UsersController extends Controller
trans('admin/users/table.email'),
trans('admin/users/table.manager'),
trans('admin/users/table.location'),
trans('general.department'),
trans('general.assets'),
trans('general.licenses'),
trans('general.accessories'),
@@ -1105,6 +1111,7 @@ class UsersController extends Controller
$user->email,
($user->manager) ? $user->manager->present()->fullName() : '',
($user->userloc) ? $user->userloc->name : '',
($user->department) ? $user->department->name : '',
$user->assets->count(),
$user->licenses->count(),
$user->accessories->count(),
+4 -1
View File
@@ -36,13 +36,16 @@ class AssetRequest extends Request
'checkin_date' => 'date',
'supplier_id' => 'integer|nullable',
'status' => 'integer|nullable',
'asset_tag' => 'required',
'purchase_cost' => 'numeric|nullable',
"assigned_user" => 'sometimes:required_without_all:assigned_asset,assigned_location',
"assigned_asset" => 'sometimes:required_without_all:assigned_user,assigned_location',
"assigned_location" => 'sometimes:required_without_all:assigned_user,assigned_asset',
];
$settings = \App\Models\Setting::getSettings();
$rules['asset_tag'] = ($settings->auto_increment_assets == '1') ? 'max:255' : 'required';
$model = AssetModel::find($this->request->get('model_id'));
if (($model) && ($model->fieldset)) {
+1 -1
View File
@@ -26,7 +26,7 @@ class ItemImportRequest extends FormRequest
public function rules()
{
return [
//
'import-type' => 'required',
];
}
@@ -37,7 +37,7 @@ class ActionlogsTransformer
] : null,
'created_at' => Helper::getFormattedDateObject($actionlog->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($actionlog->updated_at, 'datetime'),
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(), 'date'): null,
'next_audit_date' => ($actionlog->itemType()=='asset') ? Helper::getFormattedDateObject($actionlog->calcNextAuditDate(null, $actionlog->item), 'date'): null,
'days_to_next_audit' => $actionlog->daysUntilNextAudit($settings->audit_interval, $actionlog->item),
'action_type' => $actionlog->present()->actionType(),
'admin' => ($actionlog->user) ? [
+6 -5
View File
@@ -34,14 +34,15 @@ class AssetsTransformer
'eol' => ($asset->purchase_date!='') ? Helper::getFormattedDateObject($asset->present()->eol_date(), 'date') : null ,
'status_label' => ($asset->assetstatus) ? [
'id' => (int) $asset->assetstatus->id,
'name'=> e($asset->present()->statusText),
'status_meta' => e($asset->present()->statusMeta),
'name'=> e($asset->assetstatus->name),
'status_type'=> e($asset->assetstatus->getStatuslabelType()),
'status_meta' => e($asset->present()->statusMeta),
] : null,
'category' => ($asset->model->category) ? [
'category' => (($asset->model) && ($asset->model->category)) ? [
'id' => (int) $asset->model->category->id,
'name'=> e($asset->model->category->name)
] : null,
'manufacturer' => ($asset->model->manufacturer) ? [
'manufacturer' => (($asset->model) && ($asset->model->manufacturer)) ? [
'id' => (int) $asset->model->manufacturer->id,
'name'=> e($asset->model->manufacturer->name)
] : null,
@@ -80,7 +81,7 @@ class AssetsTransformer
];
if (($asset->model->fieldset) && (count($asset->model->fieldset->fields)> 0)) {
if (($asset->model) && ($asset->model->fieldset) && (count($asset->model->fieldset->fields)> 0)) {
$fields_array = array();
foreach ($asset->model->fieldset->fields as $field) {
@@ -38,7 +38,7 @@ class CompaniesTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Company::class) ? true : false,
'delete' => (Gate::allows('delete', Category::class) && ($company->assets_count == 0) && ($company->accessories_count == 0) && ($company->consumables_count == 0) && ($company->components_count == 0) && ($company->users_count == 0)) ? true : false,
'delete' => (Gate::allows('delete', Company::class) && ($company->assets_count == 0) && ($company->accessories_count == 0) && ($company->consumables_count == 0) && ($company->components_count == 0) && ($company->users_count == 0)) ? true : false,
];
$array += $permissions_array;
@@ -22,6 +22,7 @@ class CustomFieldsTransformer
{
$array = [
'id' => $field->id,
'name' => e($field->name),
'db_column_name' => e($field->db_column_name()),
'format' => e($field->format),
@@ -0,0 +1,62 @@
<?php
namespace App\Http\Transformers;
use App\Models\LicenseSeat;
use Gate;
use Illuminate\Database\Eloquent\Collection;
use App\Helpers\Helper;
class LicenseSeatsTransformer
{
public function transformLicenseSeats (Collection $seats, $total)
{
$array = array();
$seat_count = 0;
foreach ($seats as $seat) {
$seat_count++;
$array[] = self::transformLicenseSeat($seat, $seat_count);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformLicenseSeat (LicenseSeat $seat, $seat_count)
{
$array = [
'id' => (int) $seat->id,
'license_id' => (int) $seat->license->id,
'name' => 'Seat '.$seat_count,
'assigned_user' => ($seat->user) ? [
'id' => (int) $seat->user->id,
'name'=> e($seat->user->present()->fullName)
] : null,
'assigned_asset' => ($seat->asset) ? [
'id' => (int) $seat->asset->id,
'name'=> e($seat->asset->present()->fullName)
] : null,
'location' => ($seat->location()) ? [
'id' => (int) $seat->location()->id,
'name'=> e($seat->location()->name)
] : null,
'reassignable' => (bool) $seat->license->reassignable,
'user_can_checkout' => (($seat->assigned_to=='') && ($seat->asset_id=='')) ? true : false,
];
$permissions_array['available_actions'] = [
'checkout' => Gate::allows('checkout', License::class) ? true : false,
'checkin' => Gate::allows('checkin', License::class) ? true : false,
'clone' => Gate::allows('create', License::class) ? true : false,
'update' => Gate::allows('update', License::class) ? true : false,
'delete' => Gate::allows('delete', License::class) ? true : false,
];
$array += $permissions_array;
return $array;
}
}
@@ -34,15 +34,16 @@ class LocationsTransformer
'id' => (int) $location->id,
'name' => e($location->name),
'image' => ($location->image) ? app('locations_upload_url').e($location->image) : null,
'address' => e($location->address),
'city' => e($location->city),
'state' => e($location->state),
'country' => e($location->country),
'zip' => e($location->zip),
'address' => ($location->address) ? e($location->address) : null,
'address2' => ($location->address2) ? e($location->address2) : null,
'city' => ($location->city) ? e($location->city) : null,
'state' => ($location->state) ? e($location->state) : null,
'country' => ($location->country) ? e($location->country) : null,
'zip' => ($location->zip) ? e($location->zip) : null,
'assigned_assets_count' => (int) $location->assigned_assets_count,
'assets_count' => (int) $location->assets_count,
'users_count' => (int) $location->users_count,
'currency' => ($location->currency) ? e($location->currency) : null,
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($location->updated_at, 'datetime'),
'parent' => ($location->parent) ? [
@@ -57,7 +58,7 @@ class LocationsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Location::class) ? true : false,
'delete' => (Gate::allows('delete', Department::class) && ($location->assigned_assets_count==0) && ($location->assets_count==0) && ($location->users_count==0) && ($location->deleted_at=='')) ? true : false,
'delete' => (Gate::allows('delete', Location::class) && ($location->assigned_assets_count==0) && ($location->assets_count==0) && ($location->users_count==0) && ($location->deleted_at=='')) ? true : false,
];
$array += $permissions_array;
+2 -2
View File
@@ -25,8 +25,8 @@ class UsersTransformer
'id' => (int) $user->id,
'avatar' => e($user->present()->gravatar),
'name' => e($user->first_name).' '.($user->last_name),
'firstname' => e($user->first_name),
'lastname' => e($user->last_name),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
'employee_num' => e($user->employee_num),
'manager' => ($user->manager) ? [
+3
View File
@@ -41,6 +41,9 @@ class AccessoryImporter extends ItemImporter
$this->log("No Matching Accessory, Creating a new one");
$accessory = new Accessory();
$accessory->fill($this->sanitizeItemForStoring($accessory));
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
// $accessory->unsetEventDispatcher();
if ($accessory->save()) {
$accessory->logCreate('Imported using CSV Importer');
$this->log('Accessory ' . $this->item["name"] . ' was created');
+18 -3
View File
@@ -79,28 +79,43 @@ class AssetImporter extends ItemImporter
}
$this->item['asset_tag'] = $asset_tag;
// We need to save the user if it exists so that we can checkout to user later.
// Sanitizing the item will remove it.
if(array_key_exists('user', $this->item)) {
$user = $this->item['user'];
}
$item = $this->sanitizeItemForStoring($asset, $editingAsset);
// By default we're set this to location_id in the item.
// The location id fetched by the csv reader is actually the rtd_location_id.
// This will also set location_id, but then that will be overridden by the
// checkout method if necessary below.
if (isset($this->item["location_id"])) {
$item['rtd_location_id'] = $this->item['location_id'];
unset($item['location_id']);
}
if ($editingAsset) {
$asset->update($item);
} else {
$asset->fill($item);
}
// If we're updating, we don't want to overwrite old fields.
// If we're updating, we don't want to overwrite old fields.
if (array_key_exists('custom_fields', $this->item)) {
foreach ($this->item['custom_fields'] as $custom_field => $val) {
$asset->{$custom_field} = $val;
}
}
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
// $asset->unsetEventDispatcher();
if ($asset->save()) {
$asset->logCreate('Imported using csv importer');
$this->log('Asset ' . $this->item["name"] . ' with serial number ' . $this->item['serial'] . ' was created');
// If we have a user to checkout to, lets do so.
if(isset($user)) {
$asset->fresh()->checkOut($user);
}
return;
}
$this->logError($asset, 'Asset "' . $this->item['name'].'"');
+8 -8
View File
@@ -27,27 +27,27 @@ class ComponentImporter extends ItemImporter
public function createComponentIfNotExists()
{
$component = null;
$editingComponent = false;
$this->log("Creating Component");
$component = Component::where('name', $this->item['name']);
$component = Component::where('name', $this->item['name'])
->where('serial', $this->item['serial'])
->first();
if ($component) {
$editingComponent = true;
$this->log('A matching Component ' . $this->item["name"] . ' already exists. ');
$this->log('A matching Component ' . $this->item["name"] . ' with serial ' .$this->item['serial'].' already exists. ');
if (!$this->updating) {
$this->log("Skipping Component");
return;
}
$this->log("Updating Component");
$component = $this->components[$componentId];
$component->update($this->sanitizeItemFor($component));
$component->update($this->sanitizeItemForUpdating($component));
$component->save();
return;
}
$this->log("No matching component, creating one");
$component = new Component;
$component->fill($$this->sanitizeItemForStoring($component));
$component->fill($this->sanitizeItemForStoring($component));
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
$component->unsetEventDispatcher();
if ($component->save()) {
$component->logCreate('Imported using CSV Importer');
$this->log("Component " . $this->item["name"] . ' was created');
+2 -1
View File
@@ -40,7 +40,8 @@ class ConsumableImporter extends ItemImporter
$this->log("No matching consumable, creating one");
$consumable = new Consumable();
$consumable->fill($this->sanitizeItemForStoring($consumable));
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
$consumable->unsetEventDispatcher();
if ($consumable->save()) {
$consumable->logCreate('Imported using CSV Importer');
$this->log("Consumable " . $this->item["name"] . ' was created');
+6 -3
View File
@@ -239,12 +239,15 @@ abstract class Importer
// A number was given instead of a name
if (is_numeric($user_name)) {
$this->log('User '.$user_name.' is not a name - assume this user already exists');
$user_username = '';
// No name was given
$user = User::find($user_name);
if($user) {
return $user;
}
$this->log('User with id'.$user_name.' does not exist. Continuing through our processes');
} elseif (empty($user_name)) {
$this->log('No user data provided - skipping user creation, just adding asset');
//$user_username = '';
return false;
} else {
$user_email_array = User::generateFormattedNameFromFullName(Setting::getSettings()->email_format, $user_name);
$first_name = $user_email_array['first_name'];
+4 -4
View File
@@ -22,6 +22,9 @@ class ItemImporter extends Importer
protected function handle($row)
{
// Need to reset this between iterations or we'll have stale data.
$this->item = [];
$item_category = $this->findCsvMatch($row, "category");
if ($this->shouldUpdateField($item_category)) {
$this->item["category_id"] = $this->createOrFetchCategory($item_category);
@@ -67,10 +70,7 @@ class ItemImporter extends Importer
// NO need to call this method if we're running the user import.
// TODO: Merge these methods.
if(get_class($this) !== UserImporter::class) {
if ($this->item["user"] = $this->createOrFetchUser($row)) {
$this->item['assigned_to'] = $this->item['user']->id;
$this->item['assigned_type'] = User::class;
}
$this->item["user"] = $this->createOrFetchUser($row);
}
}
+2
View File
@@ -63,6 +63,8 @@ class LicenseImporter extends ItemImporter
} else {
$license->fill($this->sanitizeItemForStoring($license));
}
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
// $license->unsetEventDispatcher();
if ($license->save()) {
$license->logCreate('Imported using csv importer');
$this->log('License ' . $this->item["name"] . ' with serial number ' . $this->item['serial'] . ' was created');
+1 -1
View File
@@ -33,7 +33,7 @@ class UserImporter extends ItemImporter
$this->item['username'] = $this->findCsvMatch($row, 'username');
$this->item['first_name'] = $this->findCsvMatch($row, 'first_name');
$this->item['last_name'] = $this->findCsvMatch($row, 'last_name');
$this->item['email'] = $this->findCsvMatch($row, 'user_email');
$this->item['email'] = $this->findCsvMatch($row, 'email');
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
+1 -2
View File
@@ -181,8 +181,7 @@ class Accessory extends SnipeModel
})->orWhere('accessories.name', 'LIKE', '%'.$search.'%')
->orWhere('accessories.model_number', 'LIKE', '%'.$search.'%')
->orWhere('accessories.order_number', 'LIKE', '%'.$search.'%')
->orWhere('accessories.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('accessories.purchase_date', 'LIKE', '%'.$search.'%');
->orWhere('accessories.purchase_cost', '=', $search);
}
});
}
+23 -5
View File
@@ -12,6 +12,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use Log;
use Watson\Validating\ValidatingTrait;
use Illuminate\Notifications\Notifiable;
use DB;
/**
* Model for Assets.
@@ -173,6 +174,10 @@ class Asset extends Depreciable
if ($location != null) {
$this->location_id = $location;
} else {
if($target->location) {
$this->location_id = $target->location->id;
}
}
if ($this->requireAcceptance()) {
@@ -218,7 +223,7 @@ class Asset extends Depreciable
*/
public function components()
{
return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id')->withTrashed();
return $this->belongsToMany('\App\Models\Component', 'components_assets', 'asset_id', 'component_id')->withPivot('id', 'assigned_qty')->withTrashed();
}
/**
@@ -226,7 +231,9 @@ class Asset extends Depreciable
*/
public function get_depreciation()
{
return $this->model->depreciation;
if (($this->model) && ($this->model->depreciation)) {
return $this->model->depreciation;
}
}
/**
@@ -814,7 +821,7 @@ class Asset extends Depreciable
})->orWhere(function ($query) use ($search) {
$query->where('assets_users.first_name', 'LIKE', '%'.$search.'%')
->orWhere('assets_users.last_name', 'LIKE', '%'.$search.'%')
->orWhereRaw('CONCAT(assets_users.first_name," ",assets_users.last_name) LIKE ?', ["%$search%", "%$search%"])
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%", "%$search%"])
->orWhere('assets_users.username', 'LIKE', '%'.$search.'%')
->orWhere('assets_locations.name', 'LIKE', '%'.$search.'%')
->orWhere('assigned_assets.name', 'LIKE', '%'.$search.'%');
@@ -822,7 +829,6 @@ class Asset extends Depreciable
->orWhere('assets.asset_tag', 'LIKE', '%'.$search.'%')
->orWhere('assets.serial', 'LIKE', '%'.$search.'%')
->orWhere('assets.order_number', 'LIKE', '%'.$search.'%')
->orWhere('assets.purchase_date', 'LIKE', '%'.$search.'%')
->orWhere('assets.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('assets.notes', 'LIKE', '%'.$search.'%');
}
@@ -873,7 +879,7 @@ class Asset extends Depreciable
})->orWhere(function ($query) use ($search) {
$query->where('assets_users.first_name', 'LIKE', '%'.$search.'%')
->orWhere('assets_users.last_name', 'LIKE', '%'.$search.'%')
->orWhereRaw('CONCAT(assets_users.first_name," ",assets_users.last_name) LIKE ?', ["%$search%", "%$search%"])
->orWhereRaw('CONCAT('.DB::getTablePrefix().'assets_users.first_name," ",'.DB::getTablePrefix().'assets_users.last_name) LIKE ?', ["%$search%", "%$search%"])
->orWhere('assets_users.username', 'LIKE', '%'.$search.'%')
->orWhere('assets_locations.name', 'LIKE', '%'.$search.'%')
->orWhere('assigned_assets.name', 'LIKE', '%'.$search.'%');
@@ -1158,6 +1164,18 @@ class Asset extends Depreciable
return $query->leftJoin('locations as asset_locations', 'asset_locations.id', '=', 'assets.location_id')->orderBy('asset_locations.name', $order);
}
/**
* Query builder scope to order on default
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderRtdLocation($query, $order)
{
return $query->leftJoin('locations as rtd_asset_locations', 'rtd_asset_locations.id', '=', 'assets.rtd_location_id')->orderBy('rtd_asset_locations.name', $order);
}
/**
* Query builder scope to order on supplier name
+6 -6
View File
@@ -166,31 +166,31 @@ final class Company extends SnipeModel
public function users()
{
return $this->hasMany(User::class, 'users.company_id');
return $this->hasMany(User::class, 'company_id');
}
public function assets()
{
return $this->hasMany(Asset::class, 'assets.company_id');
return $this->hasMany(Asset::class, 'company_id');
}
public function licenses()
{
return $this->hasMany(License::class, 'licenses.company_id');
return $this->hasMany(License::class, 'company_id');
}
public function accessories()
{
return $this->hasMany(Accessory::class, 'accessories.company_id');
return $this->hasMany(Accessory::class, 'company_id');
}
public function consumables()
{
return $this->hasMany(Consumable::class, 'consumables.company_id');
return $this->hasMany(Consumable::class, 'company_id');
}
public function components()
{
return $this->hasMany(Component::class, 'components.company_id');
return $this->hasMany(Component::class, 'company_id');
}
/**
+2 -2
View File
@@ -55,6 +55,7 @@ class Component extends SnipeModel
'purchase_date',
'min_amt',
'qty',
'serial'
];
public function location()
@@ -143,8 +144,7 @@ class Component extends SnipeModel
})->orWhere('components.name', 'LIKE', '%'.$search.'%')
->orWhere('components.order_number', 'LIKE', '%'.$search.'%')
->orWhere('components.serial', 'LIKE', '%'.$search.'%')
->orWhere('components.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('components.purchase_date', 'LIKE', '%'.$search.'%');
->orWhere('components.purchase_cost', 'LIKE', '%'.$search.'%');
}
});
}
+1 -2
View File
@@ -186,8 +186,7 @@ class Consumable extends SnipeModel
});
})->orWhere('consumables.name', 'LIKE', '%'.$search.'%')
->orWhere('consumables.order_number', 'LIKE', '%'.$search.'%')
->orWhere('consumables.purchase_cost', 'LIKE', '%'.$search.'%')
->orWhere('consumables.purchase_date', 'LIKE', '%'.$search.'%');
->orWhere('consumables.purchase_cost', 'LIKE', '%'.$search.'%');
}
});
}
+36 -3
View File
@@ -8,6 +8,7 @@ use App\Http\Traits\UniqueUndeletedTrait;
use ForceUTF8\Encoding;
use EasySlugger\Utf8Slugger;
use Patchwork\Utf8;
use Illuminate\Validation\Rule;
class CustomField extends Model
{
@@ -29,8 +30,18 @@ class CustomField extends Model
"BOOLEAN" => "boolean",
];
public $rules = [
"name" => "required|unique:custom_fields"
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'name',
'element',
'format',
'field_values',
'field_encrypted',
'help_text'
];
// This is confusing, since it's actually the custom fields table that
@@ -160,7 +171,7 @@ class CustomField extends Model
public function getFormatAttribute($value)
{
foreach (self::$PredefinedFormats as $name => $pattern) {
if ($pattern === $value) {
if ($pattern === $value || $name === $value) {
return $name;
}
}
@@ -248,4 +259,26 @@ class CustomField extends Model
return substr($long_slug, 0, 50) . '_' . $id;
}
/**
* Get validation rules for custom fields to use with Validator
* @author [V. Cordes] [<volker@fdatek.de>]
* @param int $id
* @since [v4.1.10]
* @return Array
*/
public function validationRules()
{
return [
"name" => "required|unique:custom_fields",
"element" => [
"required",
Rule::in(['text', 'listbox'])
],
'format' => [
Rule::in(array_merge(array_keys(CustomField::$PredefinedFormats), CustomField::$PredefinedFormats))
],
'field_encrypted' => "nullable|boolean"
];
}
}
+26
View File
@@ -93,5 +93,31 @@ class Department extends SnipeModel
}
/**
* Query builder scope to order on location name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderLocation($query, $order)
{
return $query->leftJoin('locations as department_location', 'departments.location_id', '=', 'department_location.id')->orderBy('department_location.name', $order);
}
/**
* Query builder scope to order on manager name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderManager($query, $order)
{
return $query->leftJoin('users as department_user', 'departments.manager_id', '=', 'department_user.id')->orderBy('department_user.first_name', $order)->orderBy('department_user.last_name', $order);
}
}
+13
View File
@@ -34,4 +34,17 @@ class LicenseSeat extends Model implements ICompanyableChild
{
return $this->belongsTo('\App\Models\Asset', 'asset_id')->withTrashed();
}
public function location()
{
if (($this->user) && ($this->user->location)) {
return $this->user->location;
} elseif (($this->asset) && ($this->asset->location)) {
return $this->asset->location;
}
return false;
}
}
+15 -1
View File
@@ -9,6 +9,7 @@ use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use DB;
class Location extends SnipeModel
{
@@ -184,7 +185,7 @@ class Location extends SnipeModel
})
// Ugly, ugly code because Laravel sucks at self-joins
->orWhere(function ($query) use ($search) {
$query->whereRaw("parent_id IN (select id from locations where name LIKE '%".$search."%') ");
$query->whereRaw("parent_id IN (select id from ".DB::getTablePrefix()."locations where name LIKE '%".$search."%') ");
});
});
@@ -204,4 +205,17 @@ class Location extends SnipeModel
// Left join here, or it will only return results with parents
return $query->leftJoin('locations as parent_loc', 'locations.parent_id', '=', 'parent_loc.id')->orderBy('parent_loc.name', $order);
}
/**
* Query builder scope to order on manager name
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderManager($query, $order)
{
return $query->leftJoin('users as location_user', 'locations.manager_id', '=', 'location_user.id')->orderBy('location_user.first_name', $order)->orderBy('location_user.last_name', $order);
}
}
+1 -1
View File
@@ -182,7 +182,7 @@ trait Loggable
$log->location_id = null;
$log->note = $note;
$log->user_id = $user_id;
$log->logaction('created');
$log->logaction('create');
$log->save();
return $log;
}
+17 -3
View File
@@ -79,13 +79,27 @@ class Setting extends Model
public static function getDefaultEula()
{
$Parsedown = new \Parsedown();
if (Setting::getSettings()->default_eula_text) {
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
} else {
return null;
}
return null;
}
public function modellistCheckedValue ($element) {
// If the value is blank for some reason
if ($this->modellist_displays=='') {
return false;
}
$values = explode(',', $this->modellist_displays);
foreach ($values as $value) {
if ($value == $element) {
return true;
}
}
return false;
}
+14 -32
View File
@@ -36,7 +36,7 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
'jobtitle',
'location_id',
'password',
'phone_number',
'phone',
'username',
'first_name',
'address',
@@ -44,6 +44,8 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
'state',
'country',
'zip',
'activated',
'manager_id',
];
protected $casts = [
@@ -328,44 +330,24 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
public static function generateFormattedNameFromFullName($format = 'filastname', $users_name)
{
$name = explode(" ", $users_name);
$name = str_replace("'", '', $name);
$first_name = $name[0];
$email_last_name = '';
$email_prefix = $first_name;
list($first_name, $last_name) = explode(" ", $users_name, 2);
// If there is no last name given
if (!array_key_exists(1, $name)) {
$last_name='';
$email_last_name = $last_name;
$user_username = $first_name;
// There is a last name given
} else {
$last_name = str_replace($first_name . ' ', '', $users_name);
if ($format=='filastname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name[0].$email_last_name;
} elseif ($format=='firstname.lastname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name.'.'.$email_last_name;
} elseif ($format=='firstname') {
$email_last_name.=str_replace(' ', '', $last_name);
$email_prefix = $first_name;
}
// Assume filastname by default
$username = str_slug(substr($first_name, 0, 1).$last_name);
if ($format=='firstname.lastname') {
$username = str_slug($first_name).'.'.str_slug($last_name);
} elseif ($format=='firstname_lastname') {
$username = str_slug($first_name).'_'.str_slug($last_name);
} elseif ($format=='firstname') {
$username = str_slug($first_name);
}
$user_username = $email_prefix;
$user['first_name'] = $first_name;
$user['last_name'] = $last_name;
$user['username'] = strtolower($user_username);
$user['username'] = strtolower($username);
return $user;
+1 -7
View File
@@ -42,13 +42,7 @@ class AssetObserver
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
} else {
\Log::debug('Something else happened');
\Log::debug($asset->getOriginal()['assigned_to'].' == '.$asset->getAttributes()['assigned_to']);
\Log::debug($asset->getOriginal()['next_audit_date'].' == '.$asset->getAttributes()['next_audit_date']);
\Log::debug($asset->getOriginal()['last_checkout'].' == '.$asset->getAttributes()['last_checkout']);
}
}
}
+13
View File
@@ -0,0 +1,13 @@
<?php
namespace App\Policies;
use App\Policies\SnipePermissionsPolicy;
class CompanyPolicy extends SnipePermissionsPolicy
{
protected function columnName()
{
return 'companies';
}
}
+1 -1
View File
@@ -58,7 +58,7 @@ class ActionlogPresenter extends Presenter
public function actionType() {
return strtolower(trans('general.'.str_replace(' ', '_', $this->action_type)));
return mb_strtolower(trans('general.'.str_replace(' ', '_', $this->action_type)));
}
+1 -1
View File
@@ -47,7 +47,7 @@ class AssetModelPresenter extends Presenter
{
$name = '';
if ($this->model->manufacturer) {
$name .= $this->model->manufacturer->name;
$name .= $this->model->manufacturer->name.' ';
}
$name .= $this->name;
+57 -10
View File
@@ -113,7 +113,14 @@ class AssetPresenter extends Presenter
"title" => trans('admin/hardware/table.location'),
"visible" => true,
"formatter" => "deployedLocationFormatter"
], [
], [
"field" => "rtd_location",
"searchable" => true,
"sortable" => true,
"title" => trans('admin/hardware/form.default_location'),
"visible" => false,
"formatter" => "deployedLocationFormatter"
], [
"field" => "manufacturer",
"searchable" => true,
"sortable" => true,
@@ -165,7 +172,7 @@ class AssetPresenter extends Presenter
"searchable" => false,
"sortable" => false,
"visible" => false,
"title" => 'Warranty Expires',
"title" => trans('admin/hardware/form.warranty_expires'),
"formatter" => "dateDisplayFormatter"
],[
"field" => "notes",
@@ -173,6 +180,7 @@ class AssetPresenter extends Presenter
"sortable" => true,
"visible" => false,
"title" => trans('general.notes'),
], [
"field" => "created_at",
"searchable" => false,
@@ -246,11 +254,11 @@ class AssetPresenter extends Presenter
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => 'Checkin/Checkout',
"title" => trans('general.checkin').'/'.trans('general.checkout'),
"visible" => true,
"formatter" => "hardwareInOutFormatter",
];
$layout[] = [
"field" => "actions",
"searchable" => false,
@@ -263,7 +271,7 @@ class AssetPresenter extends Presenter
return json_encode($layout);
}
/**
* Generate html link to this items name.
@@ -325,15 +333,14 @@ class AssetPresenter extends Presenter
**/
public function name()
{
if (empty($this->model->name)) {
if (isset($this->model->model)) {
return $this->model->model->name.' ('.$this->model->asset_tag.')';
}
return $this->model->asset_tag;
} else {
return $this->model->name . ' (' . $this->model->asset_tag . ')';
}
return $this->model->name . ' (' . $this->model->asset_tag . ')';
}
@@ -399,7 +406,7 @@ class AssetPresenter extends Presenter
public function statusMeta()
{
if ($this->model->assigned) {
return strtolower(trans('general.deployed'));
return 'deployed';
}
return $this->model->assetstatus->getStatuslabelType();
}
@@ -417,6 +424,47 @@ class AssetPresenter extends Presenter
return $this->model->assetstatus->name;
}
/**
* @return string
* This handles the status label "meta" status of "deployed" if
* it's assigned. Results look like:
*
* (if assigned and the status label is "Ready to Deploy"):
* (Deployed)
*
* (f assigned and status label is not "Ready to Deploy":)
* Deployed (Another Status Label)
*
* (if not deployed:)
* Another Status Label
*/
public function fullStatusText() {
// Make sure the status is valid
if ($this->assetstatus) {
// If the status is assigned to someone or something...
if ($this->model->assigned) {
// If it's assigned and not set to the default "ready to deploy" status
if ($this->assetstatus->name != trans('general.ready_to_deploy')) {
return trans('general.deployed'). ' (' . $this->model->assetstatus->name.')';
}
// If it's assigned to the default "ready to deploy" status, just
// say it's deployed - otherwise it's confusing to have a status that is
// both "ready to deploy" and deployed at the same time.
return trans('general.deployed');
}
// Return just the status name
return $this->model->assetstatus->name;
}
// This status doesn't seem valid - either data has been manually edited or
// the status label was deleted.
return 'Invalid status';
}
/**
* Date the warantee expires.
* @return false|string
@@ -442,4 +490,3 @@ class AssetPresenter extends Presenter
return '<i class="fa fa-barcode"></i>';
}
}
+1 -1
View File
@@ -114,7 +114,7 @@ class ComponentPresenter extends Presenter
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => 'Checkin/Checkout',
"title" => trans('general.checkin').'/'.trans('general.checkout'),
"visible" => true,
"formatter" => "componentsInOutFormatter",
];
+55 -1
View File
@@ -117,6 +117,7 @@ class LicensePresenter extends Presenter
"sortable" => true,
"visible" => false,
"title" => trans('general.notes'),
"formatter" => "notesFormatter"
]
];
@@ -125,7 +126,7 @@ class LicensePresenter extends Presenter
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => 'Checkin/Checkout',
"title" => trans('general.checkin').'/'.trans('general.checkout'),
"visible" => true,
"formatter" => "licensesInOutFormatter",
];
@@ -144,6 +145,59 @@ class LicensePresenter extends Presenter
}
/**
* Json Column Layout for bootstrap table
* @return string
*/
public static function dataTableLayoutSeats()
{
$layout = [
[
"field" => "name",
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => trans('admin/licenses/general.seat'),
"visible" => true,
], [
"field" => "assigned_user",
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => trans('admin/licenses/general.user'),
"visible" => true,
"formatter" => "usersLinkObjFormatter"
], [
"field" => "assigned_asset",
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => trans('admin/licenses/form.asset'),
"visible" => true,
"formatter" => "hardwareLinkObjFormatter"
], [
"field" => "location",
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => trans('general.location'),
"visible" => true,
"formatter" => "locationsLinkObjFormatter"
], [
"field" => "checkincheckout",
"searchable" => false,
"sortable" => false,
"switchable" => true,
"title" => trans('general.checkin').'/'.trans('general.checkout'),
"visible" => true,
"formatter" => "licenseSeatInOutFormatter"
]
];
return json_encode($layout);
}
/**
* Link to this licenses Name
* @return string
+150
View File
@@ -11,6 +11,156 @@ use App\Helpers\Helper;
class LocationPresenter extends Presenter
{
/**
* Json Column Layout for bootstrap table
* @return string
*/
public static function dataTableLayout()
{
$layout = [
[
"field" => "id",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('general.id'),
"visible" => false
],
[
"field" => "name",
"searchable" => true,
"sortable" => true,
"title" => trans('admin/locations/table.name'),
"visible" => true,
"formatter" => "locationsLinkFormatter"
],
[
"field" => "image",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('general.image'),
"visible" => true,
"formatter" => "imageFormatter"
],
[
"field" => "parent",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.parent'),
"visible" => true,
"formatter" => "locationsLinkObjFormatter"
],
[
"field" => "assets_count",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.assets_rtd'),
"visible" => true,
],
[
"field" => "assigned_assets_count",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.assets_checkedout'),
"visible" => true,
],
[
"field" => "users_count",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('general.people'),
"visible" => true,
],
[
"field" => "currency",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('general.currency'),
"visible" => true,
],
[
"field" => "address",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.address'),
"visible" => true,
],
[
"field" => "city",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.city'),
"visible" => true,
],
[
"field" => "state",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.state'),
"visible" => true,
],
[
"field" => "zip",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.zip'),
"visible" => false,
],
[
"field" => "country",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/locations/table.country'),
"visible" => false,
],[
"field" => "manager",
"searchable" => false,
"sortable" => true,
"switchable" => true,
"title" => trans('admin/users/table.manager'),
"visible" => false,
"formatter" => 'usersLinkObjFormatter'
],
[
"field" => "created_at",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('general.created_at'),
"visible" => false,
'formatter' => 'dateDisplayFormatter'
],
[
"field" => "actions",
"searchable" => false,
"sortable" => false,
"switchable" => false,
"title" => trans('table.actions'),
"visible" => true,
"formatter" => "locationsActionsFormatter",
]
];
return json_encode($layout);
}
/**
* Link to this locations name
* @return string
+6 -5
View File
@@ -69,7 +69,8 @@ class ManufacturerPresenter extends Presenter
"sortable" => true,
"switchable" => true,
"title" => trans('admin/manufacturers/table.support_phone'),
"visible" => true
"visible" => true,
"formatter" => "phoneFormatter"
],
[
@@ -85,7 +86,7 @@ class ManufacturerPresenter extends Presenter
[
"field" => "assets_count",
"searchable" => false,
"sortable" => false,
"sortable" => true,
"switchable" => true,
"title" => ' <span class="hidden-md hidden-lg">Assets</span>'
.'<span class="hidden-xs"><i class="fa fa-barcode fa-lg"></i></span>',
@@ -94,7 +95,7 @@ class ManufacturerPresenter extends Presenter
[
"field" => "licenses_count",
"searchable" => false,
"sortable" => false,
"sortable" => true,
"switchable" => true,
"title" => ' <span class="hidden-md hidden-lg">Licenses</span>'
.'<span class="hidden-xs"><i class="fa fa-floppy-o fa-lg"></i></span>',
@@ -103,7 +104,7 @@ class ManufacturerPresenter extends Presenter
[
"field" => "consumables_count",
"searchable" => false,
"sortable" => false,
"sortable" => true,
"switchable" => true,
"title" => ' <span class="hidden-md hidden-lg">Consumables</span>'
.'<span class="hidden-xs"><i class="fa fa-tint fa-lg"></i></span>',
@@ -112,7 +113,7 @@ class ManufacturerPresenter extends Presenter
[
"field" => "accessories_count",
"searchable" => false,
"sortable" => false,
"sortable" => true,
"switchable" => true,
"title" => ' <span class="hidden-md hidden-lg">Accessories</span>'
.'<span class="hidden-xs"><i class="fa fa-keyboard-o fa-lg"></i></span>',
+1
View File
@@ -85,6 +85,7 @@ class UserPresenter extends Presenter
"switchable" => true,
"title" => trans('admin/users/table.phone'),
"visible" => true,
"formatter" => "phoneFormatter",
],
[
"field" => "address",
+4
View File
@@ -15,6 +15,7 @@ use App\Models\Location;
use App\Models\Statuslabel;
use App\Models\Supplier;
use App\Models\Manufacturer;
use App\Models\Company;
use App\Models\User;
use App\Policies\AccessoryPolicy;
use App\Policies\AssetModelPolicy;
@@ -30,6 +31,7 @@ use App\Policies\StatuslabelPolicy;
use App\Policies\SupplierPolicy;
use App\Policies\UserPolicy;
use App\Policies\ManufacturerPolicy;
use App\Policies\CompanyPolicy;
use Carbon\Carbon;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Gate;
@@ -59,6 +61,7 @@ class AuthServiceProvider extends ServiceProvider
Supplier::class => SupplierPolicy::class,
User::class => UserPolicy::class,
Manufacturer::class => ManufacturerPolicy::class,
Company::class => CompanyPolicy::class,
];
/**
@@ -132,6 +135,7 @@ class AuthServiceProvider extends ServiceProvider
|| $user->can('view', \App\Models\Location::class)
|| $user->can('view', \App\Models\Company::class)
|| $user->can('view', \App\Models\Manufacturer::class)
|| $user->can('view', \App\Models\Company::class)
|| $user->can('view', \App\Models\Depreciation::class);
});
}
+1 -1
View File
@@ -30,7 +30,7 @@
"predis/predis": "^1.1",
"rollbar/rollbar-laravel": "^2.2",
"schuppo/password-strength": "~1.5",
"spatie/laravel-backup": "^3.0.0",
"spatie/laravel-backup": "3.11.0",
"tecnickcom/tc-lib-barcode": "^1.15",
"tightenco/ziggy": "^0.4.1",
"unicodeveloper/laravel-password": "^1.0",
Generated
+194 -190
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -75,9 +75,9 @@ return [
'dump_command_timeout' => 60 * 5, // 5 minute timeout
'dump_using_single_transaction' => true, // perform dump using a single transaction
'options' => (env('DB_SSL')) ? [
PDO::MYSQL_ATTR_SSL_KEY => env('DB_SSL_KEY'), // /path/to/key.pem
PDO::MYSQL_ATTR_SSL_CERT => env('DB_SSL_CERT'), // /path/to/cert.pem
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA'), // /path/to/ca.pem
PDO::MYSQL_ATTR_SSL_KEY => env('DB_SSL_KEY_PATH'), // /path/to/key.pem
PDO::MYSQL_ATTR_SSL_CERT => env('DB_SSL_CERT_PATH'), // /path/to/cert.pem
PDO::MYSQL_ATTR_SSL_CA => env('DB_SSL_CA_PATH'), // /path/to/ca.pem
PDO::MYSQL_ATTR_SSL_CIPHER => env('DB_SSL_CIPHER')
] : []
],
+27
View File
@@ -521,6 +521,33 @@ return array(
),
),
'Companies' => array(
array(
'permission' => 'companies.view',
'label' => 'View ',
'note' => '',
'display' => true,
),
array(
'permission' => 'companies.create',
'label' => 'Create ',
'note' => '',
'display' => true,
),
array(
'permission' => 'companies.edit',
'label' => 'Edit ',
'note' => '',
'display' => true,
),
array(
'permission' => 'companies.delete',
'label' => 'Delete ',
'note' => '',
'display' => true,
),
),
+5 -5
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v4.1.8',
'full_app_version' => 'v4.1.8-pre - build 3106-geb827cd',
'build_version' => '3106',
'app_version' => 'v4.1.13',
'full_app_version' => 'v4.1.13 - build 3374-gcccd75f',
'build_version' => '3374',
'prerelease_version' => '',
'hash_version' => 'geb827cd',
'full_hash' => 'v4.1.7-69-geb827cd',
'hash_version' => 'gcccd75f',
'full_hash' => 'v4.1.12-7-gcccd75f',
'branch' => 'master',
);
@@ -12,9 +12,11 @@ class AddRememberTokenToUsersTable extends Migration
*/
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->text('remember_token')->nullable()->default(NULL);
});
if (!Schema::hasColumn('users', 'remember_token')) {
Schema::table('users', function (Blueprint $table) {
$table->text('remember_token')->nullable()->default(null);
});
}
}
/**
@@ -25,7 +27,7 @@ class AddRememberTokenToUsersTable extends Migration
public function down()
{
Schema::table('users', function (Blueprint $table) {
//
$table->dropColumn('remember_token');
});
}
}
@@ -32,6 +32,6 @@ class CreatePasswordResetsTable extends Migration
*/
public function down()
{
//
Schema::dropIfExists('password_resets');
}
}
@@ -57,7 +57,6 @@ class MigrateAssetLogToActionLog extends Migration
$a->deleted_at = $log->deleted_at;
$a->note = $log->note;
$a->expected_checkin = $log->expected_checkin;
$a->thread_id = $log->thread_id;
$a->accepted_id = $log->accepted_id;
$a->filename = $log->filename;
@@ -52,10 +52,12 @@ class FixUtf8CustomFieldColumnNames extends Migration
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
$platform->registerDoctrineTypeMapping('enum', 'string');
Schema::table('custom_fields', function ($table) {
$table->string('db_column')->nullable();
$table->text('help_text')->nullable();
});
if (!Schema::hasColumn('custom_fields', 'db_column')) {
Schema::table('custom_fields', function ($table) {
$table->string('db_column')->nullable();
$table->text('help_text')->nullable();
});
}
foreach(CustomField::all() as $field) {
@@ -3,8 +3,7 @@
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Models\Actionlog;
use App\Models\Asset;
class NormalizeAssetLastAuditDate extends Migration
{
@@ -16,23 +15,14 @@ class NormalizeAssetLastAuditDate extends Migration
public function up()
{
Schema::table('assets', function (Blueprint $table) {
$table->datetime('last_audit_date')->after('assigned_type')->nullable()->default(null);
});
// Grab the latest info from the Actionlog table where the action is 'audit'
$audits = Actionlog::selectRaw('MAX(created_at) AS created_at, item_id')->where('action_type', 'audit')->where('item_type', Asset::class)->groupBy('item_id')->orderBy('created_at', 'desc')->get();
if ($audits) {
foreach ($audits as $audit) {
$assets = Asset::where('id', $audit->item_id)->first();
$assets->last_audit_date = $audit->created_at;
$assets->unsetEventDispatcher();
$assets->save();
}
if (!Schema::hasColumn('assets', 'last_audit_date')) {
Schema::table('assets', function (Blueprint $table) {
$table->datetime('last_audit_date')->after('assigned_type')->nullable()->default(null);
});
}
}
/**
@@ -42,8 +32,10 @@ class NormalizeAssetLastAuditDate extends Migration
*/
public function down()
{
Schema::table('assets', function (Blueprint $table) {
$table->dropColumn('last_audit_date');
});
if (Schema::hasColumn('assets', 'last_audit_date')) {
Schema::table('assets', function (Blueprint $table) {
$table->dropColumn('last_audit_date');
});
}
}
}
@@ -0,0 +1,52 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Models\Actionlog;
use App\Models\Asset;
class ReNormalizeLastAudit extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
if (Schema::hasColumn('assets', 'last_audit_date')) {
// Grab the latest info from the Actionlog table where the action is 'audit'
$audits = Actionlog::selectRaw('MAX(created_at) AS created_at, item_id')
->where('action_type', 'audit')
->where('item_type', Asset::class)
->groupBy('item_id')
->orderBy('created_at', 'desc')
->get();
if ($audits) {
foreach ($audits as $audit) {
$asset = Asset::where('id', $audit->item_id)->withTrashed()->first();
if ($asset) {
$asset->last_audit_date = $audit->created_at;
$asset->unsetEventDispatcher();
$asset->save();
}
}
}
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddArchivedInListSetting extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('show_archived_in_list')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('show_archived_in_list');
});
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddDashboardMessageToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->text('dashboard_message')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('dashboard_message');
});
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddFooterSettingsToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->char('support_footer', 5)->nullable()->default('on');
$table->text('footer_text')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('support_footer');
$table->dropColumn('footer_text');
});
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddModellistPreferenc extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->char('modellist_displays')->nullable()->default('image,category,manufacturer,model_number');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('modellist_displays');
});
}
}
+1
View File
@@ -44,6 +44,7 @@ class AssetSeeder extends Seeder
unlink($del_file); // delete file
}
DB::table('checkout_requests')->truncate();
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ else
fi
# create data directories
for dir in 'data/private_uploads' 'data/uploads' 'data/uploads/avatars' 'data/uploads/barcodes' 'data/uploads/models' 'data/uploads/suppliers' 'dumps'; do
for dir in 'data/private_uploads' 'data/uploads' 'data/uploads/avatars' 'data/uploads/barcodes' 'data/uploads/categories' 'data/uploads/companies' 'data/uploads/departments' 'data/uploads/locations' 'data/uploads/manufacturers' 'data/uploads/models' 'data/uploads/suppliers' 'dumps'; do
mkdir -p "/var/lib/snipeit/$dir"
done
+2 -1
View File
@@ -14,9 +14,10 @@
"babel-preset-latest": "^6.24.1",
"cross-env": "^5.0.5",
"jquery": "^3.1.1",
"laravel-mix": "1.4.3",
"laravel-mix": "1.7",
"lodash": "^4.17.4",
"vue": "2.4.4",
"vue-loader": "^13.6.1",
"vue-template-compiler": "2.4.4"
},
"dependencies": {
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
+1 -6
View File
@@ -1,7 +1,2 @@
/*! @source http://purl.eligrey.com/github/FileSaver.js/blob/master/FileSaver.js */
var saveAs=saveAs||"undefined"!==typeof navigator&&navigator.msSaveOrOpenBlob&&navigator.msSaveOrOpenBlob.bind(navigator)||function(a){"use strict";if("undefined"===typeof navigator||!/MSIE [1-9]\./.test(navigator.userAgent)){var k=a.document,n=k.createElementNS("http://www.w3.org/1999/xhtml","a"),w="download"in n,x=function(c){var e=k.createEvent("MouseEvents");e.initMouseEvent("click",!0,!1,a,0,0,0,0,0,!1,!1,!1,!1,0,null);c.dispatchEvent(e)},q=a.webkitRequestFileSystem,u=a.requestFileSystem||q||a.mozRequestFileSystem,
y=function(c){(a.setImmediate||a.setTimeout)(function(){throw c;},0)},r=0,s=function(c){var e=function(){"string"===typeof c?(a.URL||a.webkitURL||a).revokeObjectURL(c):c.remove()};a.chrome?e():setTimeout(e,500)},t=function(c,a,d){a=[].concat(a);for(var b=a.length;b--;){var l=c["on"+a[b]];if("function"===typeof l)try{l.call(c,d||c)}catch(f){y(f)}}},m=function(c,e){var d=this,b=c.type,l=!1,f,p,k=function(){t(d,["writestart","progress","write","writeend"])},g=function(){if(l||!f)f=(a.URL||a.webkitURL||
a).createObjectURL(c);p?p.location.href=f:void 0==a.open(f,"_blank")&&"undefined"!==typeof safari&&(a.location.href=f);d.readyState=d.DONE;k();s(f)},h=function(a){return function(){if(d.readyState!==d.DONE)return a.apply(this,arguments)}},m={create:!0,exclusive:!1},v;d.readyState=d.INIT;e||(e="download");if(w)f=(a.URL||a.webkitURL||a).createObjectURL(c),n.href=f,n.download=e,x(n),d.readyState=d.DONE,k(),s(f);else{a.chrome&&b&&"application/octet-stream"!==b&&(v=c.slice||c.webkitSlice,c=v.call(c,0,
c.size,"application/octet-stream"),l=!0);q&&"download"!==e&&(e+=".download");if("application/octet-stream"===b||q)p=a;u?(r+=c.size,u(a.TEMPORARY,r,h(function(a){a.root.getDirectory("saved",m,h(function(a){var b=function(){a.getFile(e,m,h(function(a){a.createWriter(h(function(b){b.onwriteend=function(b){p.location.href=a.toURL();d.readyState=d.DONE;t(d,"writeend",b);s(a)};b.onerror=function(){var a=b.error;a.code!==a.ABORT_ERR&&g()};["writestart","progress","write","abort"].forEach(function(a){b["on"+
a]=d["on"+a]});b.write(c);d.abort=function(){b.abort();d.readyState=d.DONE};d.readyState=d.WRITING}),g)}),g)};a.getFile(e,{create:!1},h(function(a){a.remove();b()}),h(function(a){a.code===a.NOT_FOUND_ERR?b():g()}))}),g)}),g)):g()}},b=m.prototype;b.abort=function(){this.readyState=this.DONE;t(this,"abort")};b.readyState=b.INIT=0;b.WRITING=1;b.DONE=2;b.error=b.onwritestart=b.onprogress=b.onwrite=b.onabort=b.onerror=b.onwriteend=null;return function(a,b){return new m(a,b)}}}("undefined"!==typeof self&&
self||"undefined"!==typeof window&&window||this.content);"undefined"!==typeof module&&null!==module?module.exports=saveAs:"undefined"!==typeof define&&null!==define&&null!=define.amd&&define([],function(){return saveAs});
var saveAs=saveAs||function(e){"use strict";if(typeof e==="undefined"||typeof navigator!=="undefined"&&/MSIE [1-9]\./.test(navigator.userAgent)){return}var t=e.document,n=function(){return e.URL||e.webkitURL||e},r=t.createElementNS("http://www.w3.org/1999/xhtml","a"),o="download"in r,a=function(e){var t=new MouseEvent("click");e.dispatchEvent(t)},i=/constructor/i.test(e.HTMLElement)||e.safari,f=/CriOS\/[\d]+/.test(navigator.userAgent),u=function(t){(e.setImmediate||e.setTimeout)(function(){throw t},0)},s="application/octet-stream",d=1e3*40,c=function(e){var t=function(){if(typeof e==="string"){n().revokeObjectURL(e)}else{e.remove()}};setTimeout(t,d)},l=function(e,t,n){t=[].concat(t);var r=t.length;while(r--){var o=e["on"+t[r]];if(typeof o==="function"){try{o.call(e,n||e)}catch(a){u(a)}}}},p=function(e){if(/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(e.type)){return new Blob([String.fromCharCode(65279),e],{type:e.type})}return e},v=function(t,u,d){if(!d){t=p(t)}var v=this,w=t.type,m=w===s,y,h=function(){l(v,"writestart progress write writeend".split(" "))},S=function(){if((f||m&&i)&&e.FileReader){var r=new FileReader;r.onloadend=function(){var t=f?r.result:r.result.replace(/^data:[^;]*;/,"data:attachment/file;");var n=e.open(t,"_blank");if(!n)e.location.href=t;t=undefined;v.readyState=v.DONE;h()};r.readAsDataURL(t);v.readyState=v.INIT;return}if(!y){y=n().createObjectURL(t)}if(m){e.location.href=y}else{var o=e.open(y,"_blank");if(!o){e.location.href=y}}v.readyState=v.DONE;h();c(y)};v.readyState=v.INIT;if(o){y=n().createObjectURL(t);setTimeout(function(){r.href=y;r.download=u;a(r);h();c(y);v.readyState=v.DONE});return}S()},w=v.prototype,m=function(e,t,n){return new v(e,t||e.name||"download",n)};if(typeof navigator!=="undefined"&&navigator.msSaveOrOpenBlob){return function(e,t,n){t=t||e.name||"download";if(!n){e=p(e)}return navigator.msSaveOrOpenBlob(e,t)}}w.abort=function(){};w.readyState=w.INIT=0;w.WRITING=1;w.DONE=2;w.error=w.onwritestart=w.onprogress=w.onwrite=w.onabort=w.onerror=w.onwriteend=null;return m}(typeof self!=="undefined"&&self||typeof window!=="undefined"&&window||this.content);if(typeof module!=="undefined"&&module.exports){module.exports.saveAs=saveAs}else if(typeof define!=="undefined"&&define!==null&&define.amd!==null){define("FileSaver.js",function(){return saveAs})}
+775 -375
View File
File diff suppressed because it is too large Load Diff

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