Compare commits

...

125 Commits

Author SHA1 Message Date
snipe e20338ff9e Merge branch 'develop' 2018-07-09 22:38:04 -07:00
snipe 78530ae123 Fix tests 2018-07-09 21:57:45 -07:00
snipe 52d605d13e Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-07-09 19:21:23 -07:00
snipe 0182615e7e Bumped version 2018-07-09 19:18:38 -07:00
snipe fad84d4437 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-07-09 19:07:49 -07:00
snipe c162e9a4de Bumped hash 2018-07-09 19:06:56 -07:00
snipe bf1e742df6 Merge branch 'develop' 2018-07-09 19:05:19 -07:00
snipe 0e88a6b268 Fixed bug in branding image upload size text 2018-07-09 19:04:18 -07:00
Till Deeke c1e870528e Fixes the label association (#5510) (#5790) 2018-07-09 14:51:17 -07:00
snipe 35fc001c58 Fixed #5742 - create_function() is deprecated 2018-07-05 20:49:01 -07:00
snipe 339263a295 Fixed #5751 - added option for unique constraint on serial 2018-07-05 19:30:36 -07:00
snipe a44bd9abe0 Disallow deleting category if there are licenses 2018-07-05 18:02:25 -07:00
snipe b850d47282 Merge branch 'develop' 2018-07-05 15:40:07 -07:00
snipe 4099c06b27 fix middleware priority: handle trusted proxies prior setup check
From @plexorama
2018-07-05 15:36:59 -07:00
snipe e559879f91 Add @plexorama as a contributor 2018-07-05 15:35:37 -07:00
snipe abb95e7872 Tweaked custom field default value layout
This still needs work. It’s ugly.
2018-07-05 15:31:27 -07:00
snipe 869de3d251 Fixed broken pagination on status labels API 2018-07-05 14:42:39 -07:00
snipe f3526eccb9 Merge branch 'features/textarea-custom-field' into develop
# Conflicts:
#	public/js/build/all.js
#	public/js/build/vue.js
#	public/js/build/vue.js.map
#	public/js/dist/all.js
#	public/mix-manifest.json
2018-07-05 12:37:07 -07:00
Daniel Meltzer 880faa83a6 Importer2 checkout (#5771)
* Importer: checkout to location, backend changes+tests.

* Import location checkout. Frontend changes.

* Allow importing of item number/model number for consumables.
2018-07-05 12:22:24 -07:00
Juan Font 311f9fcefb Implemented method to get info on the current user of the API (#5722)
* Implemented method to get info on the current user of the API

* Move userinfo method to UsersController

* Added missing files
2018-07-02 20:35:10 -07:00
snipe 8732f299e6 Added logo class for logo override in custom CSS 2018-07-02 18:47:30 -07:00
Arunas Skirius b30aac536a fixed the alignment of a couple navbar icons (#5764) 2018-07-02 18:10:25 -07:00
snipe d7dc4ae0c0 Added manager to custom report 2018-06-27 00:45:09 -07:00
snipe 5bb4c85ccb Update twitter handle 2018-06-27 00:44:54 -07:00
snipe 80dda198c5 Parse line breaks in the detail view 2018-06-21 09:44:10 -07:00
snipe 9442736518 Adds textarea as a custom field type 2018-06-21 09:35:04 -07:00
snipe 2fbad52c71 Merge branch 'develop' 2018-06-21 07:54:01 -07:00
snipe 5975c9fac7 Add @ParadoxGuitarist as a contributor 2018-06-21 07:52:24 -07:00
snipe 7b0e392ecd Add @thelamer as a contributor 2018-06-21 07:52:04 -07:00
snipe b51a10b46b Add @RichardRay as a contributor 2018-06-21 07:51:39 -07:00
snipe 6c58f59d72 Add @EarlRamirez as a contributor 2018-06-21 07:51:24 -07:00
snipe cd9caa24ad Add @SjamonDaal as a contributor 2018-06-21 07:51:13 -07:00
snipe cbb4b4d846 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-06-21 07:46:27 -07:00
snipe ea4cdadc6e Bumped version 2018-06-21 07:44:58 -07:00
snipe 6638d64d68 Merge remote-tracking branch 'origin/master' into develop 2018-06-21 07:43:32 -07:00
snipe eb412c2bcb Missed one 2018-06-21 07:43:12 -07:00
snipe fde4a59510 Bumped version 2018-06-21 07:40:37 -07:00
snipe 1ee394aa69 Added Select2 to class for dropdowns 2018-06-21 07:40:30 -07:00
snipe 707f90573c Merge branch 'thelamer-docker-fixes' into develop 2018-06-21 07:31:55 -07:00
snipe f8429ad357 Merge branch 'docker-fixes' of https://github.com/thelamer/snipe-it into thelamer-docker-fixes 2018-06-21 07:31:15 -07:00
snipe aa5003d297 Merge branch 'develop' 2018-06-21 07:21:24 -07:00
snipe e9901f5e58 Set composer timeout to 3000 2018-06-21 07:17:51 -07:00
Djamon Staal f0d04a4a57 End help text with a period consistently. (#5731) 2018-06-21 07:13:29 -07:00
Djamon Staal 32e3f748d8 Make version footer configurable. (#5730) 2018-06-21 07:12:16 -07:00
Earl Ramirez fa465a84df Added cron to list of packages (#5729) 2018-06-20 23:28:35 -07:00
Earl Ramirez 82cf1a4467 Updated SELinux label (#5728) 2018-06-20 23:28:20 -07:00
tiagom62 3bbd49dbad Don't run composer as root (#5689)
* dont run composer as root

* better naming
2018-06-20 19:59:44 -07:00
Daniel Meltzer ad21857cae Update my email address across files. (#5716) 2018-06-20 01:59:59 -07:00
Daniel Meltzer 2d18b73138 Fix #5408. (#5715)
The temporary password cannot be added to the users data until after do
any update-related logic, otherwise their password will be overwritten.
2018-06-20 01:59:04 -07:00
Richard Ray Thomas e7bc18dad4 Fixed inconsistent or incorrect comment labels (#5691)
Accessories table was labeled 'Checked out License table' likely just a duplicate of the above comment for the actual licenses table. Very minor.
2018-06-11 20:11:58 -07:00
snipe 62e4eabab0 Fixed #5693 - don’t truncate license key 2018-06-11 18:47:02 -07:00
tiagom62 d204eebab9 Ubuntu Bionic Beaver 18.04 support (#5687)
* bionic box

* bionic beaver support
2018-06-09 11:21:28 -07:00
thelamer ed5823151b in order to avoid manual user intervention of running "php artisan migrate" before installation on a clean database pulling in migration scripts on startup if needed, also ownership of keys needs to be the docker user 2018-06-07 22:29:00 -07:00
snipe 968d7d1f11 Fixed #5354 - adds dd/mm/yyyy to localization 2018-06-05 15:30:50 -07:00
snipe 086683319a Fixed #5172 - autosum on assets detail view for components tab 2018-06-02 06:21:51 -07:00
snipe e5c1f4847d Added emoji to exempt list to match current labels 2018-06-01 13:55:39 -07:00
snipe 087e114d34 Merge branch 'develop' 2018-05-31 16:34:25 -07:00
snipe 5a6b8bb856 Make default custom field value null 2018-05-31 14:21:18 -07:00
snipe 102f567cb5 Fixed typo 2018-05-31 10:55:48 -07:00
snipe 1a64879b65 Only allow remote user settings to be saved if the app is not in demo mode 2018-05-31 10:55:48 -07:00
Brady Wetherington 4a0e5e4b88 Possible fix for oauth issue in Docker 2018-05-31 01:36:51 -07:00
snipe 01857fb056 Added created_at to file upload UI, added header/footer to files modal, fixed string for actions 2018-05-29 16:38:23 -07:00
snipe 3afe4938f9 Fixed #5616 - removed duplicate call to ekkoLightbox on asset view
It’s already in the default blade
2018-05-29 16:36:42 -07:00
snipe 9e0544e735 Fixed #5617 - incorrect url to fieldset editing 2018-05-29 10:41:46 -07:00
snipe 3993c6ad6b Use custom header color in emails 2018-05-29 10:23:39 -07:00
Brian Monroe 649563457d Added notes field to acessories and consumable checkout pages. Resolves request #5607. (#5608) 2018-05-28 14:30:18 -07:00
snipe 6ec75714f0 Force default srtorage engine 2018-05-22 14:57:05 -07:00
snipe 15916e6668 Allow checkout to non-user objects even if the object requires checkout 2018-05-21 17:35:04 -07:00
snipe 76d0562716 Added last name to expected checkin notification
For non-US countries like Germany where it’s considered rude not to include last name
2018-05-21 17:34:27 -07:00
snipe 2ecc4aead7 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-05-21 15:43:48 -07:00
snipe d8210847a4 Bumped version 2018-05-21 15:43:04 -07:00
snipe ece916e12f Merge branch 'develop' 2018-05-21 15:41:40 -07:00
snipe 1a29d4f60f Check for > 0 expected assets 2018-05-21 15:41:19 -07:00
snipe 11832daf5c Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-05-21 15:17:40 -07:00
snipe 79555f5647 Bumped version 2018-05-21 15:16:56 -07:00
snipe 1868013704 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-05-21 14:59:08 -07:00
snipe 39cc13f155 Bumped version 2018-05-21 14:58:16 -07:00
snipe e636875797 Merge branch 'develop' 2018-05-21 14:56:57 -07:00
snipe 260749337e Updated languages 2018-05-21 14:54:36 -07:00
snipe 20a3b556bb Removed log 2018-05-21 14:33:27 -07:00
Tim Bishop fa0c58e42a Don't install require-dev packages. (#5549)
This is already set for a local composer install, but not a global
one. They should be consistent.
2018-05-18 16:06:05 -07:00
snipe abbb94239d Add @doekman as a contributor 2018-05-18 16:05:12 -07:00
snipe d89ef43834 Make category counters ints 2018-05-18 16:05:12 -07:00
Doeke Zanstra f84ab2beda Fixed bug #5540 (#5550)
Error message with button "Test LDAP" is empty #5540
2018-05-18 16:04:34 -07:00
snipe 86d398abda Fixed category test 2018-05-18 14:58:06 -07:00
snipe 883c65981b More test fixes 2018-05-16 20:09:18 -07:00
snipe 8eb96efa13 Merge branch 'develop' 2018-05-16 19:38:23 -07:00
snipe e9973670ea Could should not be equal to 1 2018-05-16 19:38:02 -07:00
snipe ef8d2d06df Fixes #5519 - count() for php 7.2 2018-05-16 19:35:14 -07:00
snipe 0b5bb520a7 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-05-16 19:24:31 -07:00
lea-mink 233fb23cb8 Create asset maintenance - Added orange bar for required asset to edit view (#5520)
* Added orange bar for required asset to edit view

* disable redirection to asset maintenances view

* Update - disable redirection to asset maintenances view
2018-05-16 19:23:23 -07:00
snipe fa89f45cb8 Bumped hash 2018-05-16 19:22:59 -07:00
snipe 4c656c0321 De-normalize new counters from 4.3.0 (#5547)
* Added de-norm counter migration for assets

* Renaming counter columns, since Eloquent has a magical *_count helper

* Added artisan command to sync counters (one-off)

* Update API to use de-normed fields

* Increment counters for checkin;/checkout

* Derp.

* Added request increment/decrementer

* Move increment for checkout to the Asset::checkout method

* Added “could take a while” message
2018-05-16 19:20:43 -07:00
snipe 87c6ee2035 Importer test fixes 2018-05-16 19:05:00 -07:00
snipe aab190423f Partial fix for license+category tests 2018-05-16 18:35:11 -07:00
snipe 05e3e6bda6 Added indexes for speed 2018-05-14 20:27:56 -07:00
Tim Bishop 1f299ed73e Fix padding on next page with Chrome. (#5509)
It looks like Chrome (and probably other browsers) is optimising the
next-padding div out since it has no content. This means the margin
doesn't apply. Adding the nbsp, and making sure it takes up no space
itself, is enough to make the margin do the right thing.

I also tried using padding instead of margin, but this results in an
extra page at the end of the output (there'd need to be a way to stop
page-break and next-padding appearing at the end of the document). I also
tried setting a min-height on next-padding, but this had the same issue.
2018-05-09 17:00:36 -07:00
snipe 4ba9792fbe Merge branch 'develop' 2018-05-09 15:29:59 -07:00
snipe f405511b6b Fixed #5501 - regression disallowing license files to be downloaded 2018-05-08 14:24:51 -07:00
snipe 8ad5eb3e59 Fixed #5500 - present() on correct location value 2018-05-08 09:21:43 -07:00
snipe 3df8fa99f0 Merge branch 'develop' 2018-05-08 07:37:44 -07:00
snipe cca97341e9 More flexible date range in datepicker for expected checkin filter on custom reports 2018-05-08 07:37:18 -07:00
snipe 13195d06fd Fixed #5491 - added default location filter for custom report 2018-05-08 07:34:14 -07:00
snipe 9b6e86b55c Merge branch 'develop' 2018-05-08 05:59:54 -07:00
snipe 65cf7527b0 Added model name to expected checkin reminders 2018-05-08 05:59:34 -07:00
snipe f74d50439c Merge branch 'develop' 2018-05-08 05:39:28 -07:00
snipe 28e7ca5a84 Formatting tweaks to email notifications 2018-05-08 05:39:11 -07:00
snipe 8f64da5bc7 Added admin alert on expiring notifications 2018-05-08 05:27:03 -07:00
snipe 25f537e730 Merge branch 'develop'
# Conflicts:
#	config/version.php
2018-05-08 03:49:28 -07:00
snipe 6d8af3d9c0 Bumped hash 2018-05-08 03:48:35 -07:00
snipe e56a46882d Include EULA/acceptance in license interfaces 2018-05-08 03:47:28 -07:00
snipe 0476ffecdb Removed debugging comments 2018-05-08 03:46:48 -07:00
snipe 47a0400a72 Fixed comment typo 2018-05-08 03:14:25 -07:00
snipe de3417d557 Added link to SnipeitPS powershell wrapper 2018-05-08 01:34:53 -07:00
snipe 83b546c1c5 Disable privacy policy link in footer if in demo mode 2018-05-08 01:07:15 -07:00
snipe 04709dc1df Fixed #5477 - added GDPR privacy policy link in email and webpage 2018-05-08 00:50:13 -07:00
snipe f48171dcab Add category to licenses 2018-05-08 00:14:38 -07:00
snipe 7b8362b64c Added license categories 2018-05-04 21:01:38 -07:00
snipe 188538651a Fixed slack notification error if location is not set on checkin 2018-05-04 21:01:25 -07:00
snipe a9fc7e04e9 Fixed php7.2 count issue 2018-05-04 21:00:58 -07:00
snipe 4812285512 Fixed #5482 - typo in custom fields info 2018-05-04 14:52:19 -07:00
snipe ec1fa8e90a Merge branch 'develop' 2018-05-03 08:06:58 -07:00
snipe 3a1b432234 Fixed #5472 - show_in_email for custom fields missing in edit field UI 2018-05-03 08:06:28 -07:00
snipe 98f853128a Merge branch 'develop' 2018-05-03 05:43:49 -07:00
snipe 276d2bc866 Fixed advanced search on model number
(RB:347)
2018-05-03 05:43:25 -07:00
366 changed files with 4348 additions and 932 deletions
+63
View File
@@ -911,6 +911,69 @@
"contributions": [
"code"
]
},
{
"login": "doekman",
"name": "Doeke Zanstra",
"avatar_url": "https://avatars1.githubusercontent.com/u/1086388?v=4",
"profile": "https://github.com/doekman",
"contributions": [
"code"
]
},
{
"login": "SjamonDaal",
"name": "Djamon Staal",
"avatar_url": "https://avatars1.githubusercontent.com/u/4325936?v=4",
"profile": "https://www.sdhd.nl/",
"contributions": [
"code"
]
},
{
"login": "EarlRamirez",
"name": "Earl Ramirez",
"avatar_url": "https://avatars3.githubusercontent.com/u/12306859?v=4",
"profile": "https://github.com/EarlRamirez",
"contributions": [
"code"
]
},
{
"login": "RichardRay",
"name": "Richard Ray Thomas",
"avatar_url": "https://avatars2.githubusercontent.com/u/8671456?v=4",
"profile": "https://github.com/RichardRay",
"contributions": [
"code"
]
},
{
"login": "thelamer",
"name": "Ryan Kuba",
"avatar_url": "https://avatars3.githubusercontent.com/u/1852688?v=4",
"profile": "https://www.taisun.io/",
"contributions": [
"code"
]
},
{
"login": "ParadoxGuitarist",
"name": "Brian Monroe",
"avatar_url": "https://avatars1.githubusercontent.com/u/6751928?v=4",
"profile": "https://github.com/ParadoxGuitarist",
"contributions": [
"code"
]
},
{
"login": "plexorama",
"name": "plexorama",
"avatar_url": "https://avatars1.githubusercontent.com/u/605167?v=4",
"profile": "https://github.com/plexorama",
"contributions": [
"code"
]
}
]
}
+4
View File
@@ -9,6 +9,10 @@ exemptLabels:
- :woman_technologist: ready for dev
- :moneybag: bounty
- :hand: bug
- "🔐 security"
- "👩‍💻 ready for dev"
- "💰 bounty"
- "✋ bug"
# 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
+1
View File
@@ -18,6 +18,7 @@ patch \
curl \
vim \
git \
cron \
mysql-client \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
+4 -2
View File
@@ -1,5 +1,5 @@
[![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-98-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)
[![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/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![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-105-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
@@ -57,6 +57,7 @@ Since the release of the JSON REST API, several third-party developers have been
- [Python Module](https://github.com/jbloomer/SnipeIT-PythonAPI) by [@jbloomer](https://github.com/jbloomer)
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
- [InQRy](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
@@ -82,6 +83,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<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/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") | [<img src="https://avatars3.githubusercontent.com/u/36515590?v=4" width="110px;"/><br /><sub>cepacs</sub>](https://github.com/cepacs)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Acepacs "Bug reports") [📖](https://github.com/snipe/snipe-it/commits?author=cepacs "Documentation") | [<img src="https://avatars2.githubusercontent.com/u/37537300?v=4" width="110px;"/><br /><sub>lea-mink</sub>](https://github.com/lea-mink)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lea-mink "Code") | [<img src="https://avatars0.githubusercontent.com/u/7140719?v=4" width="110px;"/><br /><sub>Hannah Tinkler</sub>](https://github.com/hannahtinkler)<br />[💻](https://github.com/snipe/snipe-it/commits?author=hannahtinkler "Code") |
| [<img src="https://avatars1.githubusercontent.com/u/1086388?v=4" width="110px;"/><br /><sub>Doeke Zanstra</sub>](https://github.com/doekman)<br />[💻](https://github.com/snipe/snipe-it/commits?author=doekman "Code") | [<img src="https://avatars1.githubusercontent.com/u/4325936?v=4" width="110px;"/><br /><sub>Djamon Staal</sub>](https://www.sdhd.nl/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=SjamonDaal "Code") | [<img src="https://avatars3.githubusercontent.com/u/12306859?v=4" width="110px;"/><br /><sub>Earl Ramirez</sub>](https://github.com/EarlRamirez)<br />[💻](https://github.com/snipe/snipe-it/commits?author=EarlRamirez "Code") | [<img src="https://avatars2.githubusercontent.com/u/8671456?v=4" width="110px;"/><br /><sub>Richard Ray Thomas</sub>](https://github.com/RichardRay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=RichardRay "Code") | [<img src="https://avatars3.githubusercontent.com/u/1852688?v=4" width="110px;"/><br /><sub>Ryan Kuba</sub>](https://www.taisun.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=thelamer "Code") | [<img src="https://avatars1.githubusercontent.com/u/6751928?v=4" width="110px;"/><br /><sub>Brian Monroe</sub>](https://github.com/ParadoxGuitarist)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ParadoxGuitarist "Code") | [<img src="https://avatars1.githubusercontent.com/u/605167?v=4" width="110px;"/><br /><sub>plexorama</sub>](https://github.com/plexorama)<br />[💻](https://github.com/snipe/snipe-it/commits?author=plexorama "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
Vendored
+8
View File
@@ -5,6 +5,14 @@ SNIPEIT_SH_URL= "https://raw.githubusercontent.com/snipe/snipe-it/master/snipeit
NETWORK_BRIDGE= "en0: Wi-Fi (AirPort)"
Vagrant.configure("2") do |config|
config.vm.define "bionic" do |bionic|
bionic.vm.box = "ubuntu/bionic64"
bionic.vm.hostname = 'bionic'
bionic.vm.network "public_network", bridge: NETWORK_BRIDGE
bionic.vm.provision :shell, :inline => "wget #{SNIPEIT_SH_URL}"
bionic.vm.provision :shell, :inline => "chmod 755 snipeit.sh"
end
config.vm.define "xenial" do |xenial|
xenial.vm.box = "ubuntu/xenial64"
xenial.vm.hostname = 'xenial'
@@ -4,8 +4,10 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\Setting;
use Illuminate\Console\Command;
use App\Notifications\ExpectedCheckinNotification;
use App\Notifications\ExpectedCheckinAdminNotification;
use Carbon\Carbon;
class SendExpectedCheckinAlerts extends Command
@@ -42,21 +44,28 @@ class SendExpectedCheckinAlerts extends Command
*/
public function fire()
{
$settings = Setting::getSettings();
$whenNotify = Carbon::now()->addDays(7);
$assets = Asset::with('assignedTo')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
$this->info($whenNotify.' is deadline');
$this->info($assets->count().' assets');
foreach ($assets as $asset) {
if ($asset->assignedTo && $asset->checkoutOutToUser()) {
$asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
//$this->info($asset);
if ($asset->assigned && $asset->checkedOutToUser()) {
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
}
}
// Send a rollup to the admin, if settings dictate
$recipient = new \App\Models\Recipients\AlertRecipient();
if (($assets) && ($assets->count() > 0) && ($settings->alert_email!='')) {
$recipient->notify(new ExpectedCheckinAdminNotification($assets));
}
@@ -0,0 +1,76 @@
<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Asset;
class SyncAssetCounters extends Command
{
/**
* The name and signature of the console command.
*
* @var string
*/
protected $signature = 'snipeit:counter-sync';
/**
* The console command description.
*
* @var string
*/
protected $description = 'Syncs checkedout, checked in, and requested counters for assets';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*
* @return mixed
*/
public function handle()
{
$start = microtime(true);
$assets = Asset::withCount('checkins', 'checkouts', 'userRequests')
->withTrashed()->get();
if ($assets) {
if ($assets->count() > 0) {
$bar = $this->output->createProgressBar($assets->count());
foreach ($assets as $asset) {
$asset->checkin_counter = (int) $asset->checkins_count;
$asset->checkout_counter = (int) $asset->checkouts_count;
$asset->requests_counter = (int) $asset->user_requests_count;
$asset->unsetEventDispatcher();
$asset->save();
$output['info'][] = 'Asset: ' . $asset->id . ' has ' . $asset->checkin_counter . ' checkins, ' . $asset->checkout_counter . ' checkouts, and ' . $asset->requests_counter . ' requests';
$bar->advance();
}
$bar->finish();
foreach ($output['info'] as $key => $output_text) {
$this->info($output_text);
}
$time_elapsed_secs = microtime(true) - $start;
$this->info('Sync executed in ' . $time_elapsed_secs . ' seconds');
} else {
$this->info('No assets to sync');
}
}
}
}
+1
View File
@@ -29,6 +29,7 @@ class Kernel extends ConsoleKernel
Commands\ResetDemoSettings::class,
Commands\SyncAssetLocations::class,
Commands\RegenerateAssetTags::class,
Commands\SyncAssetCounters::class,
];
/**
+11 -2
View File
@@ -330,7 +330,14 @@ class Helper
*/
public static function categoryTypeList()
{
$category_types = array('' => '','accessory' => 'Accessory', 'asset' => 'Asset', 'consumable' => 'Consumable','component' => 'Component');
$category_types = array(
'' => '',
'accessory' => 'Accessory',
'asset' => 'Asset',
'consumable' => 'Consumable',
'component' => 'Component',
'license' => 'License'
);
return $category_types;
}
@@ -406,7 +413,7 @@ class Helper
{
$keys = array_keys(CustomField::$PredefinedFormats);
$stuff = array_combine($keys, $keys);
return $stuff+["" => trans('admin/custom_fields/general.custom_format')];
return $stuff;
}
/**
@@ -738,6 +745,7 @@ class Helper
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) {
@@ -751,6 +759,7 @@ class Helper
$max_size = $upload_max;
}
}
return $max_size;
}
@@ -77,9 +77,9 @@ class AssetsController extends Controller
'last_audit_date',
'next_audit_date',
'warranty_months',
'checkouts_count',
'checkins_count',
'user_requests_count',
'checkout_counter',
'checkin_counter',
'requests_counter',
];
$filter = array();
@@ -95,7 +95,7 @@ class AssetsController extends Controller
$assets = Company::scopeCompanyables(Asset::select('assets.*'),"company_id","assets")
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier')->withCount('checkins', 'checkouts', 'userRequests');
'model.category', 'model.manufacturer', 'model.fieldset','supplier');
// These are used by the API to query against specific ID numbers.
@@ -21,10 +21,10 @@ class CategoriesController extends Controller
public function index(Request $request)
{
$this->authorize('view', Category::class);
$allowed_columns = ['id', 'name','category_type', 'category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count', 'image'];
$allowed_columns = ['id', 'name','category_type', 'category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count','licenses_count', 'image'];
$categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email','image'])
->withCount('assets', 'accessories', 'consumables', 'components');
->withCount('assets', 'accessories', 'consumables', 'components','licenses');
if ($request->has('search')) {
$categories = $categories->TextSearch($request->input('search'));
@@ -25,7 +25,7 @@ class LicensesController extends Controller
public function index(Request $request)
{
$this->authorize('view', License::class);
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier')->withCount('freeSeats'));
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats'));
if ($request->has('company_id')) {
@@ -64,6 +64,10 @@ class LicensesController extends Controller
$licenses->where('supplier_id','=',$request->input('supplier_id'));
}
if ($request->has('category_i')) {
$licenses->where('category_i','=',$request->input('category_i'));
}
if ($request->has('depreciation_id')) {
$licenses->where('depreciation_id','=',$request->input('depreciation_id'));
}
@@ -90,11 +94,14 @@ class LicensesController extends Controller
case 'supplier':
$licenses = $licenses->leftJoin('suppliers', 'licenses.supplier_id', '=', 'suppliers.id')->orderBy('suppliers.name', $order);
break;
case 'category':
$licenses = $licenses->leftJoin('categories', 'licenses.category_id', '=', 'categories.id')->orderBy('categories.name', $order);
break;
case 'company':
$licenses = $licenses->leftJoin('companies', 'licenses.company_id', '=', 'companies.id')->orderBy('companies.name', $order);
break;
default:
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','license_name','license_email','free_seats_count','seats'];
$allowed_columns = ['id','name','purchase_cost','expiration_date','purchase_order','order_number','notes','purchase_date','serial','company','category','license_name','license_email','free_seats_count','seats'];
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
$licenses = $licenses->orderBy($sort, $order);
break;
@@ -320,4 +320,17 @@ class UsersController extends Controller
return response()->json(['message' => 'No ID provided'], 500);
}
/**
* Get info on the current user.
*
* @author [Juan Font] [<juanfontalonso@gmail.com>]
* @since [v4.4.2]
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function getCurrentUserInfo(Request $request)
{
return response()->json($request->user());
}
}
@@ -113,7 +113,7 @@ class AssetMaintenancesController extends Controller
$assetMaintenance->notes = e($request->input('notes'));
$asset = Asset::find(e($request->input('asset_id')));
if (!Company::isCurrentUserHasAccess($asset)) {
if ((!Company::isCurrentUserHasAccess($asset)) && ($asset!=null)) {
return static::getInsufficientPermissionsRedirect();
}
@@ -166,13 +166,13 @@ class CustomFieldsController extends Controller
public function update(CustomFieldRequest $request, $id)
{
$field = CustomField::find($id);
$field->name = e($request->get("name"));
$field->element = e($request->get("element"));
$field->field_values = e($request->get("field_values"));
$field->field_encrypted = e($request->get("field_encrypted", 0));
$field->user_id = Auth::user()->id;
$field->help_text = $request->get("help_text");
$field->show_in_email = $request->get("show_in_email", 0);
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) {
$field->format = e($request->get("custom_format"));
@@ -180,7 +180,6 @@ class CustomFieldsController extends Controller
$field->format = e($request->get("format"));
}
if ($field->save()) {
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.update.success'));
}
+2 -1
View File
@@ -107,6 +107,7 @@ class LicensesController extends Controller
$license->seats = $request->input('seats');
$license->serial = $request->input('serial');
$license->supplier_id = $request->input('supplier_id');
$license->category_id = $request->input('category_id');
$license->termination_date = $request->input('termination_date');
$license->user_id = Auth::id();
@@ -182,6 +183,7 @@ class LicensesController extends Controller
$license->seats = e($request->input('seats'));
$license->manufacturer_id = $request->input('manufacturer_id');
$license->supplier_id = $request->input('supplier_id');
$license->category_id = $request->input('category_id');
if ($license->save()) {
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
@@ -420,7 +422,6 @@ class LicensesController extends Controller
$return_to = Asset::find($licenseSeat->asset_id);
}
\Log::debug($licenseSeat->assigned_to);
// Update the asset data
$licenseSeat->assigned_to = null;
$licenseSeat->asset_id = null;
+29 -7
View File
@@ -376,6 +376,7 @@ class ReportsController extends Controller
if ($request->has('rtd_location')) {
$header[] = trans('admin/hardware/form.default_location');
}
if ($request->has('rtd_location_address')) {
$header[] = trans('general.address');
$header[] = trans('general.address');
@@ -399,6 +400,10 @@ class ReportsController extends Controller
$header[] = 'Employee No.';
}
if ($request->has('manager')) {
$header[] = trans('admin/users/table.manager');
}
if ($request->has('department')) {
$header[] = trans('general.department');
}
@@ -462,6 +467,11 @@ class ReportsController extends Controller
$assets->where('assets.location_id', $request->input('by_location_id'));
}
if ($request->has('by_rtd_location_id')) {
\Log::debug('RTD location should match: '.$request->input('by_rtd_location_id'));
$assets->where('assets.rtd_location_id', $request->input('by_rtd_location_id'));
}
if ($request->has('by_supplier_id')) {
$assets->where('assets.supplier_id', $request->input('by_supplier_id'));
}
@@ -497,6 +507,10 @@ class ReportsController extends Controller
if (($request->has('created_start')) && ($request->has('created_end'))) {
$assets->whereBetween('assets.created_at', [$request->input('created_start'), $request->input('created_end')]);
}
if (($request->has('expected_checkin_start')) && ($request->has('expected_checkin_end'))) {
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
}
$assets->orderBy('assets.created_at', 'ASC')->chunk(500, function($assets) use($handle, $customfields, $request) {
@@ -558,16 +572,16 @@ class ReportsController extends Controller
}
if ($request->has('location_address')) {
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address2 : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->city : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->state : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->country : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->zip : '';
$row[] = ($asset->location) ? $asset->location->address : '';
$row[] = ($asset->location) ? $asset->location->address2 : '';
$row[] = ($asset->location) ? $asset->location->city : '';
$row[] = ($asset->location) ? $asset->location->state : '';
$row[] = ($asset->location) ? $asset->location->country : '';
$row[] = ($asset->location) ? $asset->location->zip : '';
}
if ($request->has('rtd_location')) {
$row[] = ($asset->location) ? $asset->defaultLoc->present()->name() : '';
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->present()->name() : '';
}
if ($request->has('rtd_location_address')) {
@@ -603,6 +617,14 @@ class ReportsController extends Controller
}
}
if ($request->has('manager')) {
if ($asset->checkedOutToUser()) {
$row[] = (($asset->assignedto) && ($asset->assignedto->manager)) ? $asset->assignedto->manager->present()->fullName : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->has('department')) {
if ($asset->checkedOutToUser()) {
+8 -4
View File
@@ -334,6 +334,7 @@ class SettingsController extends Controller
$setting->full_multiple_companies_support = $request->input('full_multiple_companies_support', '0');
$setting->load_remote = $request->input('load_remote', '0');
$setting->unique_serial = $request->input('unique_serial', '0');
$setting->show_images_in_email = $request->input('show_images_in_email', '0');
$setting->show_archived_in_list = $request->input('show_archived_in_list', '0');
$setting->dashboard_message = $request->input('dashboard_message');
@@ -347,6 +348,7 @@ class SettingsController extends Controller
$setting->default_eula_text = $request->input('default_eula_text');
$setting->thumbnail_max_h = $request->input('thumbnail_max_h');
$setting->privacy_policy_link = $request->input('privacy_policy_link');
if (Input::get('per_page')!='') {
$setting->per_page = $request->input('per_page');
@@ -395,6 +397,7 @@ 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->version_footer = $request->input('version_footer');
$setting->footer_text = $request->input('footer_text');
$setting->skin = $request->input('skin');
$setting->show_url_in_emails = $request->input('show_url_in_emails', '0');
@@ -477,6 +480,11 @@ class SettingsController extends Controller
$setting->two_factor_enabled = null;
} else {
$setting->two_factor_enabled = $request->input('two_factor_enabled');
# remote user login
$setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled');
$setting->login_common_disabled= (int)$request->input('login_common_disabled');
$setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url');
}
}
@@ -485,10 +493,6 @@ class SettingsController extends Controller
$setting->pwd_secure_min = (int) $request->input('pwd_secure_min');
$setting->pwd_secure_complexity = '';
# remote user login
$setting->login_remote_user_enabled = (int)$request->input('login_remote_user_enabled');
$setting->login_common_disabled= (int)$request->input('login_common_disabled');
$setting->login_remote_user_custom_logout_url = $request->input('login_remote_user_custom_logout_url');
if ($request->has('pwd_secure_complexity')) {
$setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity'));
+3 -3
View File
@@ -535,13 +535,13 @@ class UsersController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\RedirectResponse
*/
public function postBulkSave()
public function postBulkSave(Request $request)
{
$this->authorize('update', User::class);
if ((!Input::has('ids')) || (count(Input::has('ids')) == 0)) {
if ((!$request->has('ids')) || (count($request->input('ids')) == 0)) {
return redirect()->back()->with('error', 'No users selected');
} elseif ((!Input::has('status_id')) || (count(Input::has('status_id')) == 0)) {
} elseif ((!$request->has('status_id')) || ($request->input('status_id')=='')) {
return redirect()->route('users.index')->with('error', 'No status selected');
} else {
@@ -181,6 +181,8 @@ class ViewAssetsController extends Controller
// If it's already requested, cancel the request.
if ($asset->isRequestedBy(Auth::user())) {
$asset->cancelRequest();
$asset->decrement('requests_counter', 1);
$logaction->logaction('request canceled');
$settings->notify(new RequestAssetCancelationNotification($data));
return redirect()->route('requestable-assets')
@@ -188,8 +190,8 @@ class ViewAssetsController extends Controller
} else {
$logaction->logaction('requested');
$asset->request();
$asset->increment('requests_counter', 1);
$settings->notify(new RequestAssetNotification($data));
+1 -1
View File
@@ -22,8 +22,8 @@ class Kernel extends HttpKernel
\App\Http\Middleware\ReferrerPolicyHeader::class,
\App\Http\Middleware\ContentSecurityPolicyHeader::class,
\App\Http\Middleware\NosniffGuard::class,
\App\Http\Middleware\CheckForSetup::class,
\Fideloper\Proxy\TrustProxies::class,
\App\Http\Middleware\CheckForSetup::class,
\App\Http\Middleware\CheckForDebug::class,
// \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
];
+22
View File
@@ -0,0 +1,22 @@
<?php
namespace App\Http\Traits;
trait UniqueSerialTrait
{
/**
* Prepare a unique_ids rule, adding a model identifier if required.
*
* @param array $parameters
* @param string $field
* @return string
*/
protected function prepareUniqueSerialRule($parameters, $field)
{
if ($settings = \App\Models\Setting::first()) {
if ($settings->unique_serial=='1') {
return 'unique_undeleted:'.$this->table.','. $this->getKey();
}
}
}
}
+3 -3
View File
@@ -77,9 +77,9 @@ class AssetsTransformer
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
'purchase_cost' => Helper::formatCurrencyOutput($asset->purchase_cost),
'checkins_count' => (int) $asset->checkins_count,
'checkouts_count' => (int) $asset->checkouts_count,
'user_requests_count' => (int) $asset->user_requests_count,
'checkin_counter' => (int) $asset->checkin_counter,
'checkout_counter' => (int) $asset->checkout_counter,
'requests_counter' => (int) $asset->requests_counter,
'user_can_checkout' => (bool) $asset->availableForCheckout(),
];
@@ -30,17 +30,18 @@ class CategoriesTransformer
'eula' => ($category->getEula()) ? true : false,
'checkin_email' => ($category->checkin_email =='1') ? true : false,
'require_acceptance' => ($category->require_acceptance =='1') ? true : false,
'assets_count' => $category->assets_count,
'accessories_count' => $category->accessories_count,
'consumables_count' => $category->consumables_count,
'components_count' => $category->components_count,
'assets_count' => (int) $category->assets_count,
'accessories_count' => (int) $category->accessories_count,
'consumables_count' => (int) $category->consumables_count,
'components_count' => (int) $category->components_count,
'licenses_count' => (int) $category->licenses_count,
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($category->updated_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', Category::class) ? true : false,
'delete' => (Gate::allows('delete', Category::class) && ($category->assets_count == 0) && ($category->accessories_count == 0) && ($category->consumables_count == 0) && ($category->components_count == 0)) ? true : false,
'delete' => (Gate::allows('delete', Category::class) && ($category->assets_count == 0) && ($category->accessories_count == 0) && ($category->consumables_count == 0) && ($category->components_count == 0) && ($category->licenses_count == 0)) ? true : false,
];
$array += $permissions_array;
@@ -38,6 +38,7 @@ class LicensesTransformer
'license_email' => e($license->license_email),
'maintained' => ($license->maintained == 1) ? true : false,
'supplier' => ($license->supplier) ? ['id' => (int) $license->supplier->id,'name'=> e($license->supplier->name)] : null,
'category' => ($license->category) ? ['id' => (int) $license->category->id,'name'=> e($license->category->name)] : null,
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
'user_can_checkout' => (bool) ($license->free_seats_count > 0),
@@ -9,13 +9,13 @@ use App\Helpers\Helper;
class StatuslabelsTransformer
{
public function transformStatuslabels (Collection $statuslabels)
public function transformStatuslabels (Collection $statuslabels, $total)
{
$array = array();
foreach ($statuslabels as $statuslabel) {
$array[] = self::transformStatuslabel($statuslabel);
}
return (new DatatablesTransformer)->transformDatatables($array);
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformStatuslabel (Statuslabel $statuslabel)
+5 -5
View File
@@ -81,8 +81,8 @@ class AssetImporter extends ItemImporter
// 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'];
if(array_key_exists('checkout_target', $this->item)) {
$target = $this->item['checkout_target'];
}
$item = $this->sanitizeItemForStoring($asset, $editingAsset);
// The location id fetched by the csv reader is actually the rtd_location_id.
@@ -112,9 +112,9 @@ class AssetImporter extends ItemImporter
$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);
// If we have a target to checkout to, lets do so.
if(isset($target)) {
$asset->fresh()->checkOut($target);
}
return;
}
+6 -3
View File
@@ -14,17 +14,18 @@ class ConsumableImporter extends ItemImporter
protected function handle($row)
{
parent::handle($row); // TODO: Change the autogenerated stub
$this->createConsumableIfNotExists();
parent::handle($row);
$this->createConsumableIfNotExists($row);
}
/**
* Create a consumable if a duplicate does not exist
*
* @author Daniel Melzter
* @param array $row CSV Row Being parsed.
* @since 3.0
*/
public function createConsumableIfNotExists()
public function createConsumableIfNotExists($row)
{
$consumable = Consumable::where('name', $this->item['name'])->first();
if ($consumable) {
@@ -39,6 +40,8 @@ class ConsumableImporter extends ItemImporter
}
$this->log("No matching consumable, creating one");
$consumable = new Consumable();
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");;
$this->item['item_no'] = $this->findCsvMatch($row, "item_number");
$consumable->fill($this->sanitizeItemForStoring($consumable));
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
$consumable->unsetEventDispatcher();
+11 -6
View File
@@ -30,8 +30,11 @@ abstract class Importer
private $defaultFieldMap = [
'asset_tag' => 'asset tag',
'category' => 'category',
'checkout_class' => 'checkout type', // Supports Location or User for assets. Using checkout_class instead of checkout_type because type exists on asset already.
'checkout_location' => 'checkout location',
'company' => 'company',
'item_name' => 'item name',
'item_number' => "item number",
'image' => 'image',
'expiration_date' => 'expiration date',
'location' => 'location',
@@ -89,11 +92,12 @@ abstract class Importer
public function __construct($file)
{
$this->fieldMap = $this->defaultFieldMap;
// By default the importer passes a url to the file.
// However, for testing we also support passing a string directly
if (! ini_get("auto_detect_line_endings")) {
ini_set("auto_detect_line_endings", '1');
}
// By default the importer passes a url to the file.
// However, for testing we also support passing a string directly
if (is_file($file)) {
$this->csv = Reader::createFromPath($file);
} else {
@@ -179,9 +183,8 @@ abstract class Importer
*/
public function lookupCustomKey($key)
{
// dd($this->fieldMap);
if (array_key_exists($key, $this->fieldMap)) {
$this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
// $this->log("Found a match in our custom map: {$key} is " . $this->fieldMap[$key]);
return $this->fieldMap[$key];
}
// Otherwise no custom key, return original.
@@ -189,6 +192,8 @@ abstract class Importer
}
/**
* Used to lowercase header values to ensure we're comparing values properly.
*
* @param $results
* @return array
*/
@@ -249,11 +254,11 @@ abstract class Importer
$last_name = '';
if(empty($user_name) && empty($user_email) && empty($user_username)) {
$this->log('No user data provided - skipping user creation, just adding asset');
//$user_username = '';
return false;
}
// A username was given.
if( !empty($user_username)) {
// A username was given.
$user = User::where('username', $user_username)->first();
if($user) {
return $user;
+26 -1
View File
@@ -69,11 +69,36 @@ class ItemImporter extends Importer
$this->item['serial'] = $this->findCsvMatch($row, "serial");
// NO need to call this method if we're running the user import.
// TODO: Merge these methods.
$this->item['checkout_class'] = $this->findCsvMatch($row, "checkout_class");
if(get_class($this) !== UserImporter::class) {
$this->item["user"] = $this->createOrFetchUser($row);
// $this->item["user"] = $this->createOrFetchUser($row);
$this->item["checkout_target"] = $this->determineCheckout($row);
}
}
/**
* Parse row to determine what (if anything) we should checkout to.
* @param array $row CSV Row being parsed
* @return SnipeModel Model to be checked out to
*/
protected function determineCheckout($row)
{
// We only supporty checkout-to-location for asset, so short circuit otherw.
if(get_class($this) != AssetImporter::class) {
return $this->createOrFetchUser($row);
}
if ($this->item['checkout_class'] === 'location') {
// dd($this->findCsvMatch($row, 'checkout_location'));
return Location::findOrFail($this->createOrFetchLocation($this->findCsvMatch($row, 'checkout_location')));
// dd('here');
}
return $this->createOrFetchUser($row);
}
/**
* Cleanup the $item array before storing.
* We need to remove any values that are not part of the fillable fields.
+3 -3
View File
@@ -71,11 +71,11 @@ class LicenseImporter extends ItemImporter
// Lets try to checkout seats if the fields exist and we have seats.
if ($license->seats > 0) {
$user = $this->item['user'];
$checkout_target = $this->item['checkout_target'];
$asset = Asset::where('asset_tag', $asset_tag)->first();
$targetLicense = $license->licenseSeats()->first();
if ($user) {
$targetLicense->assigned_to = $user->id;
if ($checkout_target) {
$targetLicense->assigned_to = $checkout_target->id;
if ($asset) {
$targetLicense->asset_id = $asset->id;
}
+4 -2
View File
@@ -37,7 +37,6 @@ class UserImporter extends ItemImporter
$this->item['phone'] = $this->findCsvMatch($row, 'phone_number');
$this->item['jobtitle'] = $this->findCsvMatch($row, 'jobtitle');
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
$this->item['password'] = $this->tempPassword;
$user = User::where('username', $this->item['username'])->first();
if ($user) {
if (!$this->updating) {
@@ -45,11 +44,14 @@ class UserImporter extends ItemImporter
return;
}
$this->log('Updating User');
// $user = $this->users[$userId];
$user->update($this->sanitizeItemForUpdating($user));
$user->save();
return;
}
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
// Issue #5408
$this->item['password'] = $this->tempPassword;
$this->log("No matching user, creating one");
$user = new User();
$user->fill($this->sanitizeItemForStoring($user));
+7 -10
View File
@@ -2,6 +2,7 @@
namespace App\Models;
use App\Exceptions\CheckoutNotAllowed;
use App\Http\Traits\UniqueSerialTrait;
use App\Http\Traits\UniqueUndeletedTrait;
use App\Presenters\Presentable;
use AssetPresenter;
@@ -23,7 +24,7 @@ use App\Notifications\CheckoutAssetNotification;
class Asset extends Depreciable
{
protected $presenter = 'App\Presenters\AssetPresenter';
use Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait;
use Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait, UniqueSerialTrait;
const LOCATION = 'location';
const ASSET = 'asset';
@@ -72,12 +73,13 @@ class Asset extends Depreciable
'status_id' => 'required|integer|exists:status_labels,id',
'company_id' => 'integer|nullable',
'warranty_months' => 'numeric|nullable',
'physical' => 'numeric|max:1|nullable',
'physical' => 'numeric|max:1|nullable',
'checkout_date' => 'date|max:10|min:10|nullable',
'checkin_date' => 'date|max:10|min:10|nullable',
'supplier_id' => 'numeric|nullable',
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
'status' => 'integer',
'serial' => 'unique_serial|nullable',
'purchase_cost' => 'numeric|nullable',
'next_audit_date' => 'date|nullable',
'last_audit_date' => 'date|nullable',
@@ -189,16 +191,11 @@ class Asset extends Depreciable
$this->location_id = $target->location->id;
}
}
if ($this->requireAcceptance()) {
if(get_class($target) != User::class) {
throw new CheckoutNotAllowed;
}
$this->accepted="pending";
}
if ($this->save()) {
$this->logCheckout($note, $target);
$this->increment('checkout_counter', 1);
return true;
}
return false;
@@ -1060,7 +1057,7 @@ class Asset extends Depreciable
}
}
if (($fieldname!='category') && ($fieldname!='location') && ($fieldname!='supplier')
if (($fieldname!='category') && ($fieldname!='model_number') && ($fieldname!='location') && ($fieldname!='supplier')
&& ($fieldname!='status_label') && ($fieldname!='model') && ($fieldname!='company') && ($fieldname!='manufacturer')) {
$query->orWhere('assets.'.$fieldname, 'LIKE', '%' . $search_val . '%');
}
+1 -1
View File
@@ -153,7 +153,7 @@ class AssetModel extends SnipeModel
* @param $query
*
* @return $query
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @version v3.5
*/
public function scopeRequestableModels($query)
+6 -1
View File
@@ -33,7 +33,7 @@ class Category extends SnipeModel
'name' => 'required|min:1|max:255|unique_undeleted',
'require_acceptance' => 'boolean',
'use_default_eula' => 'boolean',
'category_type' => 'required|in:asset,accessory,consumable,component',
'category_type' => 'required|in:asset,accessory,consumable,component,license',
);
/**
@@ -74,6 +74,11 @@ class Category extends SnipeModel
return $this->hasMany('\App\Models\Accessory');
}
public function licenses()
{
return $this->hasMany('\App\Models\License');
}
public function consumables()
{
return $this->hasMany('\App\Models\Consumable');
+3 -1
View File
@@ -16,6 +16,7 @@ class CustomField extends Model
public $guarded=["id"];
public static $PredefinedFormats=[
"ANY" => "",
"CUSTOM REGEX" => "",
"ALPHA" => "alpha",
"ALPHA-DASH" => "alpha_dash",
"NUMERIC" => "numeric",
@@ -41,7 +42,8 @@ class CustomField extends Model
'format',
'field_values',
'field_encrypted',
'help_text'
'help_text',
'show_in_email',
];
// This is confusing, since it's actually the custom fields table that
+39 -2
View File
@@ -16,6 +16,14 @@ use Watson\Validating\ValidatingTrait;
class License extends Depreciable
{
protected $presenter = 'App\Presenters\LicensePresenter';
/**
* Set static properties to determine which checkout/checkin handlers we should use
*/
public static $checkoutClass = CheckoutLicenseNotification::class;
public static $checkinClass = CheckinLicenseNotification::class;
use SoftDeletes;
use CompanyableTrait;
use Loggable, Presentable;
@@ -41,6 +49,7 @@ class License extends Depreciable
'license_email' => 'email|nullable|max:120',
'license_name' => 'string|nullable|max:100',
'notes' => 'string|nullable',
'category_id' => 'required|exists:categories,id',
'company_id' => 'integer|nullable',
);
@@ -57,6 +66,7 @@ class License extends Depreciable
'license_name', //actually licensed_to
'maintained',
'manufacturer_id',
'category_id',
'name',
'notes',
'order_number',
@@ -83,7 +93,6 @@ class License extends Depreciable
static::updating(function ($license) {
$newSeatCount = $license->getAttributes()['seats'];
$oldSeatCount = isset($license->getOriginal()['seats']) ? $license->getOriginal()['seats'] : 0;
// dd($oldSeatCount.' '.$newSeatCount);
return static::adjustSeatCount($license, $oldSeatCount, $newSeatCount);
});
}
@@ -98,7 +107,7 @@ class License extends Depreciable
$change = abs($oldSeats - $newSeats);
if ($oldSeats > $newSeats) {
$license->load('licenseseats.user');
// dd("Here");
// Need to delete seats... lets see if if we have enough.
$seatsAvailableForDelete = $license->licenseseats->reject(function ($seat) {
return (!! $seat->assigned_to) || (!! $seat->asset_id);
@@ -176,11 +185,39 @@ class License extends Depreciable
return $this->belongsTo('\App\Models\Company', 'company_id');
}
public function category()
{
return $this->belongsTo('\App\Models\Category', 'category_id');
}
public function manufacturer()
{
return $this->belongsTo('\App\Models\Manufacturer', 'manufacturer_id');
}
public function checkin_email()
{
return $this->model->category->checkin_email;
}
public function requireAcceptance()
{
return $this->category->require_acceptance;
}
public function getEula()
{
$Parsedown = new \Parsedown();
if ($this->category->eula_text) {
return $Parsedown->text(e($this->category->eula_text));
} elseif ($this->category->use_default_eula == '1') {
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
} else {
return false;
}
}
/**
* Get the assigned user
*/
+15 -6
View File
@@ -21,7 +21,7 @@ trait Loggable
{
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @since [v3.4]
* @return \App\Models\Actionlog
*/
@@ -32,7 +32,7 @@ trait Loggable
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @since [v3.4]
* @return \App\Models\Actionlog
*/
@@ -55,7 +55,7 @@ trait Loggable
if ($log->target_type == Location::class) {
$log->location_id = $target->id;
} elseif ($log->target_type == Asset::class) {
$log->location_id = $target->rtd_location_id;
$log->location_id = $target->location_id;
} else {
$log->location_id = $target->location_id;
}
@@ -106,7 +106,7 @@ trait Loggable
return $log;
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @since [v3.4]
* @return \App\Models\Actionlog
*/
@@ -121,8 +121,17 @@ trait Loggable
$log->item_type = License::class;
$log->item_id = $this->license_id;
} else {
$log->item_type = static::class;
$log->item_id = $this->id;
if (static::class == Asset::class) {
if ($asset = Asset::find($log->item_id)) {
\Log::debug('Increment the checkin count for asset: '.$log->item_id);
$asset->increment('checkin_counter', 1);
}
}
}
@@ -195,7 +204,7 @@ trait Loggable
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @since [v3.5]
* @return \App\Models\Actionlog
*/
@@ -222,7 +231,7 @@ trait Loggable
}
/**
* @author Daniel Meltzer <parallelgrapefruit@gmail.com
* @author Daniel Meltzer <dmeltzer.devel@gmail.com>
* @since [v3.4]
* @return \App\Models\Actionlog
*/
+1
View File
@@ -43,6 +43,7 @@ class Setting extends Model
'audit_warning_days' => 'numeric|nullable',
'audit_interval' => 'numeric|nullable',
'custom_forgot_pass_url' => 'url|nullable',
'privacy_policy_link' => 'nullable|url'
];
protected $fillable = ['site_name','email_domain','email_format','username_format'];
@@ -76,7 +76,7 @@ class CheckinAssetNotification extends Notification
$fields = [
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.status') => $item->assetstatus->name,
trans('general.location') => $item->location->name,
trans('general.location') => ($item->location) ? $item->location->name : '',
];
return (new SlackMessage)
@@ -31,6 +31,7 @@ class CheckinLicenseNotification extends Notification
$this->admin = $params['admin'];
$this->note = '';
$this->settings = $params['settings'];
$this->target_type = $params['target_type'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
@@ -53,7 +54,10 @@ class CheckinLicenseNotification extends Notification
}
$notifyBy[] = 'mail';
if (($this->target_type == \App\Models\User::class) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
$notifyBy[] = 'mail';
}
return $notifyBy;
}
@@ -33,6 +33,7 @@ class CheckoutLicenseNotification extends Notification
$this->note = '';
$this->target_type = $params['target_type'];
$this->settings = $params['settings'];
$this->target_type = $params['target_type'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
@@ -56,7 +57,8 @@ class CheckoutLicenseNotification extends Notification
$notifyBy[] = 'slack';
}
if ($this->target_type == \App\Models\User::class) {
if (($this->target_type == \App\Models\User::class) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
$notifyBy[] = 'mail';
}
@@ -97,12 +99,18 @@ class CheckoutLicenseNotification extends Notification
public function toMail($notifiable)
{
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
$req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0;
return (new MailMessage)->markdown('notifications.markdown.checkout-license',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
'eula' => $eula,
'req_accept' => $req_accept,
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
])
->subject(trans('mail.Confirm_license_delivery'));
@@ -0,0 +1,82 @@
<?php
namespace App\Notifications;
use App\Models\Setting;
use App\Models\SnipeModel;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
use Carbon\Carbon;
class ExpectedCheckinAdminNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->assets = $params;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
$notifyBy = [];
$notifyBy[]='mail';
return $notifyBy;
}
public function toSlack($notifiable)
{
}
/**
* Get the mail representation of the notification.
*
* @param mixed $asset
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($params)
{
$message = (new MailMessage)->markdown('notifications.markdown.report-expected-checkins',
[
'assets' => $this->assets,
])
->subject('Expected asset checkin report');
return $message;
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
@@ -61,7 +61,7 @@ class ExpectedCheckinNotification extends Notification
return (new MailMessage)
->error()
->subject('Reminder: '.$this->params->present()->name().' checkin deadline approaching')
->line('Hi, '.$this->params->assignedto->first_name)
->line('Hi, '.$this->params->assignedto->first_name.' '.$this->params->assignedto->last_name)
->greeting('An asset checked out to you is due to be checked back in on '.$formatted_due.'.')
->line('Asset: '.$this->params->present()->name())
->line('Serial: '.$this->params->serial)
-7
View File
@@ -1,11 +1,4 @@
<?php
/**
* Created by PhpStorm.
* User: parallelgrapefruit
* Date: 12/23/16
* Time: 11:51 AM
*/
namespace App\Presenters;
use App\Helpers\Helper;
@@ -1,10 +1,4 @@
<?php
/**
* Created by PhpStorm.
* User: parallelgrapefruit
* Date: 12/23/16
* Time: 12:15 PM
*/
namespace App\Presenters;
-6
View File
@@ -1,10 +1,4 @@
<?php
/**
* Created by PhpStorm.
* User: parallelgrapefruit
* Date: 12/23/16
* Time: 12:15 PM
*/
namespace App\Presenters;
+3 -3
View File
@@ -182,21 +182,21 @@ class AssetPresenter extends Presenter
"title" => trans('general.notes'),
], [
"field" => "checkouts_count",
"field" => "checkout_counter",
"searchable" => false,
"sortable" => true,
"visible" => false,
"title" => trans('general.checkouts_count')
],[
"field" => "checkins_count",
"field" => "checkin_counter",
"searchable" => false,
"sortable" => true,
"visible" => false,
"title" => trans('general.checkins_count')
], [
"field" => "user_requests_count",
"field" => "requests_counter",
"searchable" => false,
"sortable" => true,
"visible" => false,
+6
View File
@@ -69,6 +69,12 @@ class CategoryPresenter extends Presenter
"sortable" => true,
"title" => trans('general.components'),
"visible" => true
], [
"field" => "licenses_count",
"searchable" => false,
"sortable" => true,
"title" => trans('general.licenses'),
"visible" => true
], [
"field" => "eula",
"searchable" => false,
+8
View File
@@ -61,6 +61,14 @@ class LicensePresenter extends Presenter
"searchable" => true,
"sortable" => true,
"title" => trans('admin/licenses/form.to_name'),
], [
"field" => "category",
"searchable" => true,
"sortable" => true,
"switchable" => true,
"title" => trans('general.category'),
"visible" => false,
"formatter" => "categoriesLinkObjFormatter"
], [
"field" => "supplier",
"searchable" => true,
+1
View File
@@ -73,6 +73,7 @@
"preferred-install": "dist",
"sort-packages": true,
"optimize-autoloader": true,
"process-timeout":3000,
"platform": {
"php": "5.6.4"
}
+1 -1
View File
@@ -78,7 +78,7 @@ return [
'collation' => env('DB_COLLATION', 'utf8mb4_unicode_ci'),
'prefix' => env('DB_PREFIX', null),
'strict' => false,
'engine' => null,
'engine' => 'InnoDB',
'unix_socket' => env('DB_SOCKET',''),
'dump_command_path' => env('DB_DUMP_PATH', '/usr/local/bin'), // only the path, so without 'mysqldump'
'dump_command_timeout' => 60 * 5, // 5 minute timeout
+5 -5
View File
@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v4.3.0',
'full_app_version' => 'v4.3.0 - build 3559-g9eab9ad40',
'build_version' => '3559',
'app_version' => 'v4.5.0',
'full_app_version' => 'v4.5.0 - build 3701-gbf1e742df',
'build_version' => '3701',
'prerelease_version' => '',
'hash_version' => 'g9eab9ad40',
'full_hash' => 'v4.3.0-66-g9eab9ad40',
'hash_version' => 'gbf1e742df',
'full_hash' => 'v4.4.2-63-gbf1e742df',
'branch' => 'master',
);
+15
View File
@@ -114,3 +114,18 @@ $factory->state(App\Models\Category::class, 'consumable-ink-category', function
];
});
$factory->state(App\Models\Category::class, 'license-graphics-category', function ($faker) {
return [
'name' => 'Graphics Software',
'category_type' => 'license',
];
});
$factory->state(App\Models\Category::class, 'license-office-category', function ($faker) {
return [
'name' => 'Office Software',
'category_type' => 'license',
];
});
+5 -1
View File
@@ -34,7 +34,8 @@ $factory->state(App\Models\License::class, 'photoshop', function ($faker) {
'purchase_cost' => '299.99',
'seats' => 10,
'purchase_order' => '13503Q',
'maintained' => true
'maintained' => true,
'category_id' => 14,
];
return $data;
@@ -49,6 +50,7 @@ $factory->state(App\Models\License::class, 'acrobat', function ($faker) {
'manufacturer_id' => 9,
'purchase_cost' => '29.99',
'seats' => 10,
'category_id' => 14,
];
@@ -62,6 +64,7 @@ $factory->state(App\Models\License::class, 'indesign', function ($faker) {
'manufacturer_id' => 9,
'purchase_cost' => '199.99',
'seats' => 10,
'category_id' => 14,
];
@@ -76,6 +79,7 @@ $factory->state(App\Models\License::class, 'office', function ($faker) {
'manufacturer_id' => 2,
'purchase_cost' => '49.99',
'seats' => 20,
'category_id' => 15,
];
@@ -17,7 +17,7 @@ class CreateCustomFieldDefaultValuesTable extends Migration
$table->increments('id');
$table->integer('asset_model_id');
$table->integer('custom_field_id');
$table->text('default_value')->nullable();
$table->text('default_value')->nullable()->default(null);
});
}
@@ -0,0 +1,35 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddCategoryToLicenses extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('licenses', function (Blueprint $table) {
$table->integer('category_id')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('licenses', function (Blueprint $table) {
$table->dropColumn('category_id');
});
}
}
@@ -0,0 +1,44 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Models\Category;
use App\Models\License;
class AddUpdateLicenseCategory extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// Create a new software category and assign all of the existing licenses to it
$category = new Category;
$category->name = 'Misc Software';
$category->category_type = 'license';
if ($category->save()) {
License::whereNull('category_id')->withTrashed()
->update(['category_id' => $category->id]);
}
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
App\Models\Category::where('name', 'Misc Software')->forceDelete();
License::whereNotNull('category_id')
->update(['category_id' => null]);
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddGdprPrivacyFooter extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->char('privacy_policy_link')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('privacy_policy_link');
});
}
}
@@ -0,0 +1,39 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddIndexes extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('action_logs', function (Blueprint $table) {
$table->index(['target_id', 'target_type']);
$table->index('created_at');
$table->index(['item_type', 'item_id', 'action_type']);
$table->index(['target_type', 'target_id', 'action_type']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('action_logs', function (Blueprint $table) {
$table->dropIndex(['target_id', 'target_type']);
$table->dropIndex(['created_at']);
$table->dropIndex(['item_type', 'item_id', 'action_type']);
$table->dropIndex(['target_type', 'target_id', 'action_type']);
});
}
}
@@ -0,0 +1,48 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddIndexesToAssets extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('assets', function (Blueprint $table) {
$table->index('created_at');
$table->index(['deleted_at', 'status_id']);
$table->index(['deleted_at', 'model_id']);
$table->index(['deleted_at', 'assigned_type', 'assigned_to']);
$table->index(['deleted_at', 'supplier_id']);
$table->index(['deleted_at', 'location_id']);
$table->index(['deleted_at', 'rtd_location_id']);
$table->index(['deleted_at', 'asset_tag']);
$table->index(['deleted_at', 'name']);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('assets', function (Blueprint $table) {
$table->dropIndex(['created_at']);
$table->dropIndex(['deleted_at', 'status_id']);
$table->dropIndex(['deleted_at', 'model_id']);
$table->dropIndex(['deleted_at', 'assigned_type', 'assigned_to']);
$table->dropIndex(['deleted_at', 'supplier_id']);
$table->dropIndex(['deleted_at', 'location_id']);
$table->dropIndex(['deleted_at', 'rtd_location_id']);
$table->dropIndex(['deleted_at', 'asset_tag']);
$table->dropIndex(['deleted_at', 'name']);
});
}
}
@@ -0,0 +1,36 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class DenormCountersOnAssets extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('assets', function (Blueprint $table) {
$table->integer('checkin_counter')->default(0);
$table->integer('checkout_counter')->default(0);
$table->integer('requests_counter')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('assets', function (Blueprint $table) {
$table->dropColumn('checkin_counter');
$table->dropColumn('checkout_counter');
$table->dropColumn('requests_counter');
});
}
}
@@ -0,0 +1,34 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
use App\Models\Asset;
class AddFirstCounterTotalsToAssets extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
// This artisan call may take a while
\Log::info('This could take a while.... ');
Artisan::call('snipeit:counter-sync');
$output = Artisan::output();
\Log::info($output);
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
//
}
}
@@ -0,0 +1,29 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddVersionFooter extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->char('version_footer', 5)->nullable()->default('on');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('version_footer');
});
}
}
@@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddUniqueSerialOptionToSettings extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('unique_serial')->default('0');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('unique_serial');
});
}
}
+2
View File
@@ -21,6 +21,8 @@ class CategorySeeder extends Seeder
factory(Category::class, 1)->states('consumable-ink-category')->create(); // 11
factory(Category::class, 1)->states('component-hdd-category')->create(); // 12
factory(Category::class, 1)->states('component-ram-category')->create(); // 13
factory(Category::class, 1)->states('license-graphics-category')->create(); // 14
factory(Category::class, 1)->states('license-office-category')->create(); // 15
}
}
+7 -1
View File
@@ -17,12 +17,18 @@ else
fi
# create data directories
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
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' 'keys'; do
mkdir -p "/var/lib/snipeit/$dir"
done
chown -R docker:root /var/lib/snipeit/data/*
chown -R docker:root /var/lib/snipeit/dumps
chown -R docker:root /var/lib/snipeit/keys
# If the Oauth DB files are not present copy the vendor files over to the db migrations
if [ ! -f "/var/www/html/database/migrations/*create_oauth*" ]; then
cp -ax /var/www/html/vendor/laravel/passport/database/migrations/* /var/www/html/database/migrations/
fi
. /etc/apache2/envvars
exec apache2 -DNO_DETACH < /dev/null
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
+16 -16
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+16 -16
View File
File diff suppressed because one or more lines are too long
+7 -7
View File
@@ -1,14 +1,14 @@
{
"/js/build/vue.js": "/js/build/vue.js?id=992bcb968a7f2da998b5",
"/js/build/vue.js": "/js/build/vue.js?id=5eab4676dde73dbab3ca",
"/css/AdminLTE.css": "/css/AdminLTE.css?id=5e72463a66acbcc740d5",
"/css/app.css": "/css/app.css?id=407edb63cc6b6dc62405",
"/css/overrides.css": "/css/overrides.css?id=d85394a0b4f58e81bb78",
"/js/build/vue.js.map": "/js/build/vue.js.map?id=e0eb0edc0b761965973f",
"/css/overrides.css": "/css/overrides.css?id=2d81c3704393bac77011",
"/js/build/vue.js.map": "/js/build/vue.js.map?id=525260f84ea83d4b55cd",
"/css/AdminLTE.css.map": "/css/AdminLTE.css.map?id=99f5a5a03c4155cf69f6",
"/css/app.css.map": "/css/app.css.map?id=bdbe05e6ecd70ccfac72",
"/css/overrides.css.map": "/css/overrides.css.map?id=898c91d4a425b01b589b",
"/css/dist/all.css": "/css/dist/all.css?id=0e3642f1b6a8a436d558",
"/js/dist/all.js": "/js/dist/all.js?id=39b95992f478d68c44a8",
"/css/build/all.css": "/css/build/all.css?id=0e3642f1b6a8a436d558",
"/js/build/all.js": "/js/build/all.js?id=39b95992f478d68c44a8"
"/css/dist/all.css": "/css/dist/all.css?id=98db4e9b7650453c8b00",
"/js/dist/all.js": "/js/dist/all.js?id=85c7dab4c75f53c45b91",
"/css/build/all.css": "/css/build/all.css?id=98db4e9b7650453c8b00",
"/js/build/all.js": "/js/build/all.js?id=85c7dab4c75f53c45b91"
}
@@ -44,8 +44,10 @@
</div>
<div class="col-sm-12 col-lg-6">
<input v-if="field.type == 'text'" class="form-control m-b-xs" type="text" :value="getValue(field)" :id="'default-value' + field.id" :name="'default_values[' + field.id + ']'">
<textarea v-if="field.type == 'textarea'" class="form-control" :value="getValue(field)" :id="'default-value' + field.id" :name="'default_values[' + field.id + ']'"></textarea><br>
<select v-if="field.type == 'listbox'" class="form-control m-b-xs" :name="'default_values[' + field.id + ']'">
<option value="0"></option>
<option value=""></option>
<option v-for="field_value in field.field_values_array" :value="field_value" :selected="getValue(field) == field_value">{{ field_value }}</option>
</select>
</div>
@@ -117,12 +117,18 @@ tr {
assets: [
{id: 'asset_tag', text: 'Asset Tag' },
{id: 'asset_model', text: 'Model Name' },
{id: 'checkout_class', text: 'Checkout Type' },
{id: 'checkout_location', text: 'Checkout Location' },
{id: 'image', text: 'Image Filename' },
{id: 'model_number', text: 'Model Number' },
{id: 'full_name', text: 'Full Name' },
{id: 'status', text: 'Status' },
{id: 'warranty_months', text: 'Warranty Months' },
],
consumables: [
{id: 'item_no', text: "Item Number"},
{id: 'model_number', text: "Model Number"},
],
licenses: [
{id: 'expiration_date', text: 'Expiration Date' },
{id: 'license_email', text: 'Licensed To Email' },
@@ -165,6 +171,11 @@ tr {
.concat(this.columnOptions.assets)
.concat(this.columnOptions.customFields)
.sort(sorter);
case 'consumable':
return this.columnOptions.general
.concat(this.columnOptions.consumables)
.sort(sorter);
case 'license':
return this.columnOptions.general.concat(this.columnOptions.licenses).sort(sorter);
case 'user':
@@ -184,7 +195,6 @@ tr {
},
watch: {
columns() {
console.log("CHANGED");
this.populateSelect2ActiveItems();
}
},
@@ -234,7 +244,6 @@ tr {
for(var j=0; j < this.columns.length; j++) {
let column = this.columns[j];
let lower = this.file.header_row.map((value) => value.toLowerCase());
console.dir(lower);
let index = lower.indexOf(column.text.toLowerCase())
if(index != -1) {
this.$set(this.columnMappings, this.file.header_row[index], column.id)
@@ -248,7 +257,6 @@ tr {
}
},
updateModel(header, value) {
console.log(header, value);
this.columnMappings[header] = value;
}
},
+6
View File
@@ -341,3 +341,9 @@ img.navbar-brand-img, .navbar-brand>img {
font-size: 20px;
color: #889195;
}
#login-logo {
padding-top: 20px;
padding-bottom: 10px;
max-width: 200px
}
@@ -5,7 +5,8 @@ return array(
'about_categories' => 'Kategorieë help jou om jou items te organiseer. Sommige voorbeeldkategorieë kan wees &quot;Desktops&quot;, &quot;Laptops&quot;, &quot;Mobile Phones&quot;, &quot;Tablets&quot;, ensovoorts, maar jy kan kategorieë gebruik wat vir jou sin maak.',
'asset_categories' => 'Bate kategorieë',
'category_name' => 'Kategorie Naam',
'checkin_email' => 'Stuur e-pos aan gebruiker op inskrywing.',
'checkin_email' => 'Send email to user on checkin/checkout.',
'checkin_email_notification' => 'This user will be sent an email on checkin/checkout.',
'clone' => 'Klone Kategorie',
'create' => 'Skep Kategorie',
'edit' => 'Wysig Kategorie',
+5 -2
View File
@@ -131,8 +131,11 @@ return array(
'labels_per_page' => 'Etikette per bladsy',
'label_dimensions' => 'Etiketafmetings (duim)',
'next_auto_tag_base' => 'Volgende outomatiese inkrement',
'page_padding' => 'Bladsy marges (duim)',
'purge' => 'Verwyder verwyderde rekords',
'page_padding' => 'Bladsy marges (duim)',
'privacy_policy_link' => 'Link to Privacy Policy',
'privacy_policy' => 'Privacy Policy',
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
'purge' => 'Verwyder verwyderde rekords',
'labels_display_bgutter' => 'Etiket onderkant goot',
'labels_display_sgutter' => 'Label side goot',
'labels_fontsize' => 'Etiket lettergrootte',
@@ -5,7 +5,8 @@ return array(
'about_categories' => 'التصنيفات تساعدك على ترتيب الأصول. من الأمثلة على التصنيفات &quot; حواسيب مكتبية &quot;، &quot; حواسيب محمولة &quot;، &quot;الهواتف النقالة &quot;، &quot;أجهزة لوحية &quot; وهكذا، كما يمكنك استخدام التصنيفات بأي طريقة تناسبك.',
'asset_categories' => 'تصنيفات الأصول',
'category_name' => 'اسم التصنيف',
'checkin_email' => 'إرسال إشعار للمستخدم عند الإدخال.',
'checkin_email' => 'Send email to user on checkin/checkout.',
'checkin_email_notification' => 'This user will be sent an email on checkin/checkout.',
'clone' => 'نسخ التصنيف',
'create' => 'إنشاء تصنيف',
'edit' => 'تعديل التصنيف',
+5 -2
View File
@@ -131,8 +131,11 @@ return array(
'labels_per_page' => 'عدد التسميات لكل صفحة',
'label_dimensions' => 'أبعاد التسمية (بوصة)',
'next_auto_tag_base' => 'الزيادة التلقائية التالية',
'page_padding' => 'هوامش الصفحة (بوصة)',
'purge' => 'تطهير السجلات المحذوفة',
'page_padding' => 'هوامش الصفحة (بوصة)',
'privacy_policy_link' => 'Link to Privacy Policy',
'privacy_policy' => 'Privacy Policy',
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
'purge' => 'تطهير السجلات المحذوفة',
'labels_display_bgutter' => 'الجزء السفلي للتسمية',
'labels_display_sgutter' => 'الجزء الجانبي للتسمية',
'labels_fontsize' => 'حجم خط التسمية',
@@ -5,7 +5,8 @@ return array(
'about_categories' => 'Категориите помагат с организирането на вашите елементи. Някои примерни категории могат да бъдат &quot;Настолни компютри&quot;,&quot;Лаптопи&quot;,&quot;Мобилни телефони&quot;,&quot;Таблети&quot;, и т.н., но може да използвате всяка категория, имаща смисъл за организацията ви.',
'asset_categories' => 'Категории на активи',
'category_name' => 'Име на категория',
'checkin_email' => 'Изпращане на email до потребителя при вписване на активи.',
'checkin_email' => 'Send email to user on checkin/checkout.',
'checkin_email_notification' => 'This user will be sent an email on checkin/checkout.',
'clone' => 'Копиране на категория',
'create' => 'Създаване на категория',
'edit' => 'Редакция на категория',
@@ -28,5 +28,5 @@ return array(
'create_fieldset' => 'Нов Fieldset',
'create_field' => 'Ново персонализирано поле',
'value_encrypted' => 'Стойността на това поле е криптирана в базата данни. Само администратор потребители ще бъде в състояние да видят дешифрираната стойност',
'show_in_email' => 'Include the value of this field in checkout emails sent to the user? Encrypted fields cannot be included in emails.',
'show_in_email' => 'Да се включи ли стойността на това поле в електронната поща, изпращана към потребителите? Криптираните полета не могат да бъдат включвани в изпращаните електронни пощи.',
);
+1 -1
View File
@@ -5,7 +5,7 @@ return array(
'about_assets_text' => 'Активите са елементи, проследен от сериен номер или етикет. По-често, те са елементи с висока стойност, където идентифицирането на специфичен елемент е от значение.',
'archived' => 'Архивиран',
'asset' => 'Актив',
'bulk_checkout' => 'Checkout Assets',
'bulk_checkout' => 'Изписване на активи',
'checkin' => 'Връщане на актив',
'checkout' => 'Проверка на активите',
'clone' => 'Копиране на актив',
+1 -1
View File
@@ -14,5 +14,5 @@ return array(
'view_models' => 'Преглед на моделите',
'fieldset' => 'Полета',
'no_custom_field' => 'Няма потребителски полета',
'add_default_values' => 'Add default values',
'add_default_values' => 'Добавяне на стойности по подразбиране',
);
+9 -6
View File
@@ -4,8 +4,8 @@ return array(
'ad' => 'Активна директория',
'ad_domain' => 'Домейн на активна директория',
'ad_domain_help' => 'Това е понякога еднакво с вашия email домейн, но не винаги.',
'admin_cc_email' => 'CC Email',
'admin_cc_email_help' => 'If you would like to send a copy of checkin/checkout emails that are sent to users to an additional email account, enter it here. Otherwise leave this field blank.',
'admin_cc_email' => 'CC електронна поща',
'admin_cc_email_help' => 'Въведете допълнителни електронни адреси, ако желаете да се изпраща копие на електронните пощи при вписване и изписване на активи.',
'is_ad' => 'Това е активна директория на сървър',
'alert_email' => 'Изпращане на нотификации към',
'alerts_enabled' => 'Включване на известията',
@@ -109,8 +109,8 @@ return array(
'show_alerts_in_menu' => 'Показва съобщения в главното меню',
'show_archived_in_list' => 'Архивирани активи',
'show_archived_in_list_text' => 'Показва архивираните активи в списъка "Всички активи"',
'show_images_in_email' => 'Show images in emails',
'show_images_in_email_help' => 'Uncheck this box if your Snipe-IT installation is behind a VPN or closed network and users outside the network will not be able to load images served from this installation in their emails.',
'show_images_in_email' => 'Показване на изображения в електронните съобщения',
'show_images_in_email_help' => 'Премахнете отметката, ако Вашата инсталация е достъпна единствено във вътрешната мрежа или през VPN.',
'site_name' => 'Име на системата',
'slack_botname' => 'Име на Slack bot',
'slack_channel' => 'Slack канал',
@@ -131,8 +131,11 @@ return array(
'labels_per_page' => 'Етикети на страница',
'label_dimensions' => 'Измерения на етикети (инчове)',
'next_auto_tag_base' => 'Следващото автоматично увеличение',
'page_padding' => 'Марж на страница (инчове)',
'purge' => 'Пречисти изтрити записи',
'page_padding' => 'Марж на страница (инчове)',
'privacy_policy_link' => 'Link to Privacy Policy',
'privacy_policy' => 'Privacy Policy',
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
'purge' => 'Пречисти изтрити записи',
'labels_display_bgutter' => 'Обозначаване на долен канал',
'labels_display_sgutter' => 'Обозначаване на страничен канал',
'labels_fontsize' => 'Обозначаване на размер на шрифта',
+1 -1
View File
@@ -12,5 +12,5 @@ return array(
'submit' => 'Потвърди',
'upload' => 'Качване',
'select_file' => 'Изберете файл...',
'select_files' => 'Select Files...',
'select_files' => 'Изберете файлове...',
);
+6 -6
View File
@@ -9,7 +9,7 @@
'activity_report' => 'Справка за дейностите',
'address' => 'Aдрес',
'admin' => 'Администриране',
'administrator' => 'Administrator',
'administrator' => 'Администратор',
'add_seats' => 'Добавени работни места',
'all_assets' => 'Всички активи',
'all' => 'Всички',
@@ -39,9 +39,9 @@
'checkin' => 'Вписване',
'checkin_from' => 'Форма за вписване',
'checkout' => 'Изписване',
'checkouts_count' => 'Checkouts',
'checkins_count' => 'Checkins',
'user_requests_count' => 'Requests',
'checkouts_count' => 'Изписвания',
'checkins_count' => 'Вписвания',
'user_requests_count' => 'Заявки',
'city' => 'Град',
'click_here' => 'Натиснете тук',
'clear_selection' => 'Изчистване на селектираното',
@@ -68,7 +68,7 @@
'debug_warning' => 'Предупреждение!',
'debug_warning_text' => 'Това приложение се изпълнява в режим на производство с разрешено отстраняване на грешки. Това може да изложи чувствителни данни, ако приложението ви е достъпно за външния свят. Забранете режим отстраняване на грешки чрез задаване на стойността <code>APP_DEBUF</code> <code>.env</code> във файла <code>false</code>.',
'delete' => 'Изтриване',
'delete_confirm' => 'Are you sure you wish to delete :item?',
'delete_confirm' => 'Сигурни ли сте, че желаете изтриването на :item?',
'deleted' => 'Изтрито',
'delete_seats' => 'Изтрити работни места за лиценз',
'departments' => 'Катедри',
@@ -206,7 +206,7 @@
'unknown_admin' => 'Непознат администратор',
'username_format' => 'Формат на потребителско име',
'update' => 'Обновяване',
'upload_filetypes_help' => 'Allowed filetypes are png, gif, jpg, jpeg, doc, docx, pdf, txt, zip, and rar. Max upload size allowed is :size.',
'upload_filetypes_help' => 'Допустимите типове файлове са png, gif, jpg, jpeg, doc, docx, pdf, txt, zip и rar. Максималният размер за качване е :size.',
'uploaded' => 'Качен',
'user' => 'Потребител',
'accepted' => 'приет',
+4 -4
View File
@@ -22,7 +22,7 @@ return array(
'Confirm_Asset_Checkin' => 'Потвърдете вписване на актив.',
'Confirm_Accessory_Checkin' => 'Потвърдете вписване на аксесоар.',
'Confirm_accessory_delivery' => 'Потвърдете доставка на аксесоар.',
'Confirm_license_delivery' => 'Confirm license delivery.',
'Confirm_license_delivery' => 'Потвърдете доставката на лиценз.',
'Confirm_asset_delivery' => 'Подвърдете доставка на актив.',
'Confirm_consumable_delivery' => 'Потвърдете доставка на консуматив.',
'current_QTY' => 'Текуща наличност',
@@ -55,7 +55,7 @@ return array(
'requested' => 'Изискан:',
'reset_link' => 'Вашата връзка за повторно задаване на паролата',
'reset_password' => 'Щракнете тук, за да нулирате паролата си:',
'serial' => 'Serial',
'serial' => 'Лицензен номер',
'supplier' => 'Доставчик',
'tag' => 'Етикет',
'test_email' => 'Тест Email от Snipe-IT',
@@ -64,8 +64,8 @@ return array(
'There_are' => '{1} има | [2, Inf] Имат',
'to_reset' => 'За да нулирате вашата :web password, попълнете този формуляр:',
'type' => 'Вид',
'user' => 'User',
'username' => 'Username',
'user' => 'Потребител',
'username' => 'Потребителско име',
'welcome' => 'Добре дошли, :name',
'welcome_to' => 'Добре дошли: уеб!',
'your_credentials' => 'Вашите идентификационни данни за Snipe-IT',
@@ -5,7 +5,8 @@ return array(
'about_categories' => 'Kategorie usnadňují organizovat majetek. Takovou kategorii může být např. &quot;Desktopy&quot;, &quot;Notebooky&quot;, &quot;Mobilní telefony&quot;, &quot;Tablety&quot;, apod., ale můžete použít kategorie jakýmkoli způsobem.',
'asset_categories' => 'Kategorie majetku',
'category_name' => 'Jméno kategorie',
'checkin_email' => 'Poslat uživateli zprávu při přejímce.',
'checkin_email' => 'Send email to user on checkin/checkout.',
'checkin_email_notification' => 'This user will be sent an email on checkin/checkout.',
'clone' => 'Klonovat Kategorii',
'create' => 'Vytvořit kategorii',
'edit' => 'Upravit Kategorii',
+5 -2
View File
@@ -131,8 +131,11 @@ return array(
'labels_per_page' => 'Štítků na stránku',
'label_dimensions' => 'Rozměry štítku (palce)',
'next_auto_tag_base' => 'Další auto přírůstek',
'page_padding' => 'Okraje stránky (palce)',
'purge' => 'Vyčištění odstraněných záznamů',
'page_padding' => 'Okraje stránky (palce)',
'privacy_policy_link' => 'Link to Privacy Policy',
'privacy_policy' => 'Privacy Policy',
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
'purge' => 'Vyčištění odstraněných záznamů',
'labels_display_bgutter' => 'Spodní okraj štítku',
'labels_display_sgutter' => 'Boční okraj štítku',
'labels_fontsize' => 'Velikost písma štítku',
@@ -5,7 +5,8 @@ return array(
'about_categories' => 'Kategorier hjælper dig med at organisere dine varer. Nogle eksempler kan være &quot;Desktops&quot;, &quot;Laptops&quot;, &quot;Mobile Phones&quot;, &quot;Tablets&quot; osv., Men du kan bruge kategorier på nogen måde, der giver mening for dig.',
'asset_categories' => 'Aktiver Kategorier',
'category_name' => 'Kategorinavn',
'checkin_email' => 'Send email til bruger ved tjek ind.',
'checkin_email' => 'Send email to user on checkin/checkout.',
'checkin_email_notification' => 'This user will be sent an email on checkin/checkout.',
'clone' => 'Klon Kategori',
'create' => 'Opret kategori',
'edit' => 'Rediger Kategori',
+5 -2
View File
@@ -131,8 +131,11 @@ return array(
'labels_per_page' => 'Etiketter pr. Side',
'label_dimensions' => 'Etiket dimensioner (inches)',
'next_auto_tag_base' => 'Næste automatisk stigning',
'page_padding' => 'Sidemarginer (tommer)',
'purge' => 'Ryd slettet poster',
'page_padding' => 'Sidemarginer (tommer)',
'privacy_policy_link' => 'Link to Privacy Policy',
'privacy_policy' => 'Privacy Policy',
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
'purge' => 'Ryd slettet poster',
'labels_display_bgutter' => 'Etiket bundgitter',
'labels_display_sgutter' => 'Label side rende',
'labels_fontsize' => 'Etiket skriftstørrelse',
@@ -5,7 +5,8 @@ return array(
'about_categories' => 'Kategorien helfen Ihnen beim Organisieren von Assets. Beispielkategorien sind &quot;PCs&quot;, &quot;Laptops&quot;, &quot;Mobiltelefone&quot;, &quot;Tablets&quot; usw., jedoch können Sie Kategorien nutzen, wie Sie es für sinnvoll erachten.',
'asset_categories' => 'Asset-Kategorien',
'category_name' => 'Kategoriename',
'checkin_email' => 'Dem Nutzer beim Zurücknehmen eine Mail zusenden.',
'checkin_email' => 'Send email to user on checkin/checkout.',
'checkin_email_notification' => 'This user will be sent an email on checkin/checkout.',
'clone' => 'Kategorie duplizieren',
'create' => 'Kategorie erstellen',
'edit' => 'Kategorie bearbeiten',
@@ -28,5 +28,5 @@ return array(
'create_fieldset' => 'Neuer Feldsatz',
'create_field' => 'Neues benutzerdefiniertes Feld',
'value_encrypted' => 'Der Wert dieses Feldes ist in der Datenbank verschlüsselt. Nur Benutzer mit Administratorrechten können den entschlüsselten Wert anzeigen',
'show_in_email' => 'Include the value of this field in checkout emails sent to the user? Encrypted fields cannot be included in emails.',
'show_in_email' => 'Feld miteinbeziehen bei Herausgabe-Emails an die Benutzer? Verschlüsselte Felder können nicht miteinbezogen werden.',
);
+1 -1
View File
@@ -5,7 +5,7 @@ return array(
'about_assets_text' => 'Assets sind Gegenstände die durch eine Seriennummer oder Bezeichnung identifiziert werden. Meistens sind diese von höherem Wert, wobei es Sinn macht diese spezifisch zu kennzeichnen.',
'archived' => 'Archiviert',
'asset' => 'Asset',
'bulk_checkout' => 'Checkout Assets',
'bulk_checkout' => 'Assets herausgeben',
'checkin' => 'Asset zurücknehmen',
'checkout' => 'Asset herausgeben',
'clone' => 'Asset duplizieren',
+1 -1
View File
@@ -14,5 +14,5 @@ return array(
'view_models' => 'Modelle anzeigen',
'fieldset' => 'Feldsatz',
'no_custom_field' => 'Keine benutzerdefinierten Felder',
'add_default_values' => 'Add default values',
'add_default_values' => 'Füge Standardwerte hinzu',
);
+8 -5
View File
@@ -5,7 +5,7 @@ return array(
'ad_domain' => 'Active Directory Domäne',
'ad_domain_help' => 'Meistens dieselbe wie die E-Mail Domäne.',
'admin_cc_email' => 'CC Email',
'admin_cc_email_help' => 'If you would like to send a copy of checkin/checkout emails that are sent to users to an additional email account, enter it here. Otherwise leave this field blank.',
'admin_cc_email_help' => 'Wenn Sie eine Kopie der Rücknahme- / Herausgabe-E-Mails, die an Benutzer gehen auch an zusätzliche E-Mail-Empfänger versenden möchten, geben Sie sie hier ein. Ansonsten lassen Sie dieses Feld leer.',
'is_ad' => 'Dies ist ein Active Directory Server',
'alert_email' => 'Alarme senden an',
'alerts_enabled' => 'E-Mail-Benachrichtigungen aktiviert',
@@ -109,8 +109,8 @@ return array(
'show_alerts_in_menu' => 'Warnungen im oberen Menü anzeigen',
'show_archived_in_list' => 'Archivierte Assets',
'show_archived_in_list_text' => 'Zeige archivierte Assets in der "Alle auflisten" Liste',
'show_images_in_email' => 'Show images in emails',
'show_images_in_email_help' => 'Uncheck this box if your Snipe-IT installation is behind a VPN or closed network and users outside the network will not be able to load images served from this installation in their emails.',
'show_images_in_email' => 'Verwende Bilder in E-Mals',
'show_images_in_email_help' => 'Deaktivieren Sie dieses Kontrollkästchen, wenn sich Ihre Snipe-IT-Installation hinter einem VPN oder einem geschlossenen Netzwerk befindet und Benutzer außerhalb des Netzwerks keine Bilder von dieser Installation in ihre E-Mails laden können.',
'site_name' => 'Seitenname',
'slack_botname' => 'Slack Botname',
'slack_channel' => 'Slack Kanal',
@@ -131,8 +131,11 @@ return array(
'labels_per_page' => 'Etiketten pro Seite',
'label_dimensions' => 'Etikettengröße (Zoll)',
'next_auto_tag_base' => 'Nächster Auto-Inkrement',
'page_padding' => 'Seiten Ränder (Zoll)',
'purge' => 'Gelöschte Einträge bereinigen',
'page_padding' => 'Seiten Ränder (Zoll)',
'privacy_policy_link' => 'Link to Privacy Policy',
'privacy_policy' => 'Privacy Policy',
'privacy_policy_link_help' => 'If a url is included here, a link to your privacy policy will be included in the app footer and in any emails that the system sends out, in compliance with GDPR. ',
'purge' => 'Gelöschte Einträge bereinigen',
'labels_display_bgutter' => 'Ettiketten Spaltenzwischenraum unterhalb',
'labels_display_sgutter' => 'Ettikett Seitenabstand',
'labels_fontsize' => 'Schriftgröße der Etiketten',
+1 -1
View File
@@ -12,5 +12,5 @@ return array(
'submit' => 'Abschicken',
'upload' => 'Hochladen',
'select_file' => 'Datei auswählen...',
'select_files' => 'Select Files...',
'select_files' => 'Dateien auswählen...',
);

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