Notification improvements (#5254)

* Added “show fields in email” to custom fields

* Added “show images in email” to settings

* Added nicer HTML emails

* Break notifications out into their own, instead of trying to mash them all together

* Remove old notification for accessory checkout

* Janky fix for #5076 - “The asset you have attempted to accept was not checked out to you”

* Add method for image url for accessories

* Added accessory checkout email blade

* Make accessory email notification on checkout screen consistent with assets

* Added native consumables notifications

* Fixes for asset notification

* Updated notification blades with correct-er fields

* Updated notifications

* License checkin notification - does not work yet

Need to figure out whether the license seat is assigned to a person or an asset before we can pass the target

* Added alternate “cc” email for admins

* Only try to trigger notifications if the target is a user

* Fix tests

* Fixed consumable URL

* Removed unused notification

* Pass target type in params

* Show slack status

* Pass additional parameters

There is a logic bug in this :( Will send to slack twice, since the admin CC and the user are both using the same notification. Fuckity fuck fuck fuck.

* Pass a variable to the notification to supress the duplicate slack message

* Slack is broken :( Trying to fix

Will try a git bisect

* Put preview back into checkout

* Pulled old archaic mail

* Removed debugging

* Fixed wrong email title

* Fixed slack endpoint not firing

* Poobot, we hardly knew ye.

* Removed old, manual mail from API

* Typo :-/

* Code cleanup

* Use defined formatted date in JSON

* Use static properties for checkin/checkout notifiers for cleaner code

* Removed debugging

* Use date formatter

* Fixed target_type

* Fixed language in consumable email
This commit is contained in:
snipe 2018-03-25 13:46:57 -07:00 committed by GitHub
parent 6043d37b05
commit 46f5f21368
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
53 changed files with 1615 additions and 360 deletions

View file

@ -12,7 +12,6 @@ use DB;
use Gate;
use Input;
use Lang;
use Mail;
use Redirect;
use Illuminate\Http\Request;
use Slack;
@ -313,16 +312,6 @@ class AccessoriesController extends Controller
$data['expected_checkin'] = '';
$data['note'] = $logaction->note;
$data['require_acceptance'] = $accessory->requireAcceptance();
// TODO: Port this to new mail notifications
if ((($accessory->requireAcceptance()=='1') || ($accessory->getEula())) && ($user->email!='')) {
Mail::send('emails.accept-accessory', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_accessory_delivery'));
});
}
// Redirect to the new accessory page
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
@ -393,15 +382,6 @@ class AccessoriesController extends Controller
$data['item_tag'] = '';
$data['note'] = e($logaction->note);
if ((($accessory->checkin_email()=='1')) && ($user->email!='')) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Accessory_Checkin'));
});
}
if ($backto=='user') {
return redirect()->route("users.show", $return_to)->with('success', trans('admin/accessories/message.checkin.success'));
}

View file

@ -668,7 +668,7 @@ class AssetsController extends Controller
$asset->assigned_to = null;
$asset->assignedTo()->disassociate($asset);
$asset->accepted = null;
$asset->name = e(Input::get('name'));
$asset->name = Input::get('name');
$asset->location_id = $asset->rtd_location_id;
if ($request->has('location_id')) {
@ -676,32 +676,11 @@ class AssetsController extends Controller
}
if (Input::has('status_id')) {
$asset->status_id = e(Input::get('status_id'));
$asset->status_id = Input::get('status_id');
}
// Was the asset updated?
if ($asset->save()) {
$logaction = $asset->logCheckin($target, e(request('note')));
$data['log_id'] = $logaction->id;
$data['first_name'] = get_class($target) == User::class ? $target->first_name : '';
$data['item_name'] = $asset->present()->name();
$data['checkin_date'] = $logaction->created_at;
$data['item_tag'] = $asset->asset_tag;
$data['item_serial'] = $asset->serial;
$data['note'] = $logaction->note;
$data['manufacturer_name'] = $asset->model->manufacturer->name;
$data['model_name'] = $asset->model->name;
$data['model_number'] = $asset->model->model_number;
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Asset_Checkin'));
});
}
$asset->logCheckin($target, e(request('note')));
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.success')));
}

View file

@ -179,7 +179,7 @@ class ConsumablesController extends Controller
foreach ($consumable->consumableAssignments as $consumable_assignment) {
$rows[] = [
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
'created_at' => ($consumable_assignment->created_at->format('Y-m-d H:i:s')=='-0001-11-30 00:00:00') ? '' : $consumable_assignment->created_at->format('Y-m-d H:i:s'),
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : '',
];
}

View file

@ -591,14 +591,6 @@ class AssetsController extends Controller
$data['model_name'] = $asset->model->name;
$data['model_number'] = $asset->model->model_number;
if ((($asset->checkin_email()=='1')) && (isset($user)) && (!empty($user->email)) && (!config('app.lock_passwords'))) {
Mail::send('emails.checkin-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_Asset_Checkin'));
});
}
if ($backto=='user') {
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
}

View file

@ -7,13 +7,11 @@ use App\Models\Company;
use App\Models\Consumable;
use App\Models\Setting;
use App\Models\User;
use App\Notifications\CheckoutNotification;
use Auth;
use Config;
use DB;
use Input;
use Lang;
use Mail;
use Redirect;
use Slack;
use Str;
@ -279,14 +277,6 @@ class ConsumablesController extends Controller
$data['note'] = $logaction->note;
$data['require_acceptance'] = $consumable->requireAcceptance();
if ((($consumable->requireAcceptance()=='1') || ($consumable->getEula())) && $user->email!='') {
Mail::send('emails.accept-asset', $data, function ($m) use ($user) {
$m->to($user->email, $user->first_name . ' ' . $user->last_name);
$m->replyTo(config('mail.reply_to.address'), config('mail.reply_to.name'));
$m->subject(trans('mail.Confirm_consumable_delivery'));
});
}
// Redirect to the new consumable page
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));

View file

@ -78,6 +78,7 @@ class CustomFieldsController extends Controller
"help_text" => $request->get("help_text"),
"field_values" => $request->get("field_values"),
"field_encrypted" => $request->get("field_encrypted", 0),
"show_in_email" => $request->get("show_in_email", 0),
"user_id" => Auth::user()->id
]);

View file

@ -419,6 +419,8 @@ class LicensesController extends Controller
if (!$return_to) {
$return_to = Asset::find($licenseSeat->asset_id);
}
\Log::debug($licenseSeat->assigned_to);
// Update the asset data
$licenseSeat->assigned_to = null;
$licenseSeat->asset_id = null;

View file

@ -335,6 +335,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->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');
$setting->email_domain = $request->input('email_domain');
@ -577,8 +578,11 @@ class SettingsController extends Controller
$alert_email = rtrim($request->input('alert_email'), ',');
$alert_email = trim($alert_email);
$admin_cc_email = rtrim($request->input('admin_cc_email'), ',');
$admin_cc_email = trim($admin_cc_email);
$setting->alert_email = $alert_email;
$setting->admin_cc_email = $admin_cc_email;
$setting->alerts_enabled = $request->input('alerts_enabled', '0');
$setting->alert_interval = $request->input('alert_interval');
$setting->alert_threshold = $request->input('alert_threshold');

View file

@ -297,10 +297,12 @@ class ViewAssetsController extends Controller
$user = Auth::user();
if ($user->id != $findlog->item->assigned_to) {
// TODO - Fix this for non-assets
if (($findlog->item_type==Asset::class) && ($user->id != $findlog->item->assigned_to)) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
$item = $findlog->item;
// Check if the asset exists
@ -336,7 +338,7 @@ class ViewAssetsController extends Controller
$user = Auth::user();
if ($user->id != $findlog->item->assigned_to) {
if (($findlog->item_type==Asset::class) && ($user->id != $findlog->item->assigned_to)) {
return redirect()->to('account/view-assets')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
@ -388,9 +390,11 @@ class ViewAssetsController extends Controller
->where('id', $findlog->id)
->update(array('accepted_id' => $logaction->id));
if (($findlog->item_id!='') && ($findlog->item_type==Asset::class)) {
$affected_asset = $logaction->item;
$affected_asset->accepted = $accepted;
$affected_asset->save();
}
if ($update_checkout) {
return redirect()->to('account/view-assets')->with('success', $return_msg);

View file

@ -4,6 +4,8 @@ namespace App\Models;
use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Notifications\CheckinAccessoryNotification;
use App\Notifications\CheckoutAccessoryNotification;
/**
* Model for Accessories.
@ -23,6 +25,13 @@ class Accessory extends SnipeModel
'requestable' => 'boolean'
];
/**
* Set static properties to determine which checkout/checkin handlers we should use
*/
public static $checkoutClass = CheckoutAccessoryNotification::class;
public static $checkinClass = CheckinAccessoryNotification::class;
/**
* Accessory validation rules
*/
@ -68,6 +77,8 @@ class Accessory extends SnipeModel
];
public function supplier()
{
return $this->belongsTo('\App\Models\Supplier', 'supplier_id');
@ -106,6 +117,13 @@ class Accessory extends SnipeModel
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Accessory::class)->orderBy('created_at', 'desc')->withTrashed();
}
public function getImageUrl() {
if ($this->image) {
return url('/').'/uploads/accessories/'.$this->image;
}
return false;
}
public function users()
{

View file

@ -13,6 +13,8 @@ use Log;
use Watson\Validating\ValidatingTrait;
use Illuminate\Notifications\Notifiable;
use DB;
use App\Notifications\CheckinAssetNotification;
use App\Notifications\CheckoutAssetNotification;
/**
* Model for Assets.
@ -27,20 +29,28 @@ class Asset extends Depreciable
const LOCATION = 'location';
const ASSET = 'asset';
const USER = 'user';
/**
* The database table used by the model.
*
* @var string
*/
/**
* Set static properties to determine which checkout/checkin handlers we should use
*/
public static $checkoutClass = CheckoutAssetNotification::class;
public static $checkinClass = CheckinAssetNotification::class;
/**
* The database table used by the model.
*
* @var string
*/
protected $table = 'assets';
/**
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
* is not set in the model it will default to true.
*
* @var boolean
*/
/**
* Whether the model should inject it's identifier to the unique
* validation rules before attempting validation. If this property
* is not set in the model it will default to true.
*
* @var boolean
*/
protected $injectUniqueIdentifier = true;
// We set these as protected dates so that they will be easily accessible via Carbon

View file

@ -4,6 +4,7 @@ namespace App\Models;
use App\Presenters\Presentable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
use App\Notifications\CheckoutConsumableNotification;
class Consumable extends SnipeModel
{
@ -18,6 +19,11 @@ class Consumable extends SnipeModel
'requestable' => 'boolean'
];
/**
* Set static properties to determine which checkout/checkin handlers we should use
*/
public static $checkoutClass = CheckoutConsumableNotification::class;
public static $checkinClass = null;
/**
@ -109,6 +115,14 @@ class Consumable extends SnipeModel
return $this->hasMany('\App\Models\Actionlog', 'item_id')->where('item_type', Consumable::class)->orderBy('created_at', 'desc')->withTrashed();
}
public function getImageUrl() {
if ($this->image) {
return url('/').'/uploads/consumables/'.$this->image;
}
return false;
}
public function users()
{

View file

@ -4,6 +4,8 @@ namespace App\Models;
use App\Models\Loggable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Notifications\CheckoutLicenseNotification;
use App\Notifications\CheckinLicenseNotification;
class LicenseSeat extends Model implements ICompanyableChild
{
@ -15,6 +17,12 @@ class LicenseSeat extends Model implements ICompanyableChild
protected $guarded = 'id';
protected $table = 'license_seats';
/**
* Set static properties to determine which checkout/checkin handlers we should use
*/
public static $checkoutClass = CheckoutLicenseNotification::class;
public static $checkinClass = CheckinLicenseNotification::class;
public function getCompanyableParents()
{
return ['asset', 'license'];

View file

@ -6,11 +6,17 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\CheckoutRequest;
use App\Models\User;
use App\Notifications\CheckinNotification;
use App\Notifications\CheckinAssetNotification;
use App\Notifications\AuditNotification;
use App\Notifications\CheckoutNotification;
use App\Notifications\CheckoutAssetNotification;
use App\Notifications\CheckoutAccessoryNotification;
use App\Notifications\CheckinAccessoryNotification;
use App\Notifications\CheckoutConsumableNotification;
use App\Notifications\CheckoutLicenseNotification;
use App\Notifications\CheckinLicenseNotification;
use Illuminate\Support\Facades\Auth;
trait Loggable
{
@ -32,6 +38,7 @@ trait Loggable
*/
public function logCheckout($note, $target /* What are we checking out to? */)
{
$settings = Setting::getSettings();
$log = new Actionlog;
$log = $this->determineLogItemType($log);
$log->user_id = Auth::user()->id;
@ -43,13 +50,11 @@ trait Loggable
$log->target_type = get_class($target);
$log->target_id = $target->id;
$target_class = get_class($target);
// Figure out what the target is
if ($target_class == Location::class) {
// We can checkout to a location
if ($log->target_type == Location::class) {
$log->location_id = $target->id;
} elseif ($target_class== Asset::class) {
} elseif ($log->target_type == Asset::class) {
$log->location_id = $target->rtd_location_id;
} else {
$log->location_id = $target->location_id;
@ -60,18 +65,25 @@ trait Loggable
$params = [
'item' => $log->item,
'target_type' => $log->target_type,
'target' => $target,
'admin' => $log->user,
'note' => $note,
'log_id' => $log->id
'log_id' => $log->id,
'settings' => $settings,
];
if ($settings = Setting::getSettings()) {
// $settings->notify(new CheckoutNotification($params));
}
// Send to the admin, if settings dictate
$recipient = new \App\Models\Recipients\AdminRecipient();
if (method_exists($target, 'notify')) {
$target->notify(new CheckoutNotification($params));
$target->notify(new static::$checkoutClass($params));
}
if ($settings->admin_cc_email!='') {
$recipient->notify(new static::$checkoutClass($params));
}
return $log;
@ -100,9 +112,11 @@ trait Loggable
*/
public function logCheckin($target, $note)
{
$settings = Setting::getSettings();
$log = new Actionlog;
$log->target_type = get_class($target);
$log->target_id = $target->id;
if (static::class == LicenseSeat::class) {
$log->item_type = License::class;
$log->item_id = $this->license_id;
@ -110,17 +124,34 @@ trait Loggable
$log->item_type = static::class;
$log->item_id = $this->id;
}
$log->location_id = null;
$log->note = $note;
$log->user_id = Auth::user()->id;
$log->logaction('checkin from');
$params = [
'target' => $target,
'item' => $log->item,
'admin' => $log->user,
'note' => $note
'note' => $note,
'target_type' => $log->target_type,
'settings' => $settings,
];
Setting::getSettings()->notify(new CheckinNotification($params));
// Send to the admin, if settings dictate
$recipient = new \App\Models\Recipients\AdminRecipient();
$checkoutClass = null;
if (method_exists($target, 'notify')) {
$target->notify(new static::$checkinClass($params));
}
if ($settings->admin_cc_email!='') {
$recipient->notify(new static::$checkinClass($params));
}
return $log;
}

View file

@ -0,0 +1,14 @@
<?php
namespace App\Models\Recipients;
use App\Models\Setting;
class AdminRecipient extends Recipient{
public function __construct()
{
$settings = Setting::getSettings();
$this->email = $settings->admin_cc_email;
}
}

View file

@ -0,0 +1,14 @@
<?php
namespace App\Models\Recipients;
use App\Models\Setting;
class AlertRecipient extends Recipient{
public function __construct()
{
$settings = Setting::getSettings();
$this->email = $settings->alert_email;
}
}

View file

@ -0,0 +1,12 @@
<?php
namespace App\Models\Recipients;
use Illuminate\Notifications\Notifiable;
abstract class Recipient {
use Notifiable;
protected $email;
}

View file

@ -17,6 +17,7 @@ class Setting extends Model
'qr_text' => 'max:31|nullable',
'logo_img' => 'mimes:jpeg,bmp,png,gif',
'alert_email' => 'email_array|nullable',
'admin_cc_email' => 'email|nullable',
'default_currency' => 'required',
'locale' => 'required',
'slack_endpoint' => 'url|required_with:slack_channel|nullable',

View file

@ -149,6 +149,18 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
return $this->last_name . ", " . $this->first_name . " (" . $this->username . ")";
}
/**
* The url for slack notifications.
* Used by Notifiable trait.
* @return mixed
*/
public function routeNotificationForSlack()
{
// At this point the endpoint is the same for everything.
// In the future this may want to be adapted for individual notifications.
$this->endpoint = \App\Models\Setting::getSettings()->slack_endpoint;
return $this->endpoint;
}
/**

View file

@ -0,0 +1,127 @@
<?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\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckinAccessoryNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->note = '';
$this->target_type = $params['target'];
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via()
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint) {
$notifyBy[] = 'slack';
}
// Make sure the target is a user and that its appropriate to send them an email
if (($this->target_type == \App\Models\User::class) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
$notifyBy[] = 'mail';
}
return $notifyBy;
}
public function toSlack()
{
$target = $this->target;
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname) ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
];
return (new SlackMessage)
->content(':arrow_down: :keyboard: Accessory Checked In')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->markdown('notifications.markdown.checkin-accessory',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
])
->subject('Accessory checked in');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -0,0 +1,126 @@
<?php
namespace App\Notifications;
use App\Models\Setting;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
class CheckinAssetNotification extends Notification
{
use Queueable;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->note = '';
$this->expected_checkin = '';
$this->target_type = $params['target_type'];
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
if ($this->item->expected_checkin) {
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
false);
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via()
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
\Log::debug('use slack');
$notifyBy[] = 'slack';
}
// Make sure the target is a user and that its appropriate to send them an email
if ((($this->target->email!='') && ($this->target_type == 'App\Models\User')) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
\Log::debug('use email');
$notifyBy[] = 'mail';
}
return $notifyBy;
}
public function toSlack()
{
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname!='') ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
trans('general.status') => $item->assetstatus->name,
trans('general.location') => $item->location->name,
];
return (new SlackMessage)
->content(':arrow_down: :computer: Asset Checked In')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail()
{
$fields = [];
// Check if the item has custom fields associated with it
if (($this->item->model) && ($this->item->model->fieldset)) {
$fields = $this->item->model->fieldset->fields;
}
$message = (new MailMessage)->markdown('notifications.markdown.checkin-asset',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
'fields' => $fields,
'expected_checkin' => $this->expected_checkin,
])
->subject('Asset checked in');
return $message;
}
}

View file

@ -0,0 +1,119 @@
<?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\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckinLicenseNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->note = '';
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
$notifyBy[] = 'slack';
}
$notifyBy[] = 'mail';
return $notifyBy;
}
public function toSlack($notifiable)
{
$target = $this->target;
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname) ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
];
return (new SlackMessage)
->content(':arrow_down: :floppy_disk: License Checked In')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->markdown('notifications.markdown.checkin-license',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
])
->subject('License checked in');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -1,97 +0,0 @@
<?php
namespace App\Notifications;
use App\Models\Setting;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class CheckinNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
//
$this->params = $params;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint) {
$notifyBy[] = 'slack';
}
$item = $this->params['item'];
if (class_basename(get_class($this->params['item']))=='Asset') {
if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance() == '1'))
|| (method_exists($item, 'getEula') && ($item->getEula()))
) {
// $notifyBy[] = 'mail';
}
}
return $notifyBy;
}
public function toSlack($notifiable)
{
return (new SlackMessage)
->success()
->content(class_basename(get_class($this->params['item'])) . " Checked In")
->attachment(function ($attachment) use ($notifiable) {
$item = $this->params['item'];
$admin_user = $this->params['admin'];
$fields = [
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>',
];
array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note'];
$attachment->title($item->name, $item->present()->viewUrl())
->fields($fields);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\sMessages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)
->line('The introduction to the notification.')
->action('Notification Action', 'https://laravel.com')
->line('Thank you for using our application!');
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -0,0 +1,136 @@
<?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\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckoutAccessoryNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->log_id = $params['log_id'];
$this->note = '';
$this->last_checkout = '';
$this->expected_checkin = '';
$this->target_type = $params['target_type'];
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
$notifyBy[] = 'slack';
}
// Make sure the target is a user and that its appropriate to send them an email
if ((($this->target->email!='') && ($this->target_type == 'App\Models\User')) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
$notifyBy[] = 'mail';
}
return $notifyBy;
}
public function toSlack($notifiable)
{
$target = $this->target;
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname) ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
];
return (new SlackMessage)
->content(':arrow_up: :keyboard: Accessory Checked Out')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
\Log::debug($this->item->getImageUrl());
$eula = $this->item->getEula();
$req_accept = $this->item->requireAcceptance();
return (new MailMessage)->markdown('notifications.markdown.checkout-accessory',
[
'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_accessory_delivery'));
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -0,0 +1,146 @@
<?php
namespace App\Notifications;
use App\Models\Setting;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
class CheckoutAssetNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->log_id = $params['log_id'];
$this->note = '';
$this->last_checkout = '';
$this->expected_checkin = '';
$this->target_type = $params['target_type'];
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
if ($this->item->last_checkout) {
$this->last_checkout = \App\Helpers\Helper::getFormattedDateObject($this->item->last_checkout, 'date',
false);
}
if ($this->item->expected_checkin) {
$this->expected_checkin = \App\Helpers\Helper::getFormattedDateObject($this->item->expected_checkin, 'date',
false);
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via()
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
\Log::debug('use slack');
$notifyBy[] = 'slack';
}
// Make sure the target is a user and that its appropriate to send them an email
if (($this->target_type == \App\Models\User::class) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
$notifyBy[] = 'mail';
}
return $notifyBy;
}
public function toSlack()
{
$target = $this->target;
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname) ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
];
if (($this->expected_checkin) && ($this->expected_checkin!='')) {
$fields['Expected Checkin'] = $this->expected_checkin;
}
return (new SlackMessage)
->content(':arrow_up: :computer: Asset Checked Out')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail()
{
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
$req_accept = method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0;
$fields = [];
// Check if the item has custom fields associated with it
if (($this->item->model) && ($this->item->model->fieldset)) {
$fields = $this->item->model->fieldset->fields;
}
$message = (new MailMessage)->markdown('notifications.markdown.checkout-asset',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'log_id' => $this->note,
'target' => $this->target,
'fields' => $fields,
'eula' => $eula,
'req_accept' => $req_accept,
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
'last_checkout' => $this->last_checkout,
'expected_checkin' => $this->expected_checkin,
])
->subject(trans('mail.Confirm_asset_delivery'));
return $message;
}
}

View file

@ -0,0 +1,130 @@
<?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\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckoutConsumableNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->log_id = $params['log_id'];
$this->note = '';
$this->last_checkout = '';
$this->expected_checkin = '';
$this->target_type = $params['target_type'];
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
$notifyBy[] = 'slack';
}
// Make sure the target is a user and that its appropriate to send them an email
if ((($this->target->email!='') && ($this->target_type == 'App\Models\User')) && (($this->item->requireAcceptance() == '1') || ($this->item->getEula())))
{
$notifyBy[] = 'mail';
}
return $notifyBy;
}
public function toSlack($notifiable)
{
$target = $this->target;
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname) ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
];
return (new SlackMessage)
->content(':arrow_up: :paperclip: Consumable Checked Out')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
\Log::debug($this->item->getImageUrl());
$eula = $this->item->getEula();
$req_accept = $this->item->requireAcceptance();
return (new MailMessage)->markdown('notifications.markdown.checkout-consumable',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'log_id' => $this->note,
'target' => $this->target,
'eula' => $eula,
'req_accept' => $req_accept,
'accept_url' => url('/').'/account/accept-asset/'.$this->log_id,
])
->subject(trans('mail.Confirm_consumable_delivery'));
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -0,0 +1,123 @@
<?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\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckoutLicenseNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
$this->target = $params['target'];
$this->item = $params['item'];
$this->admin = $params['admin'];
$this->log_id = $params['log_id'];
$this->note = '';
$this->target_type = $params['target_type'];
$this->settings = $params['settings'];
if (array_key_exists('note', $params)) {
$this->note = $params['note'];
}
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via()
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
$notifyBy[] = 'slack';
}
if ($this->target_type == \App\Models\User::class) {
$notifyBy[] = 'mail';
}
return $notifyBy;
}
public function toSlack($notifiable)
{
$target = $this->target;
$admin = $this->admin;
$item = $this->item;
$note = $this->note;
$botname = ($this->settings->slack_botname) ? $this->settings->slack_botname : 'Snipe-Bot' ;
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
];
return (new SlackMessage)
->content(':arrow_up: :floppy_disk: License Checked Out')
->from($botname)
->attachment(function ($attachment) use ($item, $note, $admin, $fields) {
$attachment->title(htmlspecialchars_decode($item->present()->name), $item->present()->viewUrl())
->fields($fields)
->content($note);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
return (new MailMessage)->markdown('notifications.markdown.checkout-license',
[
'item' => $this->item,
'admin' => $this->admin,
'note' => $this->note,
'target' => $this->target,
])
->subject(trans('mail.Confirm_license_delivery'));
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -1,133 +0,0 @@
<?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\Messages\SlackMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Support\Facades\Mail;
class CheckoutNotification extends Notification
{
use Queueable;
/**
* @var
*/
private $params;
/**
* Create a new notification instance.
*
* @param $params
*/
public function __construct($params)
{
//
$this->params = $params;
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint) {
$notifyBy[] = 'slack';
}
$item = $this->params['item'];
if (class_basename(get_class($this->params['item']))=='Asset') {
if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance() == '1'))
|| (method_exists($item, 'getEula') && ($item->getEula()))
) {
$notifyBy[] = 'mail';
}
}
return $notifyBy;
}
public function toSlack($notifiable)
{
return (new SlackMessage)
->success()
->content(class_basename(get_class($this->params['item'])) . " Checked Out")
->attachment(function ($attachment) use ($notifiable) {
$item = $this->params['item'];
$admin_user = $this->params['admin'];
$target = $this->params['target'];
$fields = [
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>'
];
array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note'];
$attachment->title($item->name, $item->present()->viewUrl())
->fields($fields);
});
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
if (class_basename(get_class($this->params['item']))=='Asset') {
//TODO: Expand for non assets.
$item = $this->params['item'];
$admin_user = $this->params['admin'];
$target = $this->params['target'];
$data = [
'eula' => method_exists($item, 'getEula') ? $item->getEula() : '',
'first_name' => $target->present()->fullName(),
'item_name' => $item->present()->name(),
'checkout_date' => $item->last_checkout,
'expected_checkin' => ($item->expected_checkin) ? $item->expected_checkin->format('Y-m-d') : '',
'item_tag' => $item->asset_tag,
'note' => $this->params['note'],
'item_serial' => $item->serial,
'require_acceptance' => method_exists($item, 'requireAcceptance') ? $item->requireAcceptance() : '',
'log_id' => $this->params['log_id'],
'manufacturer_name' => $item->model->manufacturer->name,
'model_name' => $item->model->name,
'model_number' => $item->model->model_number,
];
if ((method_exists($item, 'requireAcceptance') && ($item->requireAcceptance() == '1'))
|| (method_exists($item, 'getEula') && ($item->getEula()))
) {
return (new MailMessage)
->view('emails.accept-asset', $data)
->subject(trans('mail.Confirm_asset_delivery'));
}
}
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddDisplayInEmailToCustomFields extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->boolean('show_in_email')->default(0);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('custom_fields', function (Blueprint $table) {
$table->dropColumn('show_in_email');
});
}
}

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddShowImagesInEmailSetting extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->boolean('show_images_in_email')->default(1);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('show_images_in_email');
});
}
}

View file

@ -0,0 +1,32 @@
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class AddCcAlerts extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('settings', function (Blueprint $table) {
$table->char('admin_cc_email')->nullable()->default(null);
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn('admin_cc_email');
});
}
}

View file

@ -28,4 +28,5 @@ return array(
'create_fieldset' => 'New Fieldset',
'create_field' => 'New Custom Field',
'value_encrypted' => 'The value of this field is encrypted in the database. Only admin users will be able to view the decrypted value',
'show_in_email' => 'Include the value of this field in checkout emails sent to the user? Encrypted fields cannot be included in emails.',
);

View file

@ -4,6 +4,8 @@ return array(
'ad' => 'Active Directory',
'ad_domain' => 'Active Directory domain',
'ad_domain_help' => 'This is sometimes the same as your email domain, but not always.',
'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.',
'is_ad' => 'This is an Active Directory server',
'alert_email' => 'Send alerts to',
'alerts_enabled' => 'Email Alerts Enabled',
@ -107,6 +109,8 @@ return array(
'show_alerts_in_menu' => 'Show alerts in top menu',
'show_archived_in_list' => 'Archived Assets',
'show_archived_in_list_text' => 'Show archived assets in the "all assets" listing',
'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.',
'site_name' => 'Site Name',
'slack_botname' => 'Slack Botname',
'slack_channel' => 'Slack Channel',

View file

@ -9,6 +9,7 @@
'activity_report' => 'Activity Report',
'address' => 'Address',
'admin' => 'Admin',
'administrator' => 'Administrator',
'add_seats' => 'Added seats',
'all_assets' => 'All Assets',
'all' => 'All',

View file

@ -50,16 +50,15 @@
<div class="form-group {{ $errors->has('note') ? 'error' : '' }}">
<label for="note" class="col-md-2 control-label">{{ trans('admin/hardware/form.notes') }}</label>
<div class="col-md-7">
<textarea class="col-md-6 form-control" id="note" name="note">
{{ Input::old('note', $accessory->note) }}
</textarea>
<textarea class="col-md-6 form-control" id="note" name="note">{{ Input::old('note', $accessory->note) }}</textarea>
{!! $errors->first('note', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>
</div>
<div class="box-footer">
<a class="btn btn-link" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>
<button type="submit" class="btn btn-success pull-right"><i class="fa fa-check icon-white"></i>{{ trans('general.checkin') }}</button>
<button type="submit" class="btn btn-success pull-right"><i class="fa fa-check icon-white"></i>
{{ trans('general.checkin') }}</button>
</div>
</div> <!-- .box.box-default -->
</form>

View file

@ -53,22 +53,32 @@
@include ('partials.forms.edit.user-select', ['translated_name' => trans('general.select_user'), 'fieldname' => 'assigned_to'])
@if (($accessory->category) && ($accessory->category->require_acceptance=='1'))
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<p class="hint-block">{{ trans('admin/categories/general.required_acceptance') }}</p>
</div>
</div>
@endif
@if ($accessory->getEula())
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<p class="hint-block">{{ trans('admin/categories/general.required_eula') }}</p>
</div>
</div>
@endif
@if ($accessory->requireAcceptance() || $accessory->getEula() || ($snipeSettings->slack_endpoint!=''))
<div class="form-group notification-callout">
<div class="col-md-8 col-md-offset-3">
<div class="callout callout-info">
@if ($accessory->requireAcceptance())
<i class="fa fa-envelope"></i>
{{ trans('admin/categories/general.required_acceptance') }}
<br>
@endif
@if ($accessory->getEula())
<i class="fa fa-envelope"></i>
{{ trans('admin/categories/general.required_eula') }}
<br>
@endif
@if ($snipeSettings->slack_endpoint!='')
<i class="fa fa-slack"></i>
A slack message will be sent
@endif
</div>
</div>
</div>
@endif
</div>
<div class="box-footer">
<a class="btn btn-link" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>

View file

@ -40,21 +40,33 @@
<!-- User -->
@include ('partials.forms.edit.user-select', ['translated_name' => trans('general.select_user'), 'fieldname' => 'assigned_to', 'required'=> 'true'])
@if ($consumable->category->require_acceptance=='1')
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<p class="hint-block">{{ trans('admin/categories/general.required_acceptance') }}</p>
</div>
</div>
@endif
@if ($consumable->getEula())
<div class="form-group">
<div class="col-md-9 col-md-offset-3">
<p class="hint-block">{{ trans('admin/categories/general.required_eula') }}</p>
</div>
</div>
@endif
@if ($consumable->requireAcceptance() || $consumable->getEula() || ($snipeSettings->slack_endpoint!=''))
<div class="form-group notification-callout">
<div class="col-md-8 col-md-offset-3">
<div class="callout callout-info">
@if ($consumable->category->require_acceptance=='1')
<i class="fa fa-envelope"></i>
{{ trans('admin/categories/general.required_acceptance') }}
<br>
@endif
@if ($consumable->getEula())
<i class="fa fa-envelope"></i>
{{ trans('admin/categories/general.required_eula') }}
<br>
@endif
@if ($snipeSettings->slack_endpoint!='')
<i class="fa fa-slack"></i>
A slack message will be sent
@endif
</div>
</div>
</div>
@endif
</div> <!-- .box-body -->
<div class="box-footer">
<a class="btn btn-link" href="{{ URL::previous() }}">{{ trans('button.cancel') }}</a>

View file

@ -36,7 +36,7 @@
data-cookie-id-table="consumablesCheckedoutTable"
data-pagination="true"
data-id-table="consumablesCheckedoutTable"
data-search="true"
data-search="false"
data-side-pagination="server"
data-show-columns="true"
data-show-export="true"
@ -54,7 +54,7 @@
<thead>
<tr>
<th data-searchable="false" data-sortable="false" data-field="name">{{ trans('general.user') }}</th>
<th data-searchable="false" data-sortable="false" data-field="created_at">{{ trans('general.date') }}</th>
<th data-searchable="false" data-sortable="false" data-field="created_at" data-formatter="dateDisplayFormatter">{{ trans('general.date') }}</th>
<th data-searchable="false" data-sortable="false" data-field="admin">{{ trans('general.admin') }}</th>
</tr>
</thead>

View file

@ -104,6 +104,19 @@
@if (!$field->id)
<!-- Show in Email -->
<div class="form-group {{ $errors->has('show_in_email') ? ' has-error' : '' }}" id="show_in_email">
<div class="col-md-8 col-md-offset-4">
<label for="field_encrypted">
<input type="checkbox" name="show_in_email"class="minimal"{{ (Input::old('show_in_email') || $field->show_in_email) ? ' checked="checked"' : '' }}>
{{ trans('admin/custom_fields/general.show_in_email') }}
</label>
</div>
</div>
<!-- Encrypted -->
<div class="form-group {{ $errors->has('encrypted') ? ' has-error' : '' }}">
<div class="col-md-8 col-md-offset-4">
@ -177,10 +190,12 @@
// Checkbox handling
$('#field_encrypted').on('ifChecked', function(event){
$("#encrypt_warning").show();
$("#show_in_email").hide();
});
$('#field_encrypted').on('ifUnchecked', function(event){
$("#encrypt_warning").hide();
$("#show_in_email").show();
});
</script>

View file

@ -72,7 +72,7 @@
</div> <!-- .row-->
<div class="row">
<div class="col-md-9">
<div class="col-md-12">
<div class="box box-default">
<div class="box-header with-border">
<h3 class="box-title">{{ trans('admin/custom_fields/general.custom_fields') }}</h3>
@ -86,6 +86,7 @@
<tr>
<th>{{ trans('general.name') }}</th>
<th>Help Text</th>
<th>Email</th>
<th>DB Field</th>
<th>{{ trans('admin/custom_fields/general.field_format') }}</th>
<th>{{ trans('admin/custom_fields/general.field_element_short') }}</th>
@ -98,6 +99,7 @@
<tr>
<td>{{ $field->name }}</td>
<td>{{ $field->help_text }}</td>
<td>{!! ($field->show_in_email=='1') ? '<i class="fa fa-check text-success"></i>' : '<i class="fa fa-times text-danger"></i>' !!}</td>
<td>
<code>{{ $field->convertUnicodeDbSlug() }}</code>
@if ($field->convertUnicodeDbSlug()!=$field->db_column)

View file

@ -98,7 +98,7 @@
</div>
</div>
@if ($asset->requireAcceptance() || $asset->getEula())
@if ($asset->requireAcceptance() || $asset->getEula() || ($snipeSettings->slack_endpoint!=''))
<div class="form-group notification-callout">
<div class="col-md-8 col-md-offset-3">
<div class="callout callout-info">
@ -112,6 +112,12 @@
@if ($asset->getEula())
<i class="fa fa-envelope"></i>
{{ trans('admin/categories/general.required_eula') }}
<br>
@endif
@if ($snipeSettings->slack_endpoint!='')
<i class="fa fa-slack"></i>
A slack message will be sent
@endif
</div>
</div>

View file

@ -0,0 +1,33 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.the_following_item') }}
@if ($item->getImageUrl())
<center><img src="{{ $item->getImageUrl() }}" alt="Asset" style="max-width: 570px;"></center>
@endif
@component('mail::table')
| | |
| ------------- | ------------- |
| **{{ trans('mail.asset_name') }}** | {{ $item->name }} |
| **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if (isset($item->model_no))
| **{{ trans('general.model_no') }}** | {{ $item->model_no }} |
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@endcomponent
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -0,0 +1,47 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.the_following_item') }}
@if ($item->getImageUrl())
<center><img src="{{ $item->getImageUrl() }}" alt="Asset" style="max-width: 570px;"></center>
@endif
@component('mail::table')
| | |
| ------------- | ------------- |
| **{{ trans('mail.asset_name') }}** | {{ $item->name }} |
| **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if (isset($item->model))
| **{{ trans('general.asset_model') }}** | {{ $item->model->name }} |
@endif
@if (isset($item->model_no))
| **{{ trans('general.model_no') }}** | {{ $item->model_no }} |
@endif
@if (isset($item->serial))
| **{{ trans('mail.serial') }}** | {{ $item->serial }} |
@endif
@if (isset($last_checkout))
| **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} |
@endif
@foreach($fields as $field)
@if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0'))
| **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} |
@endif
@endforeach
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@endcomponent
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -0,0 +1,28 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.the_following_item') }}
@component('mail::table')
| | |
| ------------- | ------------- |
| **{{ trans('mail.asset_name') }}** | {{ $item->name }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if ($target->can('update', $item))
| **Key** | {{ $item->serial }} |
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@endcomponent
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -0,0 +1,54 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.new_item_checked') }}
@if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl())
<center><img src="{{ $item->getImageUrl() }}" alt="Accessory" style="max-width: 570px;"></center>
@endif
@component('mail::table')
| | |
| ------------- | ------------- |
@if (isset($checkout_date))
| **{{ trans('mail.checkout_date') }}** | {{ $checkout_date }} |
@endif
| **{{ trans('general.accessory') }}** | {{ $item->name }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if (isset($item->model_no))
| **{{ trans('general.model_no') }}** | {{ $item->model_no }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@endcomponent
@if (($req_accept == 1) && ($eula!=''))
{{ trans('mail.read_the_terms_and_click') }}
@elseif (($req_accept == 1) && ($eula==''))
{{ trans('mail.click_on_the_link_asset') }}
@elseif (($req_accept == 0) && ($eula!=''))
{{ trans('mail.read_the_terms') }}
@endif
@if ($eula)
@component('mail::panel')
{!! $eula !!}
@endcomponent
@endif
@if ($req_accept == 1)
**[ {{ trans('mail.i_have_read') }}]({{ $accept_url }})**
@endif
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -0,0 +1,69 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.new_item_checked') }}
@if (($snipeSettings->show_images_in_email =='1') && $item->getImageUrl())
<center><img src="{{ $item->getImageUrl() }}" alt="Asset" style="max-width: 570px;"></center>
@endif
@component('mail::table')
| | |
| ------------- | ------------- |
| **{{ trans('mail.asset_name') }}** | {{ $item->name }} |
| **{{ trans('mail.asset_tag') }}** | {{ $item->asset_tag }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if (isset($item->model))
| **{{ trans('general.asset_model') }}** | {{ $item->model->name }} |
@endif
@if (isset($item->model_no))
| **{{ trans('general.model_no') }}** | {{ $item->model_no }} |
@endif
@if (isset($item->serial))
| **{{ trans('mail.serial') }}** | {{ $item->serial }} |
@endif
@if (isset($last_checkout))
| **{{ trans('mail.checkout_date') }}** | {{ $last_checkout }} |
@endif
@if (isset($expected_checkin))
| **{{ trans('mail.expecting_checkin_date') }}** | {{ $expected_checkin }} |
@endif
@foreach($fields as $field)
@if (($item->{ $field->db_column_name() }!='') && ($field->show_in_email) && ($field->field_encrypted=='0'))
| **{{ $field->name }}** | {{ $item->{ $field->db_column_name() } }} |
@endif
@endforeach
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@endcomponent
@if (($req_accept == 1) && ($eula!=''))
{{ trans('mail.read_the_terms_and_click') }}
@elseif (($req_accept == 1) && ($eula==''))
{{ trans('mail.click_on_the_link_asset') }}
@elseif (($req_accept == 0) && ($eula!=''))
{{ trans('mail.read_the_terms') }}
@endif
@if ($eula)
@component('mail::panel')
{!! $eula !!}
@endcomponent
@endif
@if ($req_accept == 1)
**[ {{ trans('mail.i_have_read') }}]({{ $accept_url }})**
@endif
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -0,0 +1,51 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.new_item_checked') }}
@component('mail::table')
| | |
| ------------- | ------------- |
@if (isset($checkout_date))
| **{{ trans('mail.checkout_date') }}** | {{ $checkout_date }} |
@endif
| **{{ trans('general.consumable') }}** | {{ $item->name }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if (isset($item->model_no))
| **{{ trans('general.model_no') }}** | {{ $item->model_no }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@endcomponent
@if (($req_accept == 1) && ($eula!=''))
{{ trans('mail.read_the_terms_and_click') }}
@elseif (($req_accept == 1) && ($eula==''))
{{ trans('mail.click_on_the_link_asset') }}
@elseif (($req_accept == 0) && ($eula!=''))
{{ trans('mail.read_the_terms') }}
@endif
@if ($eula)
@component('mail::panel')
{!! $eula !!}
@endcomponent
@endif
@if ($req_accept == 1)
**[ {{ trans('mail.i_have_read') }}]({{ $accept_url }})**
@endif
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -0,0 +1,32 @@
@component('mail::message')
# {{ trans('mail.hello') }} {{ $target->present()->fullName() }},
{{ trans('mail.new_item_checked') }}
@component('mail::table')
| | |
| ------------- | ------------- |
@if (isset($checkout_date))
| **{{ trans('mail.checkout_date') }}** | {{ $checkout_date }} |
@endif
| **{{ trans('general.license') }}** | {{ $item->name }} |
@if (isset($item->manufacturer))
| **{{ trans('general.manufacturer') }}** | {{ $item->manufacturer->name }} |
@endif
@if ($target->can('update', $item))
| **Key** | {{ $item->serial }} |
@endif
@if ($note)
| **{{ trans('mail.additional_notes') }}** | {{ $note }} |
@endif
@if ($admin)
| **{{ trans('general.administrator') }}** | {{ $admin->present()->fullName() }} |
@endif
@endcomponent
Thanks,
{{ $snipeSettings->site_name }}
@endcomponent

View file

@ -79,6 +79,22 @@
</div>
</div>
<!-- Admin CC Email -->
<div class="form-group {{ $errors->has('admin_cc_email') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('admin_cc_email', trans('admin/settings/general.admin_cc_email')) }}
</div>
<div class="col-md-7">
{{ Form::text('admin_cc_email', Input::old('admin_cc_email', $setting->admin_cc_email), array('class' => 'form-control','placeholder' => 'admin@yourcompany.com')) }}
{!! $errors->first('admin_cc_email', '<span class="alert-msg">:message</span><br>') !!}
<p class="help-block">{{ trans('admin/settings/general.admin_cc_email_help') }}</p>
</div>
</div>
<!-- Alert interval -->
<div class="form-group {{ $errors->has('alert_interval') ? 'error' : '' }}">
<div class="col-md-3">

View file

@ -122,6 +122,22 @@
</div>
</div>
<!-- Load images in emails -->
<div class="form-group {{ $errors->has('show_images_in_email') ? 'error' : '' }}">
<div class="col-md-3">
{{ Form::label('show_images_in_email', trans('admin/settings/general.show_images_in_email')) }}
</div>
<div class="col-md-9">
{{ Form::checkbox('show_images_in_email', '1', Input::old('show_images_in_email', $setting->show_images_in_email),array('class' => 'minimal')) }}
{{ trans('general.yes') }}
{!! $errors->first('show_images_in_email', '<span class="alert-msg">:message</span>') !!}
<p class="help-block">
{{ trans('admin/settings/general.show_images_in_email_help') }}
</p>
</div>
</div>
<!-- Per Page -->
<div class="form-group {{ $errors->has('per_page') ? 'error' : '' }}">
<div class="col-md-3">

View file

@ -2,7 +2,8 @@
{{-- Header --}}
@slot('header')
@component('mail::header', ['url' => config('app.url')])
@if($snipeSettings::setupCompleted())
@if (($snipeSettings->show_images_in_email=='1' ) && ($snipeSettings::setupCompleted()))
@if ($snipeSettings->brand == '3')
@if ($snipeSettings->logo!='')
<img class="navbar-brand-img logo" src="{{ url('/') }}/uploads/{{ $snipeSettings->logo }}">

View file

@ -133,7 +133,6 @@ img {
background-color: #FFFFFF;
margin: 0 auto;
padding: 0;
width: 570px;
-premailer-cellpadding: 0;
-premailer-cellspacing: 0;
-premailer-width: 570px;
@ -192,7 +191,7 @@ img {
}
.content-cell {
padding: 35px;
padding: 20px;
}
/* Buttons */

View file

@ -5,7 +5,7 @@ use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Location;
use App\Models\User;
use App\Notifications\CheckoutNotification;
use App\Notifications\CheckoutAssetNotification;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Foundation\Testing\WithoutMiddleware;