Merge branch 'develop' into chore/migrate-select-helper

This commit is contained in:
Marcus Moore
2025-03-06 13:39:05 -08:00
35 changed files with 426 additions and 329 deletions

View File

@@ -3298,6 +3298,15 @@
"contributions": [
"code"
]
},
{
"login": "Fiala06",
"name": "Fiala06",
"avatar_url": "https://avatars.githubusercontent.com/u/5183146?v=4",
"profile": "https://github.com/Fiala06",
"contributions": [
"code"
]
}
]
}

View File

@@ -53,7 +53,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/55590532?v=4" width="110px;"/><br /><sub>squintfox</sub>](https://github.com/squintfox)<br />[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [<img src="https://avatars.githubusercontent.com/u/1380084?v=4" width="110px;"/><br /><sub>Jeff Clay</sub>](https://github.com/jeffclay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [<img src="https://avatars.githubusercontent.com/u/52716446?v=4" width="110px;"/><br /><sub>Phil J R</sub>](https://github.com/PP-JN-RL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [<img src="https://avatars.githubusercontent.com/u/1496725?v=4" width="110px;"/><br /><sub>i_virus</sub>](https://www.corelight.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [<img src="https://avatars.githubusercontent.com/u/1020541?v=4" width="110px;"/><br /><sub>Paul Grime</sub>](https://github.com/gitgrimbo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [<img src="https://avatars.githubusercontent.com/u/922815?v=4" width="110px;"/><br /><sub>Lee Porte</sub>](https://leeporte.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [<img src="https://avatars.githubusercontent.com/u/23613427?v=4" width="110px;"/><br /><sub>BRYAN </sub>](https://github.com/bryanlopezinc)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") | [<img src="https://avatars.githubusercontent.com/u/143394709?v=4" width="110px;"/><br /><sub>Sebastian Groß</sub>](https://github.com/sgross-emlix)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sgross-emlix "Code") |
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") | [<img src="https://avatars.githubusercontent.com/u/18550946?v=4" width="110px;"/><br /><sub>Adugna Gizaw</sub>](https://orbalia.pythonanywhere.com/)<br />[🌍](#translation-addex12 "Translation") | [<img src="https://avatars.githubusercontent.com/u/760989?v=4" width="110px;"/><br /><sub>Jesse Ostrander</sub>](https://github.com/jostrander)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jostrander "Code") | [<img src="https://avatars.githubusercontent.com/u/31522486?v=4" width="110px;"/><br /><sub>James M</sub>](https://github.com/azmcnutt)<br />[💻](https://github.com/snipe/snipe-it/commits?author=azmcnutt "Code") |
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") | [<img src="https://avatars.githubusercontent.com/u/18550946?v=4" width="110px;"/><br /><sub>Adugna Gizaw</sub>](https://orbalia.pythonanywhere.com/)<br />[🌍](#translation-addex12 "Translation") | [<img src="https://avatars.githubusercontent.com/u/760989?v=4" width="110px;"/><br /><sub>Jesse Ostrander</sub>](https://github.com/jostrander)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jostrander "Code") | [<img src="https://avatars.githubusercontent.com/u/31522486?v=4" width="110px;"/><br /><sub>James M</sub>](https://github.com/azmcnutt)<br />[💻](https://github.com/snipe/snipe-it/commits?author=azmcnutt "Code") | [<img src="https://avatars.githubusercontent.com/u/5183146?v=4" width="110px;"/><br /><sub>Fiala06</sub>](https://github.com/Fiala06)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Fiala06 "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

View File

@@ -42,7 +42,7 @@ class SendExpirationAlerts extends Command
public function handle()
{
$settings = Setting::getSettings();
$threshold = $settings->alert_interval;
$alert_interval = $settings->alert_interval;
if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
@@ -51,18 +51,18 @@ class SendExpirationAlerts extends Command
->map(fn($item) => trim($item)) // Trim each email
->all();
// Expiring Assets
$assets = Asset::getExpiringWarrantee($threshold);
$assets = Asset::getExpiringWarrantee($alert_interval);
if ($assets->count() > 0) {
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count' => $assets->count(), 'threshold' => $threshold]));
Mail::to($recipients)->send(new ExpiringAssetsMail($assets, $threshold));
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count' => $assets->count(), 'threshold' => $alert_interval]));
Mail::to($recipients)->send(new ExpiringAssetsMail($assets, $alert_interval));
}
// Expiring licenses
$licenses = License::getExpiringLicenses($threshold);
$licenses = License::getExpiringLicenses($alert_interval);
if ($licenses->count() > 0) {
$this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $threshold]));
Mail::to($recipients)->send(new ExpiringLicenseMail($licenses, $threshold));
$this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $alert_interval]));
Mail::to($recipients)->send(new ExpiringLicenseMail($licenses, $alert_interval));
}
} else {
if ($settings->alert_email == '') {

View File

@@ -125,7 +125,9 @@ class Handler extends ExceptionHandler
// This is traaaaash but it handles models that are not found while using route model binding :(
// The only alternative is to set that at *each* route, which is crazypants
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
$model_name = last(explode('\\', $e->getModel()));
// This gets the MVC model name from the exception and formats in a way that's less fugly
$model_name = strtolower(implode(" ", preg_split('/(?=[A-Z])/', last(explode('\\', $e->getModel())))));
$route = str_plural(strtolower(last(explode('\\', $e->getModel())))).'.index';
// Sigh.

View File

@@ -850,8 +850,8 @@ class SettingsController extends Controller
$setting->ldap_fname_field = $request->input('ldap_fname_field');
$setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query');
$setting->ldap_version = $request->input('ldap_version', 3);
$setting->ldap_active_flag = $request->input('ldap_active_flag');
$setting->ldap_invert_active_flag = $request->input('ldap_invert_active_flag');
$setting->ldap_active_flag = $request->input('ldap_active_flag', 0);
$setting->ldap_invert_active_flag = $request->input('ldap_invert_active_flag', 0);
$setting->ldap_emp_num = $request->input('ldap_emp_num');
$setting->ldap_email = $request->input('ldap_email');
$setting->ldap_manager = $request->input('ldap_manager');

View File

@@ -33,9 +33,9 @@ class SaveUserRequest extends FormRequest
public function rules()
{
$rules = [
'department_id' => 'nullable|exists:departments,id',
'department_id' => 'nullable|integer|exists:departments,id',
'manager_id' => 'nullable|exists:users,id',
'company_id' => ['nullable','exists:companies,id']
'company_id' => ['nullable', 'integer', 'exists:companies,id']
];
switch ($this->method()) {

View File

@@ -785,7 +785,7 @@ class Asset extends Depreciable
->whereNotNull('warranty_months')
->whereNotNull('purchase_date')
->whereNull('deleted_at')
->whereRaw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) <= DATE(NOW() + INTERVAL '
->whereRaw('DATE_ADD(`purchase_date`, INTERVAL `warranty_months` MONTH) <= DATE_ADD(NOW(), INTERVAL '
. $days
. ' DAY) AND DATE_ADD(`purchase_date`, INTERVAL `warranty_months` MONTH) > NOW()')
->orderByRaw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH)')

View File

@@ -6,6 +6,8 @@ use App\Models\Setting;
use App\Notifications\AuditNotification;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use Osama\LaravelTeamsNotification\TeamsNotification;
trait Loggable
{
@@ -242,7 +244,14 @@ trait Loggable
'location' => ($location) ? $location->name : '',
'note' => $note,
];
Setting::getSettings()->notify(new AuditNotification($params));
if(Setting::getSettings()->webhook_selected === 'microsoft' && Str::contains(Setting::getSettings()->webhook_endpoint, 'workflows')){
$message = AuditNotification::toMicrosoftTeams($params);
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]);
}
else {
Setting::getSettings()->notify(new AuditNotification($params));
}
return $log;
}

View File

@@ -44,44 +44,6 @@ class ReportTemplate extends Model
$builder->where('created_by', auth()->id());
}
});
static::created(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('create');
});
static::updated(function (ReportTemplate $reportTemplate) {
$changed = [];
foreach ($reportTemplate->getDirty() as $key => $value) {
$changed[$key] = [
'old' => $reportTemplate->getOriginal($key),
'new' => $reportTemplate->getAttribute($key),
];
}
$logAction = new Actionlog();
$logAction->item_type = ReportTemplate::class;
$logAction->item_id = $reportTemplate->id;
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
});
static::deleted(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('delete');
});
}
/**

View File

@@ -247,7 +247,7 @@ class Setting extends Model
*
* @return string
*/
public function routeNotificationForSlack(): string
public function routeNotificationForSlack(): ?string
{
// At this point the endpoint is the same for everything.
// In the future this may want to be adapted for individual notifications.
@@ -259,7 +259,7 @@ class Setting extends Model
*
* @return string
*/
public function routeNotificationForMail(): string
public function routeNotificationForMail(): ?string
{
// At this point the endpoint is the same for everything.
// In the future this may want to be adapted for individual notifications.

View File

@@ -4,8 +4,13 @@ namespace App\Notifications;
use App\Models\Setting;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Channels\SlackWebhookChannel;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Str;
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsChannel;
use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
class AuditNotification extends Notification
{
@@ -35,10 +40,14 @@ class AuditNotification extends Notification
public function via()
{
$notifyBy = [];
if (Setting::getSettings()->webhook_endpoint) {
$notifyBy[] = 'slack';
if (Setting::getSettings()->webhook_selected == 'slack' || Setting::getSettings()->webhook_selected == 'general' ) {
Log::debug('use webhook');
$notifyBy[] = SlackWebhookChannel::class;
}
if (Setting::getSettings()->webhook_selected == 'microsoft' && Setting::getSettings()->webhook_endpoint) {
$notifyBy[] = MicrosoftTeamsChannel::class;
}
return $notifyBy;
}
@@ -63,4 +72,30 @@ class AuditNotification extends Notification
->fields($fields);
});
}
public static function toMicrosoftTeams($params)
{
$item = $params['item'];
$admin_user = $params['admin'];
$note = $params['note'];
$location = $params['location'];
$setting = Setting::getSettings();
if(!Str::contains($setting->webhook_endpoint, 'workflows')) {
return MicrosoftTeamsMessage::create()
->to($setting->webhook_endpoint)
->type('success')
->title(class_basename(get_class($params['item'])) . ' Audited')
->addStartGroupToSection('activityText')
->fact(trans('mail.asset'), $item)
->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->present()->fullName());
}
$message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->present()->fullName();
$details = [
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
trans('mail.notes') => $note ?: '',
trans('general.location') => $location ?: '',
];
return [$message, $details];
}
}

View File

@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v8.0.2',
'full_app_version' => 'v8.0.2 - build 17048-g44dd06161',
'build_version' => '17048',
'app_version' => 'v8.0.4',
'full_app_version' => 'v8.0.4 - build 17196-gc29bdbdac',
'build_version' => '17196',
'prerelease_version' => '',
'hash_version' => 'g44dd06161',
'full_hash' => 'v8.0.2-54-g44dd06161',
'hash_version' => 'gc29bdbdac',
'full_hash' => 'v8.0.4-29-gc29bdbdac',
'branch' => 'develop',
);

View File

@@ -12,7 +12,7 @@ return new class extends Migration
public function up(): void
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('ldap_invert_active_flag')->default(false);
$table->boolean('ldap_invert_active_flag')->default(0);
});
}

View File

@@ -0,0 +1,26 @@
<?php
use App\Models\ReportTemplate;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Support\Facades\DB;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
DB::table("action_logs")
->where("item_type", ReportTemplate::class)
->whereIn("action_type", ["create", "update", "delete"])
->delete();
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// nothing to do here...
}
};

View File

@@ -1017,6 +1017,18 @@ a.settings_button:visited,
a.settings_button:hover {
color: #3c8dbc;
}
a.label.label-default:link {
color: #307095;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:visited {
color: #23536f;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:hover {
background-color: #BBB;
color: #296282;
}
/*
* Skin: blue dark
* ----------

View File

@@ -1017,6 +1017,18 @@ a.settings_button:visited,
a.settings_button:hover {
color: #3c8dbc;
}
a.label.label-default:link {
color: #307095;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:visited {
color: #23536f;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:hover {
background-color: #BBB;
color: #296282;
}
/*
* Skin: blue dark
* ----------

View File

@@ -236,4 +236,16 @@ a.settings_button:visited,
a.settings_button:hover {
color: #3c8dbc;
}
a.label.label-default:link {
color: #307095;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:visited {
color: #23536f;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:hover {
background-color: #BBB;
color: #296282;
}

View File

@@ -236,4 +236,16 @@ a.settings_button:visited,
a.settings_button:hover {
color: #3c8dbc;
}
a.label.label-default:link {
color: #307095;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:visited {
color: #23536f;
/* Use same as Header picker, lighten by 70% */
}
a.label.label-default:hover {
background-color: #BBB;
color: #296282;
}

View File

@@ -1,7 +1,7 @@
{
"/js/build/app.js": "/js/build/app.js?id=65d7af7b9fa7fd0e05737526a0d1d282",
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=06c13e817cc022028b3f4a33c0ca303a",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=e71ef4171dee5da63af390966ac60ffc",
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=79aa889a1a6691013be6c342ca7391cd",
"/css/build/overrides.css": "/css/build/overrides.css?id=6528155ed5ed8fddf4047de7f0d0298d",
"/css/build/app.css": "/css/build/app.css?id=3422f2ca2056b952c3c361adf00c10b8",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=4ea0068716c1bb2434d87a16d51b98c9",
@@ -16,7 +16,7 @@
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=bb302302d9566adf783a2b7dc31e840c",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=a82b065847bf3cd5d713c04ee8dc86c6",
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=6ea836d8126de101081c49abbdb89417",
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/all.css": "/css/dist/all.css?id=18ebb9c284b49dcf6c8e4fdb923ad923",
@@ -92,11 +92,11 @@
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=331c85bd61ffa93af09273d1bc2add5a",
"/js/dist/bootstrap-table-locale-all.min.js": "/js/dist/bootstrap-table-locale-all.min.js?id=02dfc50d5b951dc6d260bd508968d319",
"/js/dist/bootstrap-table-en-US.min.js": "/js/dist/bootstrap-table-en-US.min.js?id=1c350eabf064c309f67d6779e5cc4afa",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=e71ef4171dee5da63af390966ac60ffc",
"/css/dist/skins/_all-skins.min.css": "/css/dist/skins/_all-skins.min.css?id=79aa889a1a6691013be6c342ca7391cd",
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=06c13e817cc022028b3f4a33c0ca303a",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=6ea836d8126de101081c49abbdb89417",
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=f677207c6cf9678eb539abecb408c374",
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=a82b065847bf3cd5d713c04ee8dc86c6",
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=da6c7997d9de2f8329142399f0ce50da",
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=bb302302d9566adf783a2b7dc31e840c",
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",

View File

@@ -156,4 +156,18 @@ a:hover {
// Link colors for the settings page
a.settings_button:link, a.settings_button:visited, a.settings_button:hover {
color: @light-blue;
}
}
a.label.label-default:link {
color: darken(#3c8dbc, 10%); /* Use same as Header picker, lighten by 70% */
}
a.label.label-default:visited {
color: darken(#3c8dbc,20%); /* Use same as Header picker, lighten by 70% */
}
a.label.label-default:hover {
background-color: #BBB;
color: darken(#3c8dbc,15%);
}

View File

@@ -369,6 +369,7 @@ return [
'label2_2d_target_help' => 'The data that will be contained in the 2D barcode',
'label2_fields' => 'Field Definitions',
'label2_fields_help' => 'Fields can be added, removed, and reordered in the left column. For each field, multiple options for Label and DataSource can be added, removed, and reordered in the right column.',
'purge_barcodes' => 'Purge Barcodes',
'help_asterisk_bold' => 'Text entered as <code>**text**</code> will be displayed as bold',
'help_blank_to_use' => 'Leave blank to use the value from <code>:setting_name</code>',
'help_default_will_use' => '<code>:default</code> will use the value from <code>:setting_name</code>. <br>Note that the value of the barcodes must comply with the respective barcode spec in order to be successfully generated. Please see <a href="https://snipe-it.readme.io/docs/barcodes">the documentation <i class="fa fa-external-link"></i></a> for more details. ',

View File

@@ -1211,7 +1211,11 @@
<a href="{{ route('components.show', $component->id) }}">{{ $component->name }}</a>
</td>
<td>{{ $component->pivot->assigned_qty }}</td>
<td>{{ trans('general.cost_each', ['amount' => Helper::formatCurrencyOutput($component->purchase_cost)]) }} </td>
<td>
@if ($component->purchase_cost!='')
{{ trans('general.cost_each', ['amount' => Helper::formatCurrencyOutput($component->purchase_cost)]) }}
@endif
</td>
<td>{{ $component->serial }}</td>
<td>
<a href="{{ route('components.checkin.show', $component->pivot->id) }}" class="btn btn-sm bg-purple hidden-print" data-tooltip="true">{{ trans('general.checkin') }}</a>

View File

@@ -157,7 +157,42 @@
<div class="tab-content">
<div class="tab-pane active" id="users">
<div class="tab-pane active" id="assets">
<h2 class="box-title">{{ trans('admin/locations/message.current_location') }}</h2>
<div class="table table-responsive">
@include('partials.asset-bulk-actions')
<table
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
data-cookie-id-table="assetsListingTable"
data-pagination="true"
data-id-table="assetsListingTable"
data-search="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
data-toolbar="#assetsBulkEditToolbar"
data-bulk-button-id="#bulkAssetEditButton"
data-bulk-form-id="#assetsBulkForm"
data-click-to-select="true"
id="assetsListingTable"
class="table table-striped snipe-table"
data-url="{{route('api.assets.index', ['location_id' => $location->id]) }}"
data-export-options='{
"fileName": "export-locations-{{ str_slug($location->name) }}-assets-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="users">
<h2 class="box-title">{{ trans('general.users') }}</h2>
<div class="table table-responsive">
@include('partials.users-bulk-actions')
@@ -188,37 +223,6 @@
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="assets">
<h2 class="box-title">{{ trans('admin/locations/message.current_location') }}</h2>
<div class="table table-responsive">
@include('partials.asset-bulk-actions')
<table
data-columns="{{ \App\Presenters\AssetPresenter::dataTableLayout() }}"
data-cookie-id-table="assetsListingTable"
data-pagination="true"
data-id-table="assetsListingTable"
data-search="true"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
data-show-refresh="true"
data-sort-order="asc"
data-toolbar="#assetsBulkEditToolbar"
data-bulk-button-id="#bulkAssetEditButton"
data-bulk-form-id="#assetsBulkForm"
data-click-to-select="true"
id="assetsListingTable"
class="table table-striped snipe-table"
data-url="{{route('api.assets.index', ['location_id' => $location->id]) }}"
data-export-options='{
"fileName": "export-locations-{{ str_slug($location->name) }}-assets-{{ date('Y-m-d') }}",
"ignoreColumn": ["actions","image","change","checkbox","checkincheckout","icon"]
}'>
</table>
</div><!-- /.table-responsive -->
</div><!-- /.tab-pane -->
<div class="tab-pane" id="assets_assigned">
<h2 class="box-title">

View File

@@ -2,7 +2,7 @@
@if (($snipeSettings->full_multiple_companies_support=='1') && (!Auth::user()->isSuperUser()))
<!-- full company support is enabled and this user isn't a superadmin -->
<div class="form-group">
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<label for="{{ $fieldname }}" class="col-md-3 control-label">{{ $translated_name }}</label>
<div class="col-md-6">
<select class="js-data-ajax" disabled="true" data-endpoint="companies" data-placeholder="{{ trans('general.select_company') }}" name="{{ $fieldname }}" style="width: 100%" id="company_select" aria-label="{{ $fieldname }}"{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@if ($company_id = old($fieldname, (isset($item)) ? $item->{$fieldname} : ''))
@@ -19,7 +19,7 @@
@else
<!-- full company support is enabled or this user is a superadmin -->
<div id="{{ $fieldname }}" class="form-group{{ $errors->has($fieldname) ? ' has-error' : '' }}">
{{ Form::label($fieldname, $translated_name, array('class' => 'col-md-3 control-label')) }}
<label for="{{ $fieldname }}" class="col-md-3 control-label">{{ $translated_name }}</label>
<div class="col-md-8">
<select class="js-data-ajax" data-endpoint="companies" data-placeholder="{{ trans('general.select_company') }}" name="{{ $fieldname }}" style="width: 100%" id="company_select"{{ (isset($multiple) && ($multiple=='true')) ? " multiple='multiple'" : '' }}>
@isset ($selected)

View File

@@ -1,7 +1,7 @@
<div class="form-group {{ $errors->has('email') ? ' has-error' : '' }}">
<label for="email" class="col-md-3 col-xs-12 control-label">{{ trans('admin/suppliers/table.email') }}</label>
<div class="col-md-8 col-xs-12">
<input type="text" name="email" id="email" value="{{ old('email', $item->email) }}" class="form-control" maxlength="191" style="width:100%; display:flex;">
<input type="text" name="email" id="email" value="{{ old('email', $item->email ?? null) }}" class="form-control" maxlength="191" style="width:100%; display:flex;">
{!! $errors->first('email', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
</div>
</div>

View File

@@ -37,7 +37,7 @@
<form
method="POST"
action="{{ request()->routeIs('report-templates.edit') ? route('report-templates.update', $template) : '/reports/custom' }}"
action="{{ request()->routeIs('report-templates.edit') ? route('report-templates.update', $template) : route('reports.post-custom') }}"
accept-charset="UTF-8"
class="form-horizontal"
id="custom-report-form"
@@ -627,7 +627,11 @@
>
<option></option>
@foreach($report_templates as $savedTemplate)
<option value="{{ $savedTemplate->id }}" @selected($savedTemplate->is(request()->route()->parameter('reportTemplate')))>
<option
value="{{ $savedTemplate->id }}"
data-route="{{ route('report-templates.show', $savedTemplate->id) }}"
@selected($savedTemplate->is(request()->route()->parameter('reportTemplate')))
>
{{ $savedTemplate->name }}
</option>
@endforeach
@@ -774,7 +778,7 @@
$('#saved_report_select')
.on('select2:select', function (event) {
window.location.href = '/reports/templates/' + event.params.data.id;
window.location.href = event.params.data.element.dataset.route;
});
$('#dataConfirmModal').on('show.bs.modal', function (event) {

View File

@@ -45,7 +45,7 @@
<label class="form-control">
<input type="checkbox" value="1" name="label2_enable"{{ ((old('label2_enable') == '1') || ($setting->label2_enable) == '1') ? ' checked="checked"' : '' }} aria-label="label2_enable">
{{ Form::label('label2_enable', trans('admin/settings/general.label2_enable')) }}
<label for="label2_enable">{{ trans('admin/settings/general.label2_enable') }}</label>
</label>
{!! $errors->first('label2_enable', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
@@ -105,7 +105,7 @@
<!-- Title -->
<div class="form-group{{ $errors->has('label2_title') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('label2_title', trans('admin/settings/general.label2_title'), ['class'=>'control-label']) }}
<label for="label2_title" class="control-label">{{trans('admin/settings/general.label2_title')}}</label>
</div>
<div class="col-md-7">
<input class="form-control" aria-label="label2_title" name="label2_title" type="text" id="label2_title" value="{{ old('label2_title', $setting->label2_title) }}">
@@ -129,7 +129,7 @@
<label class="form-control">
<input type="checkbox" value="1" name="label2_asset_logo"{{ ((old('label2_asset_logo') == '1') || ($setting->label2_asset_logo) == '1') ? ' checked="checked"' : '' }} aria-label="label2_asset_logo">
{{ Form::label('label2_asset_logo', trans('admin/settings/general.label2_asset_logo')) }}
<label for="label2_asset_logo">{{ trans('admin/settings/general.label2_asset_logo') }}</label>
</label>
<p class="help-block">
{!! trans('admin/settings/general.label2_asset_logo_help', ['setting_name' => trans('admin/settings/general.brand').' &gt; '.trans('admin/settings/general.label_logo')]) !!}
@@ -155,7 +155,7 @@
<!-- 1D Barcode Type -->
<div class="form-group{{ $errors->has('label2_1d_type') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('label2_1d_type', trans('admin/settings/general.label2_1d_type'), ['class'=>'control-label']) }}
<label for="label2_1d_type" class="control-label">{{ trans('admin/settings/general.label2_1d_type') }}</label>
</div>
<div class="col-md-7">
@php
@@ -205,7 +205,7 @@
<!-- 2D Barcode Type -->
<div class="form-group{{ $errors->has('label2_2d_type') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('label2_2d_type', trans('admin/settings/general.label2_2d_type'), ['class'=>'control-label']) }}
<label for="label2_2d_type" class="control-label">{{ trans('admin/settings/general.label2_2d_type') }}</label>
</div>
<div class="col-md-7">
@php
@@ -242,7 +242,7 @@
<!-- QR Text -->
<div class="form-group{{ $errors->has('qr_text') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('qr_text', trans('admin/settings/general.qr_text'), ['class'=>'control-label']) }}
<label for="qr_text" class="control-label">{{ trans('admin/settings/general.qr_text') }}</label>
</div>
<div class="col-md-7">
@if ($setting->qr_code == 1)
@@ -277,7 +277,7 @@
<!-- Nuke barcode cache -->
<div class="form-group">
<div class="col-md-3 text-right">
{{ Form::label('purge_barcodes', 'Purge Barcodes', ['class'=>'control-label']) }}
<label for="purge_barcodes" class="control-label">{{ trans('admin/settings/general.purge_barcodes') }}</label>
</div>
<div class="col-md-7">
<a class="btn btn-default btn-sm pull-left" id="purgebarcodes" style="margin-right: 10px;">
@@ -295,7 +295,7 @@
<!-- 2D Barcode Target -->
<div class="form-group{{ $errors->has('label2_2d_target') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('label2_2d_target', trans('admin/settings/general.label2_2d_target'), ['class'=>'control-label']) }}
<label for="label2_2d_target" class="control-label">{{ trans('admin/settings/general.label2_2d_target') }}</label>
</div>
<div class="col-md-9">
<x-input.select
@@ -316,7 +316,7 @@
<!-- Fields -->
<div class="form-group {{ $errors->has('label2_fields') ? 'error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('label2_fields', trans('admin/settings/general.label2_fields')) }}
<label for="label2_fields">{{ trans('admin/settings/general.label2_fields') }}</label>
</div>
<div class="col-md-9">
@include('partials.label2-field-definitions', [ 'name' => 'label2_fields', 'value' => old('label2_fields', $setting->label2_fields), 'customFields' => $customFields, 'template' => $setting->label2_template])
@@ -368,7 +368,7 @@
<div class="form-group{{ $errors->has('labels_per_page') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('labels_per_page', trans('admin/settings/general.labels_per_page'), ['class'=>'control-label']) }}
<label for="labels_per_page" class="control-label">{{ trans('admin/settings/general.labels_per_page') }}</label>
</div>
<div class="col-md-9">
<input class="form-control" style="width: 100px;" aria-label="labels_per_page" name="labels_per_page" type="text" value="{{ old('labels_per_page', $setting->labels_per_page) }}" id="labels_per_page">
@@ -378,7 +378,7 @@
<div class="form-group{{ $errors->has('labels_fontsize') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('labels_fontsize', trans('admin/settings/general.labels_fontsize'), ['class'=>'control-label']) }}
<label for="labels_fontsize" class="control-label">{{ trans('admin/settings/general.labels_fontsize') }}</label>
</div>
<div class="col-md-2">
<div class="input-group">
@@ -393,7 +393,7 @@
<div class="form-group{{ $errors->has('labels_width') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('labels_width', trans('admin/settings/general.label_dimensions'), ['class'=>'control-label']) }}
<label for="labels_width" class="control-label">{{ trans('admin/settings/general.label_dimensions') }}</label>
</div>
<div class="col-md-3">
<div class="input-group">
@@ -415,7 +415,7 @@
<div class="form-group{{ $errors->has('labels_display_sgutter') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('labels_display_sgutter', trans('admin/settings/general.label_gutters')) }}
<label for="labels_display_sgutter">{{ trans('admin/settings/general.label_gutters') }}</label>
</div>
<div class="col-md-3">
<div class="input-group">
@@ -437,7 +437,7 @@
<div class="form-group{{ $errors->has('labels_pmargin_top') ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('labels_pmargin_top', trans('admin/settings/general.page_padding')) }}
<label for="labels_pmargin_top">{{ trans('admin/settings/general.page_padding') }}</label>
</div>
<div class="col-md-3">
<div class="input-group" style="margin-bottom: 15px;">
@@ -468,7 +468,7 @@
<div class="form-group{{ (($errors->has('labels_pageheight')) || $errors->has('labels_pagewidth')) ? ' has-error' : '' }}">
<div class="col-md-3 text-right">
{{ Form::label('labels_pagewidth', trans('admin/settings/general.page_dimensions'), ['class'=>'control-label']) }}
<label for="labels_pagewidth" class="control-label">{{ trans('admin/settings/general.page_dimensions') }}</label>
</div>
<div class="col-md-3">
<div class="input-group">
@@ -491,7 +491,7 @@
@if(!$setting->label2_enable)
<div class="form-group">
<div class="col-md-3 text-right">
{{ Form::label('labels_display', trans('admin/settings/general.label_fields'), ['class' => 'control-label']) }}
<label for="labels_display" class="control-label">{{ trans('admin/settings/general.label_fields') }}</label>
</div>
<div class="col-md-9">
<label class="form-control">

View File

@@ -70,7 +70,7 @@
<!-- Enable LDAP -->
<div class="form-group {{ $errors->has('ldap_integration') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_enabled', trans('admin/settings/general.ldap_integration')) }}
<label for="ldap_enabled">{{ trans('admin/settings/general.ldap_integration') }}</label>
</div>
<div class="col-md-8">
@@ -92,7 +92,7 @@
<!-- AD Flag -->
<div class="form-group">
<div class="col-md-3">
{{ Form::label('is_ad', trans('admin/settings/general.ad')) }}
<label for="is_ad">{{ trans('admin/settings/general.ad') }}</label>
</div>
<div class="col-md-8">
<label class="form-control">
@@ -118,7 +118,7 @@
<!-- LDAP Password Sync -->
<div class="form-group">
<div class="col-md-3">
{{ Form::label('ldap_pw_sync', trans('admin/settings/general.ldap_pw_sync')) }}
<label for="ldap_pw_sync">{{ trans('admin/settings/general.ldap_pw_sync') }}</label>
</div>
<div class="col-md-8">
<label class="form-control">
@@ -147,7 +147,7 @@
<!-- AD Domain -->
<div class="form-group {{ $errors->has('ad_domain') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ad_domain', trans('admin/settings/general.ad_domain')) }}
<label for="ad_domain">{{ trans('admin/settings/general.ad_domain') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'example.com' }}" name="ad_domain" type="text" id="ad_domain" value="{{ old('ad_domain', $setting->ad_domain) }}">
@@ -171,7 +171,9 @@
<!-- LDAP Client-Side TLS key -->
<div class="form-group {{ $errors->has('ldap_client_tls_key') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_client_tls_key', trans('admin/settings/general.ldap_client_tls_key')) }}
<label for="ldap_client_tls_key">
{{ trans('admin/settings/general.ldap_client_tls_key') }}
</label>
</div>
<div class="col-md-8">
<x-input.textarea
@@ -198,7 +200,7 @@
<!-- LDAP Client-Side TLS certificate -->
<div class="form-group {{ $errors->has('ldap_client_tls_cert') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_client_tls_cert', trans('admin/settings/general.ldap_client_tls_cert')) }}
<label for="ldap_client_tls_cert">{{ trans('admin/settings/general.ldap_client_tls_cert') }}</label>
</div>
<div class="col-md-8">
<x-input.textarea
@@ -226,7 +228,7 @@
<!-- LDAP Server -->
<div class="form-group {{ $errors->has('ldap_server') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_server', trans('admin/settings/general.ldap_server')) }}
<label for="ldap_server">{{ trans('admin/settings/general.ldap_server') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'ldap://ldap.example.com' }}" name="ldap_server" type="text" id="ldap_server" value="{{ old('ldap_server', $setting->ldap_server) }}">
@@ -251,7 +253,7 @@
<!-- Start TLS -->
<div class="form-group">
<div class="col-md-3">
{{ Form::label('ldap_tls', trans('admin/settings/general.ldap_tls')) }}
<label for="ldap_tls">{{ trans('admin/settings/general.ldap_tls') }}</label>
</div>
<div class="col-md-8">
<label class="form-control">
@@ -277,7 +279,7 @@
<!-- Ignore LDAP Certificate -->
<div class="form-group {{ $errors->has('ldap_server_cert_ignore') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_server_cert_ignore', trans('admin/settings/general.ldap_server_cert')) }}
<label for="ldap_server_cert_ignore">{{ trans('admin/settings/general.ldap_server_cert') }}</label>
</div>
<div class="col-md-8">
<label class="form-control">
@@ -306,7 +308,7 @@
<!-- LDAP Username -->
<div class="form-group {{ $errors->has('ldap_uname') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_uname', trans('admin/settings/general.ldap_uname')) }}
<label for="ldap_uname">{{ trans('admin/settings/general.ldap_uname') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" autocomplete="off" placeholder="{{ trans('general.example') .'binduser@example.com' }}" name="ldap_uname" type="text" id="ldap_uname" value="{{ old('ldap_uname', $setting->ldap_uname) }}">
@@ -329,7 +331,7 @@
<!-- LDAP pword -->
<div class="form-group {{ $errors->has('ldap_pword') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_pword', trans('admin/settings/general.ldap_pword')) }}
<label for="ldap_pword">{{ trans('admin/settings/general.ldap_pword') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" type="password" name="ldap_pword" id="ldap_pword" value="" autocomplete="off" onfocus="this.removeAttribute('readonly');" readonly>
@@ -352,7 +354,7 @@
<!-- LDAP basedn -->
<div class="form-group {{ $errors->has('ldap_basedn') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_basedn', trans('admin/settings/general.ldap_basedn')) }}
<label for="ldap_basedn">{{ trans('admin/settings/general.ldap_basedn') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'cn=users/authorized,dc=example,dc=com' }}" name="ldap_basedn" type="text" id="ldap_basedn" value="{{ old('ldap_basedn', $setting->ldap_basedn) }}">
@@ -375,7 +377,7 @@
<!-- LDAP filter -->
<div class="form-group {{ $errors->has('ldap_filter') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_filter', trans('admin/settings/general.ldap_filter')) }}
<label for="ldap_filter">{{ trans('admin/settings/general.ldap_filter') }}</label>
</div>
<div class="col-md-8">
<input type="text" name="ldap_filter" id="ldap_filter" value="{{ old('ldap_filter', $setting->ldap_filter) }}" class="form-control" placeholder="{{ trans('general.example') .'&(cn=*)' }}">
@@ -398,7 +400,7 @@
<!-- LDAP username field-->
<div class="form-group {{ $errors->has('ldap_username_field') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_username_field', trans('admin/settings/general.ldap_username_field')) }}
<label for="ldap_username_field">{{ trans('admin/settings/general.ldap_username_field') }}</label>
</div>
<div class="col-md-8">
<input type="text" name="ldap_username_field" id="ldap_username_field" value="{{ old('ldap_username_field', $setting->ldap_username_field) }}" class="form-control" placeholder="{{ trans('general.example') .'samaccountname' }}">
@@ -421,7 +423,7 @@
<!-- LDAP Last Name Field -->
<div class="form-group {{ $errors->has('ldap_lname_field') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_lname_field', trans('admin/settings/general.ldap_lname_field')) }}
<label for="ldap_lname_field">{{ trans('admin/settings/general.ldap_lname_field') }}</label>
</div>
<div class="col-md-8">
<input type="text" name="ldap_lname_field" id="ldap_lname_field" value="{{ old('ldap_lname_field', $setting->ldap_lname_field) }}" class="form-control" placeholder="{{ trans('general.example') .'sn' }}">
@@ -444,7 +446,7 @@
<!-- LDAP First Name field -->
<div class="form-group {{ $errors->has('ldap_fname_field') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_fname_field', trans('admin/settings/general.ldap_fname_field')) }}
<label for="ldap_fname_field">{{ trans('admin/settings/general.ldap_fname_field') }}</label>
</div>
<div class="col-md-8">
<input type="text" name="ldap_fname_field" id="ldap_fname_field" value="{{ old('ldap_fname_field', $setting->ldap_fname_field) }}" class="form-control" placeholder="{{ trans('general.example') .'givenname' }}">
@@ -492,7 +494,7 @@
<div class="form-group{{ $errors->has('group') ? ' has-error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_default_group', trans('admin/settings/general.ldap_default_group')) }}
<label for="ldap_default_group">{{ trans('admin/settings/general.ldap_default_group') }}</label>
</div>
<div class="col-md-8">
@@ -532,7 +534,7 @@
<!-- LDAP active flag -->
<div class="form-group {{ $errors->has('ldap_active_flag') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_active_flag', trans('admin/settings/general.ldap_active_flag')) }}
<label for="ldap_active_flag">{{ trans('admin/settings/general.ldap_active_flag') }}</label>
</div>
<div class="col-md-8">
<input type="text" name="ldap_active_flag" id="ldap_active_flag" value="{{ old('ldap_active_flag', $setting->ldap_active_flag) }}" class="form-control">
@@ -557,33 +559,40 @@
<!-- LDAP invert active flag -->
<div class="form-group">
<div class="col-md-3">
{{ Form::label('ldap_invert_active_flag', trans('admin/settings/general.ldap_invert_active_flag')) }}
<label for="ldap_invert_active_flag">
{{ trans('admin/settings/general.ldap_invert_active_flag') }}
</label>
</div>
<div class="col-md-8">
<label class="form-control">
<input type="checkbox" name="ldap_invert_active_flag" value="1" id="ldap_invert_active_flag" @checked(old('ldap_invert_active_flag', $setting->ldap_invert_active_flag)) />
<p class="help-block">{!! trans('admin/settings/general.ldap_invert_active_flag_help') !!}</p>
{{ trans('general.yes') }}
</label>
@error('ldap_invert_active_flag')
<span class="alert-msg">
<span class="alert-msg">
<x-icon type="x" />
{{ $message }}
</span>
@enderror
<p class="help-block">
{!! trans('admin/settings/general.ldap_invert_active_flag_help') !!}
</p>
@if (config('app.lock_passwords')===true)
<p class="text-warning">
<x-icon type="locked" />
{{ trans('general.feature_disabled') }}
{!! trans('general.feature_disabled') !!}
</p>
@endif
</div>
</div>
<!-- LDAP emp number -->
<div class="form-group {{ $errors->has('ldap_emp_num') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_emp_num', trans('admin/settings/general.ldap_emp_num')) }}
<label for="ldap_emp_num">{{ trans('admin/settings/general.ldap_emp_num') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'employeenumber/employeeid' }}" name="ldap_emp_num" type="text" id="ldap_emp_num" value="{{ old('ldap_emp_num', $setting->ldap_emp_num) }}">
@@ -605,7 +614,7 @@
<!-- LDAP department -->
<div class="form-group {{ $errors->has('ldap_dept') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_dept', trans('admin/settings/general.ldap_dept')) }}
<label for="ldap_dept">{{ trans('admin/settings/general.ldap_dept') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'department' }}" name="ldap_dept" type="text" id="ldap_dept" value="{{ old('ldap_dept', $setting->ldap_dept) }}">
@@ -628,7 +637,7 @@
<!-- LDAP Manager -->
<div class="form-group {{ $errors->has('ldap_dept') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_dept', trans('admin/settings/general.ldap_manager')) }}
<label for="ldap_manager">{{ trans('admin/settings/general.ldap_manager') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder=" {{ trans('general.example') .'manager' }}" name="ldap_manager" type="text" value="{{ old('ldap_manager', $setting->ldap_manager) }}">
@@ -651,7 +660,7 @@
<!-- LDAP email -->
<div class="form-group {{ $errors->has('ldap_email') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_email', trans('admin/settings/general.ldap_email')) }}
<label for="ldap_email">{{ trans('admin/settings/general.ldap_email') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'mail' }}" name="ldap_email" type="text" id="ldap_email" value="{{ old('ldap_email', $setting->ldap_email) }}">
@@ -674,7 +683,7 @@
<!-- LDAP Phone -->
<div class="form-group {{ $errors->has('ldap_phone') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_phone', trans('admin/settings/general.ldap_phone')) }}
<label for="ldap_phone">{{ trans('admin/settings/general.ldap_phone') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'telephonenumber' }}" name="ldap_phone" type="text" id="ldap_phone" value="{{ old('ldap_phone', $setting->ldap_phone_field) }}">
@@ -697,7 +706,7 @@
<!-- LDAP Job title -->
<div class="form-group {{ $errors->has('ldap_jobtitle') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_jobtitle', trans('admin/settings/general.ldap_jobtitle')) }}
<label for="ldap_jobtitle">{{ trans('admin/settings/general.ldap_jobtitle') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'title' }}" name="ldap_jobtitle" type="text" id="ldap_jobtitle" value="{{ old('ldap_jobtitle', $setting->ldap_jobtitle) }}">
@@ -720,7 +729,7 @@
<!-- LDAP Country -->
<div class="form-group {{ $errors->has('ldap_country') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_country', trans('admin/settings/general.ldap_country')) }}
<label for="ldap_country">{{ trans('admin/settings/general.ldap_country') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'c' }}" name="ldap_country" type="text" id="ldap_country" value="{{ old('ldap_country', $setting->ldap_country) }}">
@@ -742,7 +751,7 @@
<!-- LDAP Location -->
<div class="form-group {{ $errors->has('ldap_location') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('ldap_location', trans('admin/settings/general.ldap_location')) }}
<label for="ldap_location">{{ trans('admin/settings/general.ldap_location') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'physicaldeliveryofficename' }}" name="ldap_location" type="text" id="ldap_location" value="{{ old('ldap_location', $setting->ldap_location) }}">
@@ -825,7 +834,7 @@
<!-- LDAP Forgotten password -->
<div class="form-group {{ $errors->has('custom_forgot_pass_url') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('custom_forgot_pass_url', trans('admin/settings/general.custom_forgot_pass_url')) }}
<label for="custom_forgot_pass_url">{{ trans('admin/settings/general.custom_forgot_pass_url') }}</label>
</div>
<div class="col-md-8">
<input class="form-control" placeholder="{{ trans('general.example') .'https://my.ldapserver-forgotpass.com' }}" name="custom_forgot_pass_url" type="text" id="custom_forgot_pass_url" value="{{ old('custom_forgot_pass_url', $setting->custom_forgot_pass_url) }}">

View File

@@ -532,7 +532,8 @@ Route::group(['prefix' => 'reports', 'middleware' => ['auth']], function () {
$trail->parent('home')
->push(trans('general.custom_report'), route('reports/custom')));
Route::post('custom', [ReportsController::class, 'postCustom']);
Route::post('custom', [ReportsController::class, 'postCustom'])
->name('reports.post-custom');
Route::prefix('templates')

View File

@@ -0,0 +1,60 @@
<?php
namespace Tests\Feature\Modals\Ui;
use App\Models\User;
use Tests\TestCase;
class ShowModalsTest extends TestCase
{
public function testUserModalRenders()
{
$this->actingAs(User::factory()->createUsers()->create())
->get('modals/user')
->assertOk();
}
public function testDepartmentModalRenders()
{
$this->actingAs(User::factory()->superuser()->create())
->get('modals/model')
->assertOk();
}
public function testStatusLabelModalRenders()
{
$this->actingAs(User::factory()->superuser()->create())
->get('modals/statuslabel')
->assertOk();
}
public function testLocationModalRenders()
{
$this->actingAs(User::factory()->superuser()->create())
->get('modals/location')
->assertOk();
}
public function testCategoryModalRenders()
{
$this->actingAs(User::factory()->superuser()->create())
->get('modals/category')
->assertOk();
}
public function testManufacturerModalRenders()
{
$this->actingAs(User::factory()->superuser()->create())
->get('modals/manufacturer')
->assertOk();
}
public function testSupplierModalRenders()
{
$this->actingAs(User::factory()->superuser()->create())
->get('modals/supplier')
->assertOk();
}
}

View File

@@ -26,20 +26,21 @@ class ExpiringAlertsNotificationTest extends TestCase
$alert_email = Setting::first()->alert_email;
$expiringAsset = Asset::factory()->create([
'purchase_date' => now()->subMonths(11)->format('Y-m-d'),
'purchase_date' => now()->subDays(350)->format('Y-m-d'),
'warranty_months' => 12,
'archived' => 0,
'deleted_at' => null,
]);
$expiredAsset = Asset::factory()->create([
'purchase_date' => now()->subMonths(13)->format('Y-m-d'),
'purchase_date' => now()->subDays(370)->format('Y-m-d'),
'warranty_months' => 12,
'archived' => 0,
'deleted_at' => null,
]);
$notExpiringAsset = Asset::factory()->create([
'purchase_date' => now()->subMonths(10)->format('Y-m-d'),
'purchase_date' => now()->subDays(330)->format('Y-m-d'),
'warranty_months' => 12,
'archived' => 0,
'deleted_at' => null,

View File

@@ -28,6 +28,7 @@ class LdapSettingsTest extends TestCase
'ldap_basedn' => 'uid=',
'ldap_fname_field' => 'SomeFirstnameField',
'ldap_server' => 'ldaps://ldap.example.com',
'ldap_invert_active_flag' => 0,
]))
->assertStatus(302)
->assertValid('ldap_enabled')

View File

@@ -0,0 +1,78 @@
<?php
namespace Tests\Feature\Users\Api;
use App\Models\Company;
use App\Models\Department;
use App\Models\User;
use Illuminate\Testing\Fluent\AssertableJson;
use Tests\TestCase;
class StoreUsersTest extends TestCase
{
public function testRequiresPermission()
{
$this->actingAsForApi(User::factory()->create())
->postJson(route('api.users.store'), [
'first_name' => 'Joe',
'username' => 'joe',
'password' => 'joe_password',
'password_confirmation' => 'joe_password',
])
->assertForbidden();
}
public function testCompanyIdNeedsToBeInteger()
{
$company = Company::factory()->create();
$this->actingAsForApi(User::factory()->createUsers()->create())
->postJson(route('api.users.store'), [
'company_id' => [$company->id],
'first_name' => 'Joe',
'username' => 'joe',
'password' => 'joe_password',
'password_confirmation' => 'joe_password',
])
->assertStatusMessageIs('error')
->assertJson(function (AssertableJson $json) {
$json->has('messages.company_id')->etc();
});
}
public function testDepartmentIdNeedsToBeInteger()
{
$department = Department::factory()->create();
$this->actingAsForApi(User::factory()->createUsers()->create())
->postJson(route('api.users.store'), [
'department_id' => [$department->id],
'first_name' => 'Joe',
'username' => 'joe',
'password' => 'joe_password',
'password_confirmation' => 'joe_password',
])
->assertStatusMessageIs('error')
->assertJson(function (AssertableJson $json) {
$json->has('messages.department_id')->etc();
});
}
public function testCanStoreUser()
{
$this->actingAsForApi(User::factory()->createUsers()->create())
->postJson(route('api.users.store'), [
'first_name' => 'Darth',
'username' => 'darthvader',
'password' => 'darth_password',
'password_confirmation' => 'darth_password',
])
->assertStatusMessageIs('success')
->assertOk();
$this->assertDatabaseHas('users', [
'first_name' => 'Darth',
'username' => 'darthvader',
]);
}
}

View File

@@ -1,71 +0,0 @@
<?php
namespace Tests\Unit\ActionLogTransformer;
use App\Http\Transformers\ActionlogsTransformer;
use App\Models\Actionlog;
use App\Models\ReportTemplate;
use PHPUnit\Framework\Attributes\Group;
use Tests\TestCase;
#[Group('activity-logging')]
class ReportTemplateActionLogTransformerTest extends TestCase
{
public function testLogEntryForCreatingReportTemplateCanBeTransformed()
{
ReportTemplate::factory()->create();
$actionLogs = Actionlog::query()
->whereMorphedTo('item', ReportTemplate::class)
->where('action_type', 'create')
->get();
// should be created when ActionLog is created
$this->assertCount(1, $actionLogs);
$results = (new ActionlogsTransformer())->transformActionlogs($actionLogs, 10);
$this->assertArrayHasKey('rows', $results);
$this->assertCount(1, $results['rows']);
}
public function testLogEntryForUpdatingReportTemplateCanBeDisplayedTransformed()
{
$reportTemplate = ReportTemplate::factory()->create();
$reportTemplate->update([
'options' => ['new' => 'value']
]);
$actionLogs = Actionlog::query()
->whereMorphedTo('item', ReportTemplate::class)
->where('action_type', 'update')
->get();
$this->assertCount(1, $actionLogs);
$results = (new ActionlogsTransformer())->transformActionlogs($actionLogs, 10);
$this->assertArrayHasKey('rows', $results);
$this->assertCount(1, $results['rows']);
}
public function testLogEntryForDeletingReportTemplateCanBeDisplayedTransformed()
{
$reportTemplate = ReportTemplate::factory()->create();
$reportTemplate->delete();
$actionLogs = Actionlog::query()
->whereMorphedTo('item', ReportTemplate::class)
->where('action_type', 'delete')
->get();
$this->assertCount(1, $actionLogs);
$results = (new ActionlogsTransformer())->transformActionlogs($actionLogs, 10);
$this->assertArrayHasKey('rows', $results);
$this->assertCount(1, $results['rows']);
}
}

View File

@@ -1,100 +0,0 @@
<?php
namespace Tests\Unit\Models\ReportTemplates;
use App\Models\ReportTemplate;
use App\Models\User;
use PHPUnit\Framework\Attributes\Group;
use Tests\TestCase;
#[Group('custom-reporting')]
#[Group('activity-logging')]
class ReportTemplateActivityLoggingTest extends TestCase
{
public function testCreatingReportTemplateIsLogged()
{
$user = User::factory()->create();
$this->actingAs($user);
$reportTemplate = ReportTemplate::factory()->create();
$this->assertDatabaseHas('action_logs', [
'created_by' => $user->id,
'action_type' => 'create',
'target_id' => null,
'target_type' => null,
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
]);
}
public function testUpdatingReportTemplateIsLogged()
{
$user = User::factory()->create();
$this->actingAs($user);
$reportTemplate = ReportTemplate::factory()->create([
'name' => 'Name A',
'options' => [
'company' => '1',
'location' => '1',
'by_company_id' => ['1'],
'by_location_id' => ['17'],
],
]);
$reportTemplate->update([
'name' => 'Another Name',
'options' => [
'company' => '1',
'by_company_id' => ['1'],
],
]);
$this->assertDatabaseHas('action_logs', [
'created_by' => $user->id,
'action_type' => 'update',
'target_id' => null,
'target_type' => null,
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'log_meta' => json_encode([
'name' => [
'old' => 'Name A',
'new' => 'Another Name'
],
'options' => [
'old' => [
'company' => '1',
'location' => '1',
'by_company_id' => ['1'],
'by_location_id' => ['17'],
],
'new' => [
'company' => '1',
'by_company_id' => ['1'],
],
],
]),
]);
}
public function testDeletingReportTemplateIsLogged()
{
$user = User::factory()->create();
$this->actingAs($user);
$reportTemplate = ReportTemplate::factory()->create();
$reportTemplate->delete();
$this->assertDatabaseHas('action_logs', [
'created_by' => $user->id,
'action_type' => 'delete',
'target_id' => null,
'target_type' => null,
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
]);
}
}