2018-08-28 13:10:27 -07:00
@ push ( 'css' )
2020-04-27 22:41:33 -07:00
< link rel = " stylesheet " href = " { { url(mix('css/dist/bootstrap-table.css')) }} " >
2021-05-04 22:00:34 -07:00
2018-08-28 13:10:27 -07:00
@ endpush
2018-01-10 22:53:54 -08:00
2018-08-28 13:10:27 -07:00
@ push ( 'js' )
2021-11-19 03:12:11 -08:00
2021-05-04 22:00:34 -07:00
< script src = " { { url(mix('js/dist/bootstrap-table.js')) }} " ></ script >
2022-01-06 05:29:10 -08:00
< script nonce = " { { csrf_token() }} " >
2017-10-24 05:22:26 -07:00
$ ( function () {
2022-01-06 05:29:10 -08:00
var locale = '{{ config(' app . locale ') }}' ;
2021-05-04 22:00:34 -07:00
2017-10-24 05:22:26 -07:00
var stickyHeaderOffsetY = 0 ;
if ( $ ( '.navbar-fixed-top' ) . css ( 'height' ) ) {
stickyHeaderOffsetY = + $ ( '.navbar-fixed-top' ) . css ( 'height' ) . replace ( 'px' , '' );
}
if ( $ ( '.navbar-fixed-top' ) . css ( 'margin-bottom' ) ) {
stickyHeaderOffsetY += + $ ( '.navbar-fixed-top' ) . css ( 'margin-bottom' ) . replace ( 'px' , '' );
}
2020-11-09 11:05:07 -08:00
var blockedFields = " searchable,sortable,switchable,title,visible,formatter,class " . split ( " , " );
var keyBlocked = function ( key ) {
for ( var j in blockedFields ) {
2021-05-04 22:00:34 -07:00
if ( key === blockedFields [ j ]) {
2020-11-09 11:05:07 -08:00
return true ;
}
}
return false ;
}
2017-10-24 05:22:26 -07:00
2022-03-29 14:57:00 -07:00
$ ( '.snipe-table' ) . bootstrapTable ( 'destroy' ) . each ( function () {
2022-03-29 08:28:43 -07:00
data_export_options = $ ( this ) . attr ( 'data-export-options' );
2022-04-07 08:27:06 -07:00
export_options = data_export_options ? JSON . parse ( data_export_options ) : {};
export_options [ 'htmlContent' ] = false ; // this is already the default; but let's be explicit about it
2022-05-12 09:18:44 -07:00
export_options [ 'jspdf' ] = { " orientation " : " l " };
2022-04-07 08:27:06 -07:00
// the following callback method is necessary to prevent XSS vulnerabilities
// (this is taken from Bootstrap Tables's default wrapper around jQuery Table Export)
export_options [ 'onCellHtmlData' ] = function ( cell , rowIndex , colIndex , htmlData ) {
if ( cell . is ( 'th' )) {
return cell . find ( '.th-inner' ) . text ()
}
return htmlData
}
2022-03-29 08:28:43 -07:00
$ ( this ) . bootstrapTable ({
2018-01-10 20:34:36 -08:00
classes : 'table table-responsive table-no-bordered' ,
2018-01-10 22:53:54 -08:00
ajaxOptions : {
headers : {
'X-CSRF-TOKEN' : $ ( 'meta[name="csrf-token"]' ) . attr ( 'content' )
}
},
2018-02-16 13:22:55 -08:00
stickyHeader : true ,
2022-01-06 05:29:10 -08:00
locale : locale ,
2018-02-16 13:22:55 -08:00
stickyHeaderOffsetY : stickyHeaderOffsetY + 'px' ,
2018-01-10 20:34:36 -08:00
undefinedText : '' ,
iconsPrefix : 'fa' ,
cookie : true ,
cookieExpire : '2y' ,
mobileResponsive : true ,
maintainSelected : true ,
2018-02-16 13:22:55 -08:00
trimOnSearch : false ,
2021-05-04 22:00:34 -07:00
showSearchClearButton : true ,
2018-01-10 20:34:36 -08:00
paginationFirstText : " { { trans('general.first') }} " ,
paginationLastText : " { { trans('general.last') }} " ,
paginationPreText : " { { trans('general.previous') }} " ,
paginationNextText : " { { trans('general.next') }} " ,
2022-03-16 11:02:07 -07:00
pageList : [ '10' , '20' , '30' , '50' , '100' , '150' , '200' { !! (( config ( 'app.max_results' ) > 200 ) ? " ,'500' " : '' ) !! }{ !! (( config ( 'app.max_results' ) > 500 ) ? " ,' " . config ( 'app.max_results' ) . " ' " : '' ) !! }],
2018-02-21 05:44:41 -08:00
pageSize : {{ (( $snipeSettings -> per_page != '' ) && ( $snipeSettings -> per_page > 0 )) ? $snipeSettings -> per_page : 20 }},
2018-02-16 13:22:55 -08:00
paginationVAlign : 'both' ,
2020-11-09 11:05:07 -08:00
queryParams : function ( params ) {
var newParams = {};
for ( var i in params ) {
if ( ! keyBlocked ( i )) { // only send the field if it's not in blockedFields
newParams [ i ] = params [ i ];
}
}
return newParams ;
},
2018-01-10 20:34:36 -08:00
formatLoadingMessage : function () {
2021-11-30 20:09:29 -08:00
return '<h2><i class="fas fa-spinner fa-spin" aria-hidden="true"></i> {{ trans(' general . loading ') }} </h4>' ;
2018-01-10 20:34:36 -08:00
},
icons : {
2021-09-26 01:11:08 -07:00
advancedSearchIcon : 'fas fa-search-plus' ,
2018-01-10 20:34:36 -08:00
paginationSwitchDown : 'fa-caret-square-o-down' ,
paginationSwitchUp : 'fa-caret-square-o-up' ,
2022-06-14 17:54:18 -07:00
fullscreen : 'fa-expand' ,
2018-01-10 20:34:36 -08:00
columns : 'fa-columns' ,
2021-09-24 06:18:22 -07:00
refresh : 'fas fa-sync-alt' ,
2021-05-04 22:00:34 -07:00
export : 'fa-download' ,
clearSearch : 'fa-times'
2018-01-10 20:34:36 -08:00
},
2022-03-29 08:28:43 -07:00
exportOptions : export_options ,
2021-10-15 09:50:52 -07:00
2022-06-23 11:18:59 -07:00
exportTypes : [ 'xlsx' , 'excel' , 'csv' , 'pdf' , 'json' , 'xml' , 'txt' , 'sql' , 'doc' ],
2018-10-09 15:20:27 -07:00
onLoadSuccess : function () {
2023-04-18 01:02:36 -07:00
$ ( '[data-tooltip="true"]' ) . tooltip (); // Needed to attach tooltips after ajax call
2018-10-09 15:20:27 -07:00
}
2021-05-04 22:00:34 -07:00
2022-03-29 08:28:43 -07:00
});
2018-02-16 13:22:55 -08:00
});
});
2018-01-10 22:53:54 -08:00
2017-03-11 04:26:01 -08:00
2017-10-24 05:22:26 -07:00
2017-01-18 19:28:35 -08:00
2017-08-25 18:40:20 -07:00
function dateRowCheckStyle ( value ) {
2017-08-26 15:27:50 -07:00
if (( value . days_to_next_audit ) && ( value . days_to_next_audit < {{ $snipeSettings -> audit_warning_days ? : 0 }})) {
2017-08-25 18:40:20 -07:00
return { classes : " danger " }
}
return {};
}
2021-10-04 17:58:16 -07:00
// These methods dynamically add/remove hidden input values in the bulk actions form
$ ( '.snipe-table' ) . on ( 'check.bs.table .btSelectItem' , function ( row , $element ) {
2022-06-05 21:02:19 -07:00
var buttonName = $ ( this ) . data ( 'bulk-button-id' );
var tableId = $ ( this ) . data ( 'id-table' );
2022-06-05 20:13:51 -07:00
$ ( buttonName ) . removeAttr ( 'disabled' );
2022-10-20 19:21:09 -07:00
$ ( buttonName ) . after ( '<input id="' + tableId + '_checkbox_' + $element . id + '" type="hidden" name="ids[]" value="' + $element . id + '">' );
2017-01-18 19:28:35 -08:00
});
2022-10-20 19:06:58 -07:00
$ ( '.snipe-table' ) . on ( 'check-all.bs.table' , function ( event , rowsAfter ) {
2022-06-05 21:02:19 -07:00
var buttonName = $ ( this ) . data ( 'bulk-button-id' );
$ ( buttonName ) . removeAttr ( 'disabled' );
var tableId = $ ( this ) . data ( 'id-table' );
for ( var i in rowsAfter ) {
2022-12-20 14:57:58 -08:00
// Do not select things that were already selected
if ( $ ( '#' + tableId + '_checkbox_' + rowsAfter [ i ] . id ) . length == 0 ) {
$ ( buttonName ) . after ( '<input id="' + tableId + '_checkbox_' + rowsAfter [ i ] . id + '" type="hidden" name="ids[]" value="' + rowsAfter [ i ] . id + '">' );
}
2022-06-05 21:02:19 -07:00
}
});
2022-10-20 19:21:09 -07:00
$ ( '.snipe-table' ) . on ( 'uncheck.bs.table .btSelectItem' , function ( row , $element ) {
var tableId = $ ( this ) . data ( 'id-table' );
$ ( " # " + tableId + " _checkbox_ " + $element . id ) . remove ();
});
2021-10-04 17:58:16 -07:00
// Handle whether or not the edit button should be disabled
2017-01-18 19:28:35 -08:00
$ ( '.snipe-table' ) . on ( 'uncheck.bs.table' , function () {
2022-06-05 20:13:51 -07:00
2022-06-05 21:02:19 -07:00
var buttonName = $ ( this ) . data ( 'bulk-button-id' );
2022-06-05 20:13:51 -07:00
2022-06-05 21:02:19 -07:00
if ( $ ( this ) . bootstrapTable ( 'getSelections' ) . length == 0 ) {
2022-06-05 20:13:51 -07:00
$ ( buttonName ) . attr ( 'disabled' , 'disabled' );
2017-01-18 19:28:35 -08:00
}
});
2021-10-04 17:58:16 -07:00
$ ( '.snipe-table' ) . on ( 'uncheck-all.bs.table' , function ( event , rowsAfter , rowsBefore ) {
2022-06-05 20:13:51 -07:00
2022-06-05 21:02:19 -07:00
var buttonName = $ ( this ) . data ( 'bulk-button-id' );
2022-06-05 20:13:51 -07:00
$ ( buttonName ) . attr ( 'disabled' , 'disabled' );
2022-06-05 21:02:19 -07:00
var tableId = $ ( this ) . data ( 'id-table' );
2021-10-04 17:58:16 -07:00
for ( var i in rowsBefore ) {
2022-06-13 20:30:35 -07:00
$ ( '#' + tableId + " _checkbox_ " + rowsBefore [ i ] . id ) . remove ();
2021-10-04 17:58:16 -07:00
}
2017-01-18 19:28:35 -08:00
});
2022-06-05 20:13:51 -07:00
2021-10-04 17:58:16 -07:00
2017-01-24 21:04:38 -08:00
// This only works for model index pages because it uses the row's model ID
function genericRowLinkFormatter ( destination ) {
return function ( value , row ) {
if ( value ) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/' + destination + '/' + row . id + '">' + value + '</a>' ;
2017-01-24 21:04:38 -08:00
}
};
2017-01-18 19:28:35 -08:00
}
2017-01-24 21:04:38 -08:00
// Use this when we're introspecting into a column object and need to link
function genericColumnObjLinkFormatter ( destination ) {
return function ( value , row ) {
2017-09-29 12:03:02 -07:00
if (( value ) && ( value . status_meta )) {
2017-09-29 15:24:33 -07:00
var text_color ;
var icon_style ;
2018-01-15 21:03:26 -08:00
var text_help ;
2018-01-23 18:08:54 -08:00
var status_meta = {
'deployed' : '{{ strtolower(trans(' general . deployed ')) }}' ,
'deployable' : '{{ strtolower(trans(' admin / hardware / general . deployable ')) }}' ,
2022-06-23 17:32:39 -07:00
'archived' : '{{ strtolower(trans(' general . archived ')) }}' ,
2018-01-23 18:08:54 -08:00
'pending' : '{{ strtolower(trans(' general . pending ')) }}'
}
2017-09-29 15:24:33 -07:00
switch ( value . status_meta ) {
2018-01-23 18:08:54 -08:00
case 'deployed' :
2017-09-29 15:24:33 -07:00
text_color = 'blue' ;
icon_style = 'fa-circle' ;
2018-01-15 21:03:26 -08:00
text_help = '<label class="label label-default">{{ trans(' general . deployed ') }}</label>' ;
2017-09-29 15:24:33 -07:00
break ;
2018-01-23 18:08:54 -08:00
case 'deployable' :
2017-09-29 15:24:33 -07:00
text_color = 'green' ;
icon_style = 'fa-circle' ;
2018-01-15 21:03:26 -08:00
text_help = '' ;
2017-09-29 15:24:33 -07:00
break ;
2018-01-23 18:08:54 -08:00
case 'pending' :
2017-09-29 15:24:33 -07:00
text_color = 'orange' ;
icon_style = 'fa-circle' ;
2018-01-15 21:03:26 -08:00
text_help = '' ;
2017-09-29 15:24:33 -07:00
break ;
default :
text_color = 'red' ;
icon_style = 'fa-times' ;
2018-01-15 21:03:26 -08:00
text_help = '' ;
2017-09-29 15:24:33 -07:00
}
2023-04-18 02:44:50 -07:00
return '<nobr><a href="{{ config(' app . url ') }}/' + destination + '/' + value . id + '" data-tooltip="true" title="' + status_meta [ value . status_meta ] + '"> <i class="fa ' + icon_style + ' text-' + text_color + '"></i> ' + value . name + ' ' + text_help + ' </a> </nobr>' ;
2017-09-28 21:18:00 -07:00
} else if (( value ) && ( value . name )) {
2018-05-29 10:41:46 -07:00
// Add some overrides for any funny urls we have
var dest = destination ;
2021-03-01 13:08:29 -08:00
var dpolymorphicItemFormatterest = '' ;
2018-05-29 10:41:46 -07:00
if ( destination == 'fieldsets' ) {
2021-03-01 13:08:29 -08:00
var dpolymorphicItemFormatterest = 'fields/' ;
2018-05-29 10:41:46 -07:00
}
2023-04-05 16:05:40 -07:00
return '<nobr><a href="{{ config(' app . url ') }}/' + dpolymorphicItemFormatterest + dest + '/' + value . id + '">' + value . name + '</a></span>' ;
2017-01-24 21:04:38 -08:00
}
};
2017-01-18 19:28:35 -08:00
}
2019-05-05 19:32:52 -07:00
function hardwareAuditFormatter ( value , row ) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/hardware/audit/' + row . id + '/" class="btn btn-sm bg-yellow" data-tooltip="true" title="Audit this item">{{ trans(' general . audit ') }}</a>' ;
2019-05-05 19:32:52 -07:00
}
2017-01-24 22:25:17 -08:00
// Make the edit/delete buttons
2021-01-05 19:25:30 -08:00
function genericActionsFormatter ( owner_name , element_name ) {
if ( ! element_name ) {
element_name = '' ;
}
2017-01-24 21:04:38 -08:00
return function ( value , row ) {
2017-02-08 18:21:03 -08:00
var actions = '<nobr>' ;
2018-05-29 10:41:46 -07:00
// Add some overrides for any funny urls we have
2018-10-31 06:06:38 -07:00
var dest = owner_name ;
2018-05-29 10:41:46 -07:00
2018-10-31 06:06:38 -07:00
if ( dest == 'groups' ) {
2017-10-19 02:22:05 -07:00
var dest = 'admin/groups' ;
}
2018-05-29 10:41:46 -07:00
2018-10-31 06:06:38 -07:00
if ( dest == 'maintenances' ) {
2018-02-16 13:22:55 -08:00
var dest = 'hardware/maintenances' ;
}
2017-10-19 02:22:05 -07:00
2018-10-31 06:06:38 -07:00
if ( element_name != '' ) {
dest = dest + '/' + row . owner_id + '/' + element_name ;
2018-10-19 07:30:25 -07:00
}
2017-07-07 18:45:49 -07:00
if (( row . available_actions ) && ( row . available_actions . clone === true )) {
2023-04-18 11:28:35 -07:00
actions += '<a href="{{ config(' app . url ') }}/' + dest + '/' + row . id + '/clone" class="btn btn-sm btn-info" data-tooltip="true" title="{{ trans(' general . clone_item ') }}"><i class="far fa-clone" aria-hidden="true"></i><span class="sr-only">Clone</span></a> ' ;
2017-07-07 18:45:49 -07:00
}
2017-02-21 15:40:25 -08:00
if (( row . available_actions ) && ( row . available_actions . update === true )) {
2023-04-05 16:05:40 -07:00
actions += '<a href="{{ config(' app . url ') }}/' + dest + '/' + row . id + '/edit" class="btn btn-sm btn-warning" data-tooltip="true" title="{{ trans(' general . update ') }}"><i class="fas fa-pencil-alt" aria-hidden="true"></i><span class="sr-only">{{ trans(' general . update ') }}</span></a> ' ;
2017-02-08 18:21:03 -08:00
}
2017-02-21 15:40:25 -08:00
if (( row . available_actions ) && ( row . available_actions . delete === true )) {
2023-04-26 14:41:19 -07:00
// use the asset tag if no name is provided
var name_for_box = row . name
if ( row . name == '' ) {
var name_for_box = row . asset_tag
}
2023-04-05 16:05:40 -07:00
actions += '<a href="{{ config(' app . url ') }}/' + dest + '/' + row . id + '" '
2023-04-18 02:44:50 -07:00
+ ' class="btn btn-danger btn-sm delete-asset" data-tooltip="true" '
2017-02-15 23:04:49 -08:00
+ ' data-toggle="modal" '
2023-04-26 14:41:19 -07:00
+ ' data-content="{{ trans(' general . sure_to_delete ') }} ' + name_for_box + '?" '
2017-07-08 13:36:25 -07:00
+ ' data-title="{{ trans(' general . delete ') }}" onClick="return false;">'
2023-04-26 14:41:19 -07:00
+ '<i class="fas fa-trash" aria-hidden="true"></i><span class="sr-only">{{ trans(' general . delete ') }}</span></a> ' ;
2017-10-19 11:29:58 -07:00
} else {
2023-04-18 02:44:50 -07:00
actions += '<span data-tooltip="true" title="{{ trans(' general . cannot_be_deleted ') }}"><a class="btn btn-danger btn-sm delete-asset disabled" onClick="return false;"><i class="fas fa-trash"></i></a></span> ' ;
2017-02-08 18:21:03 -08:00
}
2017-09-06 17:11:43 -07:00
if (( row . available_actions ) && ( row . available_actions . restore === true )) {
2023-04-05 16:05:40 -07:00
actions += '<form style="display: inline;" method="POST" action="{{ config(' app . url ') }}/' + dest + '/' + row . id + '/restore"> ' ;
2021-10-04 17:18:26 -07:00
actions += '@csrf' ;
2023-04-18 02:44:50 -07:00
actions += '<button class="btn btn-sm btn-warning" data-tooltip="true" title="{{ trans(' general . restore ') }}"><i class="fas fa-retweet"></i></button> ' ;
2017-09-06 17:11:43 -07:00
}
2017-10-19 11:29:58 -07:00
actions += '</nobr>' ;
2017-02-08 18:21:03 -08:00
return actions ;
2017-01-24 21:04:38 -08:00
};
2017-01-18 19:28:35 -08:00
}
2017-05-23 14:32:58 -07:00
2017-10-18 06:24:36 -07:00
// This handles the icons and display of polymorphic entries
2017-05-23 14:32:58 -07:00
function polymorphicItemFormatter ( value ) {
var item_destination = '' ;
2017-09-29 17:32:16 -07:00
var item_icon ;
2017-05-23 14:32:58 -07:00
if (( value ) && ( value . type )) {
if ( value . type == 'asset' ) {
item_destination = 'hardware' ;
2021-09-26 01:11:08 -07:00
item_icon = 'fas fa-barcode' ;
2017-05-23 14:32:58 -07:00
} else if ( value . type == 'accessory' ) {
item_destination = 'accessories' ;
2021-09-24 06:38:23 -07:00
item_icon = 'far fa-keyboard' ;
2017-05-23 14:32:58 -07:00
} else if ( value . type == 'component' ) {
item_destination = 'components' ;
2021-09-24 06:38:23 -07:00
item_icon = 'far fa-hdd' ;
2017-05-23 14:32:58 -07:00
} else if ( value . type == 'consumable' ) {
item_destination = 'consumables' ;
2021-09-26 01:11:08 -07:00
item_icon = 'fas fa-tint' ;
2017-05-23 14:32:58 -07:00
} else if ( value . type == 'license' ) {
item_destination = 'licenses' ;
2021-09-24 06:38:23 -07:00
item_icon = 'far fa-save' ;
2017-05-23 14:32:58 -07:00
} else if ( value . type == 'user' ) {
item_destination = 'users' ;
2021-09-26 01:11:08 -07:00
item_icon = 'fas fa-user' ;
2017-09-05 17:54:58 -07:00
} else if ( value . type == 'location' ) {
item_destination = 'locations'
2022-06-13 18:36:13 -07:00
item_icon = 'fas fa-map-marker-alt' ;
2022-06-28 15:56:18 -07:00
} else if ( value . type == 'model' ) {
item_destination = 'models'
item_icon = '' ;
2017-05-23 14:32:58 -07:00
}
2023-01-31 17:44:09 -08:00
// display the username if it's checked out to a user, but don't do it if the username's there already
if ( value . username && ! value . name . match ( '\\(' ) && ! value . name . match ( '\\)' )) {
2023-01-09 12:58:58 -08:00
value . name = value . name + ' (' + value . username + ')' ;
}
2023-04-05 16:05:40 -07:00
return '<nobr><a href="{{ config(' app . url ') }}/' + item_destination + '/' + value . id + '" data-tooltip="true" title="' + value . type + '"><i class="' + item_icon + ' text-{{ $snipeSettings->skin!=' ' ? $snipeSettings->skin : ' blue ' }} "></i> ' + value . name + '</a></nobr>' ;
2017-05-23 14:32:58 -07:00
} else {
2017-05-23 15:06:43 -07:00
return '' ;
2017-05-23 14:32:58 -07:00
}
}
2017-11-22 06:20:28 -08:00
// This just prints out the item type in the activity report
function itemTypeFormatter ( value , row ) {
if (( row ) && ( row . item ) && ( row . item . type )) {
return row . item . type ;
}
}
2017-05-23 14:32:58 -07:00
2018-02-16 21:38:56 -08:00
// Convert line breaks to <br>
function notesFormatter ( value ) {
if ( value ) {
return value . replace ( / ( ? : \r\n | \r | \n ) / g , '<br />' );;
}
}
2018-01-10 18:58:55 -08:00
// We need a special formatter for license seats, since they don't work exactly the same
2018-01-10 20:34:36 -08:00
// Checkouts need the license ID, checkins need the specific seat ID
2018-01-10 18:58:55 -08:00
2018-01-10 20:34:36 -08:00
function licenseSeatInOutFormatter ( value , row ) {
// The user is allowed to check the license seat out and it's available
if (( row . available_actions . checkout == true ) && ( row . user_can_checkout == true ) && (( ! row . asset_id ) && ( ! row . assigned_to ))) {
2023-04-18 02:44:50 -07:00
return '<a href="{{ config(' app . url ') }}/licenses/' + row . license_id + '/checkout/' + row . id + '" class="btn btn-sm bg-maroon" data-tooltip="true" title="{{ trans(' general . checkout_tooltip ') }}">{{ trans(' general . checkout ') }}</a>' ;
2018-01-10 20:34:36 -08:00
} else {
2023-04-18 02:44:50 -07:00
return '<a href="{{ config(' app . url ') }}/licenses/' + row . id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="Check in this license seat.">{{ trans(' general . checkin ') }}</a>' ;
2018-01-10 20:34:36 -08:00
}
2018-01-10 18:58:55 -08:00
}
2017-01-24 22:25:17 -08:00
function genericCheckinCheckoutFormatter ( destination ) {
2017-01-24 21:04:38 -08:00
return function ( value , row ) {
2017-02-08 18:21:03 -08:00
// The user is allowed to check items out, AND the item is deployable
2018-01-10 18:58:55 -08:00
if (( row . available_actions . checkout == true ) && ( row . user_can_checkout == true ) && (( ! row . asset_id ) && ( ! row . assigned_to ))) {
2023-04-18 12:54:06 -07:00
2023-04-18 02:44:50 -07:00
return '<a href="{{ config(' app . url ') }}/' + destination + '/' + row . id + '/checkout" class="btn btn-sm bg-maroon" data-tooltip="true" title="{{ trans(' general . checkout_tooltip ') }}">{{ trans(' general . checkout ') }}</a>' ;
2017-02-08 18:21:03 -08:00
2023-04-18 12:54:06 -07:00
// The user is allowed to check items out, but the item is not able to be checked out
2017-03-11 12:11:24 -08:00
} else if ((( row . user_can_checkout == false )) && ( row . available_actions . checkout == true ) && ( ! row . assigned_to )) {
2023-04-18 12:54:06 -07:00
// We use slightly different language for assets versus other things, since they are the only
// item that has a status label
2023-04-18 12:59:46 -07:00
if ( destination == 'hardware' ) {
2023-04-18 12:54:06 -07:00
return '<span data-tooltip="true" title="{{ trans(' admin / hardware / general . undeployable_tooltip ') }}"><a class="btn btn-sm bg-maroon disabled">{{ trans(' general . checkout ') }}</a></span>' ;
} else {
return '<span data-tooltip="true" title="{{ trans(' general . undeployable_tooltip ') }}"><a class="btn btn-sm bg-maroon disabled">{{ trans(' general . checkout ') }}</a></span>' ;
}
2017-02-08 18:21:03 -08:00
// The user is allowed to check items in
2017-09-28 21:18:00 -07:00
} else if ( row . available_actions . checkin == true ) {
if ( row . assigned_to ) {
2023-04-18 02:44:50 -07:00
return '<a href="{{ config(' app . url ') }}/' + destination + '/' + row . id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="Check this item in so it is available for re-imaging, re-issue, etc.">{{ trans(' general . checkin ') }}</a>' ;
2017-09-28 21:18:00 -07:00
} else if ( row . assigned_pivot_id ) {
2023-04-18 02:44:50 -07:00
return '<a href="{{ config(' app . url ') }}/' + destination + '/' + row . assigned_pivot_id + '/checkin" class="btn btn-sm bg-purple" data-tooltip="true" title="Check this item in so it is available for re-imaging, re-issue, etc.">{{ trans(' general . checkin ') }}</a>' ;
2017-09-28 21:18:00 -07:00
}
2018-01-23 18:08:54 -08:00
}
2017-02-08 18:21:03 -08:00
2017-02-08 08:48:41 -08:00
}
2017-01-24 18:58:07 -08:00
}
2017-01-24 22:46:07 -08:00
2018-04-04 17:33:02 -07:00
// This is only used by the requestable assets section
function assetRequestActionsFormatter ( row , value ) {
2021-07-20 16:56:22 -07:00
if ( value . assigned_to_self == true ){
2023-04-18 02:44:50 -07:00
return '<button class="btn btn-danger btn-sm disabled" data-tooltip="true" title="Cancel this item request">{{ trans(' button . cancel ') }}</button>' ;
2021-07-20 16:56:22 -07:00
} else if ( value . available_actions . cancel == true ) {
2023-04-18 02:44:50 -07:00
return '<form action="{{ config(' app . url ') }}/account/request-asset/' + value . id + '" method="POST">@csrf<button class="btn btn-danger btn-sm" data-tooltip="true" title="Cancel this item request">{{ trans(' button . cancel ') }}</button></form>' ;
2018-04-04 17:33:02 -07:00
} else if ( value . available_actions . request == true ) {
2023-04-18 02:44:50 -07:00
return '<form action="{{ config(' app . url ') }}/account/request-asset/' + value . id + '" method="POST">@csrf<button class="btn btn-primary btn-sm" data-tooltip="true" title="Request this item">{{ trans(' button . request ') }}</button></form>' ;
2018-04-04 17:33:02 -07:00
}
}
2017-01-24 22:25:17 -08:00
var formatters = [
'hardware' ,
2017-01-25 02:19:26 -08:00
'accessories' ,
2017-01-26 18:46:18 -08:00
'consumables' ,
'components' ,
2017-01-24 22:25:17 -08:00
'locations' ,
'users' ,
'manufacturers' ,
2018-02-16 13:22:55 -08:00
'maintenances' ,
2017-01-24 22:25:17 -08:00
'statuslabels' ,
'models' ,
'licenses' ,
'categories' ,
'suppliers' ,
2017-05-23 02:50:51 -07:00
'departments' ,
2017-01-24 22:25:17 -08:00
'companies' ,
'depreciations' ,
2017-02-01 18:50:28 -08:00
'fieldsets' ,
2018-10-19 07:30:25 -07:00
'groups' ,
2018-10-31 06:06:38 -07:00
'kits'
2017-01-24 22:25:17 -08:00
];
2017-01-18 19:46:43 -08:00
2017-01-24 21:04:38 -08:00
for ( var i in formatters ) {
window [ formatters [ i ] + 'LinkFormatter' ] = genericRowLinkFormatter ( formatters [ i ]);
window [ formatters [ i ] + 'LinkObjFormatter' ] = genericColumnObjLinkFormatter ( formatters [ i ]);
window [ formatters [ i ] + 'ActionsFormatter' ] = genericActionsFormatter ( formatters [ i ]);
2017-02-08 08:48:41 -08:00
window [ formatters [ i ] + 'InOutFormatter' ] = genericCheckinCheckoutFormatter ( formatters [ i ]);
2017-01-18 19:46:43 -08:00
}
2018-10-31 06:06:38 -07:00
var child_formatters = [
2018-10-19 07:30:25 -07:00
[ 'kits' , 'models' ],
[ 'kits' , 'licenses' ],
2019-01-27 12:19:24 -08:00
[ 'kits' , 'consumables' ],
[ 'kits' , 'accessories' ],
2018-10-19 07:30:25 -07:00
];
2018-10-31 06:06:38 -07:00
for ( var i in child_formatters ) {
var owner_name = child_formatters [ i ][ 0 ];
var child_name = child_formatters [ i ][ 1 ];
window [ owner_name + '_' + child_name + 'ActionsFormatter' ] = genericActionsFormatter ( owner_name , child_name );
2018-10-19 07:30:25 -07:00
}
2017-01-24 17:07:00 -08:00
2017-07-08 18:44:28 -07:00
// This is gross, but necessary so that we can package the API response
// for custom fields in a more useful way.
function customFieldsFormatter ( value , row ) {
2017-01-24 18:58:07 -08:00
2017-10-05 22:51:33 -07:00
if (( ! this ) || ( ! this . title )) {
return '' ;
}
2017-07-08 18:44:28 -07:00
var field_column = this . title ;
// Pull out any HTMl that might be passed via the presenter
// (for example, the locked icon for encrypted fields)
var field_column_plain = field_column . replace ( /< ( ? :.| \n ) * ?> ?/gm, '');
2017-08-23 03:28:13 -07:00
if (( row . custom_fields ) && ( row . custom_fields [ field_column_plain ])) {
2017-11-21 22:34:53 -08:00
// If the field type needs special formatting, do that here
if (( row . custom_fields [ field_column_plain ] . field_format ) && ( row . custom_fields [ field_column_plain ] . value )) {
if ( row . custom_fields [ field_column_plain ] . field_format == 'URL' ) {
return '<a href="' + row . custom_fields [ field_column_plain ] . value + '" target="_blank" rel="noopener">' + row . custom_fields [ field_column_plain ] . value + '</a>' ;
2022-06-07 16:00:46 -07:00
} else if ( row . custom_fields [ field_column_plain ] . field_format == 'BOOLEAN' ) {
2022-03-16 16:21:05 -07:00
return ( row . custom_fields [ field_column_plain ] . value == 1 ) ? " <span class='fas fa-check-circle' style='color:green' /> " : " <span class='fas fa-times-circle' style='color:red' /> " ;
2017-11-21 22:34:53 -08:00
} else if ( row . custom_fields [ field_column_plain ] . field_format == 'EMAIL' ) {
return '<a href="mailto:' + row . custom_fields [ field_column_plain ] . value + '">' + row . custom_fields [ field_column_plain ] . value + '</a>' ;
}
}
2017-07-08 18:44:28 -07:00
return row . custom_fields [ field_column_plain ] . value ;
2017-11-21 22:34:53 -08:00
2017-07-08 18:44:28 -07:00
}
}
function createdAtFormatter ( value ) {
2020-09-03 19:40:17 -07:00
if (( value ) && ( value . formatted )) {
return value . formatted ;
2017-01-24 17:07:00 -08:00
}
}
2018-08-01 18:01:31 -07:00
function externalLinkFormatter ( value ) {
if ( value ) {
return '<a href="' + value + '" target="_blank">' + value + '</a>' ;
}
}
2017-10-17 21:43:57 -07:00
function groupsFormatter ( value ) {
if ( value ) {
var groups = '' ;
for ( var index in value . rows ) {
2023-04-05 16:05:40 -07:00
groups += '<a href="{{ config(' app . url ') }}/admin/groups/' + value . rows [ index ] . id + '" class="label label-default">' + value . rows [ index ] . name + '</a> ' ;
2017-10-17 21:43:57 -07:00
}
return groups ;
}
}
2017-12-12 04:59:28 -08:00
function changeLogFormatter ( value ) {
var result = '' ;
for ( var index in value ) {
2021-09-24 07:21:30 -07:00
result += index + ': <del>' + value [ index ] . old + '</del> <i class="fas fa-long-arrow-alt-right" aria-hidden="true"></i> ' + value [ index ] . new + '<br>'
2017-12-12 04:59:28 -08:00
}
return result ;
}
2018-01-20 00:20:45 -08:00
// Create a linked phone number in the table list
function phoneFormatter ( value ) {
if ( value ) {
return '<a href="tel:' + value + '">' + value + '</a>' ;
}
}
2017-10-19 01:30:40 -07:00
function deployedLocationFormatter ( row , value ) {
if (( row ) && ( row != undefined )) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/locations/' + row . id + '">' + row . name + '</a>' ;
2017-10-19 01:30:40 -07:00
} else if ( value . rtd_location ) {
2023-04-18 02:44:50 -07:00
return '<a href="{{ config(' app . url ') }}/locations/' + value . rtd_location . id + '" data-tooltip="true" title="Default Location">' + value . rtd_location . name + '</a>' ;
2017-10-19 01:30:40 -07:00
}
}
2017-10-17 21:43:57 -07:00
function groupsAdminLinkFormatter ( value , row ) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/admin/groups/' + row . id + '">' + value + '</a>' ;
2017-10-17 21:43:57 -07:00
}
2018-03-05 16:26:40 -08:00
function assetTagLinkFormatter ( value , row ) {
2019-01-16 02:19:35 -08:00
if (( row . asset ) && ( row . asset . id )) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/hardware/' + row . asset . id + '">' + row . asset . asset_tag + '</a>' ;
2019-01-16 02:19:35 -08:00
}
return '' ;
2018-03-05 16:26:40 -08:00
}
2019-11-21 22:03:56 -08:00
function departmentNameLinkFormatter ( value , row ) {
if (( row . assigned_user ) && ( row . assigned_user . department ) && ( row . assigned_user . department . name )) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/department/' + row . assigned_user . department . id + '">' + row . assigned_user . department . name + '</a>' ;
2019-11-21 22:03:56 -08:00
}
}
2018-03-05 16:26:40 -08:00
function assetNameLinkFormatter ( value , row ) {
if (( row . asset ) && ( row . asset . name )) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/hardware/' + row . asset . id + '">' + row . asset . name + '</a>' ;
2018-03-05 16:26:40 -08:00
}
}
2018-05-01 21:35:07 -07:00
function trueFalseFormatter ( value ) {
2017-01-24 21:04:38 -08:00
if (( value ) && (( value == 'true' ) || ( value == '1' ))) {
2023-02-28 13:01:23 -08:00
return '<i class="fas fa-check text-success"></i><span class="sr-only">{{ trans(' general . true ') }}</span>' ;
2017-01-24 21:04:38 -08:00
} else {
2023-02-28 13:01:23 -08:00
return '<i class="fas fa-times text-danger"></i><span class="sr-only">{{ trans(' general . false ') }}</span>' ;
2017-01-18 19:28:35 -08:00
}
}
2018-05-01 21:35:07 -07:00
function dateDisplayFormatter ( value ) {
2017-03-03 17:29:41 -08:00
if ( value ) {
return value . formatted ;
}
}
2018-05-01 21:35:07 -07:00
function iconFormatter ( value ) {
2017-05-23 09:25:20 -07:00
if ( value ) {
2018-05-01 21:35:07 -07:00
return '<i class="' + value + ' icon-med"></i>' ;
2017-05-23 09:25:20 -07:00
}
}
2017-01-18 19:28:35 -08:00
2018-05-01 21:35:07 -07:00
function emailFormatter ( value ) {
2017-01-18 19:28:35 -08:00
if ( value ) {
2021-11-22 08:58:26 -08:00
return '<a href="mailto:' + value + '">' + value + '</a>' ;
2017-01-18 19:28:35 -08:00
}
}
2018-05-01 21:35:07 -07:00
function linkFormatter ( value ) {
2017-03-10 22:08:59 -08:00
if ( value ) {
2021-11-22 08:58:26 -08:00
return '<a href="' + value + '">' + value + '</a>' ;
2017-03-10 22:08:59 -08:00
}
}
2017-02-08 08:48:41 -08:00
function assetCompanyFilterFormatter ( value , row ) {
if ( value ) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/hardware/?company_id=' + row . id + '">' + value + '</a>' ;
2017-02-08 08:48:41 -08:00
}
}
function assetCompanyObjFilterFormatter ( value , row ) {
2017-11-22 06:20:51 -08:00
if (( row ) && ( row . company )) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/hardware/?company_id=' + row . company . id + '">' + row . company . name + '</a>' ;
2017-02-08 08:48:41 -08:00
}
}
function usersCompanyObjFilterFormatter ( value , row ) {
if ( value ) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/users/?company_id=' + row . id + '">' + value + '</a>' ;
2017-02-08 08:48:41 -08:00
} else {
return value ;
}
}
2017-07-26 16:47:47 -07:00
function employeeNumFormatter ( value , row ) {
2017-08-22 21:40:35 -07:00
2017-11-22 06:20:51 -08:00
if (( row ) && ( row . assigned_to ) && (( row . assigned_to . employee_number ))) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/users/' + row . assigned_to . id + '">' + row . assigned_to . employee_number + '</a>' ;
2017-07-26 16:47:47 -07:00
}
}
2017-02-08 08:48:41 -08:00
function orderNumberObjFilterFormatter ( value , row ) {
if ( value ) {
2023-04-05 16:05:40 -07:00
return '<a href="{{ config(' app . url ') }}/hardware/?order_number=' + row . order_number + '">' + row . order_number + '</a>' ;
2017-02-08 08:48:41 -08:00
}
}
2020-03-27 22:01:24 -07:00
function imageFormatter ( value , row ) {
2017-01-24 22:46:07 -08:00
if ( value ) {
2020-03-27 22:01:24 -07:00
2022-11-01 19:06:49 -07:00
// This is a clunky override to handle unusual API responses where we're presenting a link instead of an array
if ( row . avatar ) {
var altName = '' ;
}
else if ( row . name ) {
2020-03-27 22:01:24 -07:00
var altName = row . name ;
}
2022-11-01 19:06:49 -07:00
else if (( row ) && ( row . model )) {
2020-03-27 22:01:24 -07:00
var altName = row . model . name ;
}
return '<a href="' + value + '" data-toggle="lightbox" data-type="image"><img src="' + value + '" style="max-height: {{ $snipeSettings->thumbnail_max_h }}px; width: auto;" class="img-responsive" alt="' + altName + '"></a>' ;
2017-01-24 22:46:07 -08:00
}
}
2022-03-16 11:51:40 -07:00
function downloadFormatter ( value ) {
if ( value ) {
return '<a href="' + value + '" target="_blank"><i class="fas fa-download"></i></a>' ;
}
}
2017-01-24 22:46:07 -08:00
2018-05-02 14:13:06 -07:00
function fileUploadFormatter ( value ) {
if (( value ) && ( value . url ) && ( value . inlineable )) {
return '<a href="' + value . url + '" data-toggle="lightbox" data-type="image"><img src="' + value . url + '" style="max-height: {{ $snipeSettings->thumbnail_max_h }}px; width: auto;" class="img-responsive"></a>' ;
} else if (( value ) && ( value . url )) {
2021-09-26 01:11:08 -07:00
return '<a href="' + value . url + '" class="btn btn-default"><i class="fas fa-download"></i></a>' ;
2018-05-02 14:13:06 -07:00
}
}
function fileUploadNameFormatter ( value ) {
console . dir ( value );
if (( value ) && ( value . filename ) && ( value . url )) {
return '<a href="' + value . url + '">' + value . filename + '</a>' ;
}
}
2021-08-18 14:13:31 -07:00
function cleanFloat ( number ) {
2021-08-19 12:01:47 -07:00
if ( ! number ) { // in a JavaScript context, meaning, if it's null or zero or unset
return 0.0 ;
}
2021-08-18 14:13:31 -07:00
if ( " { { $snipeSettings -> digit_separator } } " == " 1.234,56 " ) {
// yank periods, change commas to periods
2021-09-28 19:10:25 -07:00
periodless = number . toString () . replace ( / \ ./ g , " " );
decimalfixed = periodless . replace ( / , / g , " . " );
2021-08-18 14:13:31 -07:00
} else {
// yank commas, that's it.
2021-12-06 07:27:58 -08:00
decimalfixed = number . toString () . replace ( / \ , / g , " " );
2021-08-18 14:13:31 -07:00
}
return parseFloat ( decimalfixed );
}
2017-10-18 06:24:36 -07:00
function sumFormatter ( data ) {
2018-02-16 13:22:55 -08:00
if ( Array . isArray ( data )) {
var field = this . field ;
var total_sum = data . reduce ( function ( sum , row ) {
2021-12-06 07:27:58 -08:00
2021-08-18 14:13:31 -07:00
return ( sum ) + ( cleanFloat ( row [ field ]) || 0 );
2018-02-16 13:22:55 -08:00
}, 0 );
2021-12-06 07:27:58 -08:00
2020-12-15 11:49:13 -08:00
return numberWithCommas ( total_sum . toFixed ( 2 ));
2018-02-16 13:22:55 -08:00
}
return 'not an array' ;
2017-10-18 06:24:36 -07:00
}
2018-01-23 18:08:54 -08:00
2021-08-04 14:09:50 -07:00
function sumFormatterQuantity ( data ){
if ( Array . isArray ( data )) {
2021-08-04 14:33:39 -07:00
// Prevents issues on page load where data is an empty array
2021-08-04 14:09:50 -07:00
if ( data [ 0 ] == undefined ){
return 0.00
}
2021-08-04 14:33:39 -07:00
// Check that we are actually trying to sum cost from a table
// that has a quantity column. We must perform this check to
// support licences which use seats instead of qty
if ( 'qty' in data [ 0 ]) {
var multiplier = 'qty' ;
} else if ( 'seats' in data [ 0 ]) {
var multiplier = 'seats' ;
} else {
return 'no quantity' ;
2021-08-04 14:09:50 -07:00
}
2021-08-04 14:33:39 -07:00
var total_sum = data . reduce ( function ( sum , row ) {
2021-10-30 14:48:45 -07:00
return ( sum ) + ( cleanFloat ( row [ " purchase_cost " ]) * row [ multiplier ] || 0 );
2021-08-04 14:33:39 -07:00
}, 0 );
2020-12-15 11:49:13 -08:00
return numberWithCommas ( total_sum . toFixed ( 2 ));
2018-02-16 13:22:55 -08:00
}
return 'not an array' ;
2017-10-18 06:24:36 -07:00
}
2018-01-23 18:08:54 -08:00
2020-12-15 11:49:13 -08:00
function numberWithCommas ( value ) {
2021-12-06 07:27:58 -08:00
2020-12-15 11:49:13 -08:00
if (( value ) && ( " { { $snipeSettings -> digit_separator } } " == " 1.234,56 " )){
2021-08-17 21:59:33 -07:00
var parts = value . toString () . split ( " . " );
parts [ 0 ] = parts [ 0 ] . replace ( / \B ( ? = ( \d { 3 }) + ( ? ! \d )) / g , " . " );
return parts . join ( " , " );
} else {
var parts = value . toString () . split ( " , " );
parts [ 0 ] = parts [ 0 ] . replace ( / \B ( ? = ( \d { 3 }) + ( ? ! \d )) / g , " , " );
return parts . join ( " . " );
2020-12-15 11:49:13 -08:00
}
return value
}
2017-10-18 06:24:36 -07:00
2017-01-18 19:28:35 -08:00
$ ( function () {
$ ( '#bulkEdit' ) . click ( function () {
var selectedIds = $ ( '.snipe-table' ) . bootstrapTable ( 'getSelections' );
$ . each ( selectedIds , function ( key , value ) {
$ ( " #bulkForm " ) . append ( $ ( '<input type="hidden" name="ids[' + value . id + ']" value="' + value . id + '">' ));
});
});
});
2017-02-08 08:48:41 -08:00
2017-10-18 06:24:36 -07:00
2021-05-04 22:00:34 -07:00
2017-07-08 13:21:13 -07:00
$ ( function () {
2021-05-04 22:00:34 -07:00
// This handles the search box highlighting on both ajax and client-side
// bootstrap tables
var searchboxHighlighter = function ( event ) {
$ ( '.search-input' ) . each ( function ( index , element ) {
if ( $ ( element ) . val () != '' ) {
$ ( element ) . addClass ( 'search-highlight' );
$ ( element ) . next () . children () . addClass ( 'search-highlight' );
} else {
$ ( element ) . removeClass ( 'search-highlight' );
$ ( element ) . next () . children () . removeClass ( 'search-highlight' );
}
});
};
$ ( '.search button[name=clearSearch]' ) . click ( searchboxHighlighter );
searchboxHighlighter ({ name : 'pageload' });
$ ( '.search-input' ) . keyup ( searchboxHighlighter );
// This is necessary to make the bootstrap tooltips work inside of the
// wenzhixin/bootstrap-table formatters
2017-07-08 13:21:13 -07:00
$ ( '#table' ) . on ( 'post-body.bs.table' , function () {
2023-04-18 02:44:50 -07:00
$ ( '[data-tooltip="true"]' ) . tooltip ({
2017-07-08 13:21:13 -07:00
container : 'body'
});
2021-05-04 22:00:34 -07:00
2017-07-08 13:21:13 -07:00
});
});
2016-11-23 05:56:08 -08:00
</ script >
2018-08-28 13:10:27 -07:00
2022-07-02 11:27:16 -07:00
@ endpush