2017-08-26 16:06:52 -07:00
/ *
*
* Snipe - IT Universal Modal support
*
* Enables modal dialogs to create sub - resources throughout Snipe - IT
*
* /
/ *
HOW TO USE
Create a Button looking like this :
2020-05-23 09:19:19 -07:00
< a href = '{{ route(' modal . show ', ' user ') }}' data - toggle = "modal" data - target = "#createModal" data - select = 'assigned_to' class = "btn btn-sm btn-primary" > New < / a >
2017-08-26 16:06:52 -07:00
If you don 't have access to Blade commands (like {{ and }}, etc), you can hard-code a URL as the ' href '
data - toggle = "modal" - required for Bootstrap Modals
data - target = "#createModal" - fixed ID for the modal , do not change
2017-10-16 20:34:22 -07:00
data - select = "assigned_to" - What is the * ID * of the select - dropdown that you 're going to be adding to, if the modal-create was a success? Be on the lookout for duplicate ID' s , it will confuse this library !
2020-04-02 18:33:26 -07:00
class = "btn btn-sm btn-primary" - makes it look button - ey , feel free to change : )
2018-01-20 00:42:29 -08:00
If you want to pass additional variables to the modal ( In the Category Create one , for example , you can pass category _id ) , you can encode them as URL variables in the href
2017-08-26 16:06:52 -07:00
* /
2018-07-16 14:22:25 -07:00
$ ( function ( ) {
2017-10-24 19:20:00 -07:00
2022-03-16 08:23:50 -07:00
var baseUrl = $ ( 'meta[name="baseUrl"]' ) . attr ( 'content' ) ;
2017-08-26 16:06:52 -07:00
//handle modal-add-interstitial calls
2019-01-27 12:19:24 -08:00
var model , select , refreshSelector ;
2017-08-26 16:06:52 -07:00
if ( $ ( '#createModal' ) . length == 0 ) {
$ ( 'body' ) . append ( '<div class="modal fade" id="createModal"></div><!-- /.modal -->' ) ;
}
$ ( '#createModal' ) . on ( "show.bs.modal" , function ( event ) {
var link = $ ( event . relatedTarget ) ;
model = link . data ( "dependency" ) ;
select = link . data ( "select" ) ;
2019-01-27 12:19:24 -08:00
refreshSelector = link . data ( "refresh" ) ;
2023-09-28 11:16:40 -07:00
2017-08-26 16:06:52 -07:00
$ ( '#createModal' ) . load ( link . attr ( 'href' ) , function ( ) {
2023-09-28 11:16:40 -07:00
// this sets the focus to be the name field
$ ( '#modal-name' ) . focus ( ) ;
2018-07-16 14:22:25 -07:00
//do we need to re-select2 this, after load? Probably.
$ ( '#createModal' ) . find ( 'select.select2' ) . select2 ( ) ;
// Initialize the ajaxy select2 with images.
// This is a copy/paste of the code from snipeit.js, would be great to only have this in one place.
2023-09-28 11:16:40 -07:00
2018-07-16 14:22:25 -07:00
$ ( '.js-data-ajax' ) . each ( function ( i , item ) {
var link = $ ( item ) ;
var endpoint = link . data ( "endpoint" ) ;
var select = link . data ( "select" ) ;
link . select2 ( {
ajax : {
// the baseUrl includes a trailing slash
2021-06-23 19:57:45 -07:00
url : baseUrl + 'api/v1/' + endpoint + '/selectlist' , //WARNING - we're hoping that's defined on the page somewhere...
2018-07-16 14:22:25 -07:00
dataType : 'json' ,
delay : 250 ,
headers : {
"X-Requested-With" : 'XMLHttpRequest' ,
"X-CSRF-TOKEN" : $ ( 'meta[name="csrf-token"]' ) . attr ( 'content' )
} ,
data : function ( params ) {
var data = {
search : params . term ,
page : params . page || 1 ,
assetStatusType : link . data ( "asset-status-type" ) ,
} ;
return data ;
} ,
2021-02-02 15:55:21 -08:00
/ * p r o c e s s R e s u l t s : f u n c t i o n ( d a t a , p a r a m s ) {
2018-07-16 14:22:25 -07:00
params . page = params . page || 1 ;
var answer = {
results : data . items ,
pagination : {
2020-07-16 15:33:38 -07:00
more : data . pagination . more
2018-07-16 14:22:25 -07:00
}
} ;
return answer ;
2021-02-02 15:55:21 -08:00
} , * /
2018-07-16 14:22:25 -07:00
cache : true
} ,
2021-02-02 15:55:21 -08:00
//escapeMarkup: function (markup) { return markup; }, // let our custom formatter work
templateResult : formatDatalistSafe ,
//templateSelection: formatDataSelection
2018-07-16 14:22:25 -07:00
} ) ;
} ) ;
2017-08-26 16:06:52 -07:00
} ) ;
2018-07-16 14:22:25 -07:00
2017-08-26 16:06:52 -07:00
} ) ;
2018-07-16 14:22:25 -07:00
2017-08-26 16:06:52 -07:00
$ ( '#createModal' ) . on ( 'click' , '#modal-save' , function ( ) {
$ . ajax ( {
type : 'POST' ,
2018-01-20 00:42:29 -08:00
url : $ ( '.modal-body form' ) . attr ( 'action' ) ,
2017-08-26 16:06:52 -07:00
headers : {
"X-Requested-With" : 'XMLHttpRequest' ,
"X-CSRF-TOKEN" : $ ( 'meta[name="csrf-token"]' ) . attr ( 'content' )
} ,
2018-01-20 00:42:29 -08:00
data : $ ( '.modal-body form' ) . serialize ( ) ,
2017-08-26 16:06:52 -07:00
success : function ( result ) {
2017-10-24 19:20:00 -07:00
2017-08-26 16:06:52 -07:00
if ( result . status == "error" ) {
var error _message = "" ;
for ( var field in result . messages ) {
2017-10-24 19:20:00 -07:00
error _message += "<li>Problem(s) with field <i><strong>" + field + "</strong></i>: " + result . messages [ field ] ;
2018-01-20 07:42:48 -08:00
2017-08-26 16:06:52 -07:00
}
$ ( '#modal_error_msg' ) . html ( error _message ) . show ( ) ;
return false ;
}
var id = result . payload . id ;
var name = result . payload . name || ( result . payload . first _name + " " + result . payload . last _name ) ;
if ( ! id || ! name ) {
console . error ( "Could not find resulting name or ID from modal-create. Name: " + name + ", id: " + id ) ;
return false ;
}
$ ( '#createModal' ) . modal ( 'hide' ) ;
$ ( '#createModal' ) . html ( "" ) ;
2019-01-27 12:19:24 -08:00
var refreshTable = $ ( '#' + refreshSelector ) ;
if ( refreshTable . length > 0 ) {
refreshTable . bootstrapTable ( 'refresh' ) ;
}
2017-08-26 16:06:52 -07:00
// "select" is the original drop-down menu that someone
// clicked 'add' on to add a new 'thing'
// this code adds the newly created object to that select
var selector = document . getElementById ( select ) ;
2018-01-20 07:42:48 -08:00
2017-08-26 16:06:52 -07:00
if ( ! selector ) {
return false ;
}
2017-10-24 17:10:42 -07:00
2017-08-26 16:06:52 -07:00
selector . options [ selector . length ] = new Option ( name , id ) ;
selector . selectedIndex = selector . length - 1 ;
$ ( selector ) . trigger ( "change" ) ;
2017-10-16 20:34:22 -07:00
if ( window . fetchCustomFields ) {
2017-08-26 16:06:52 -07:00
fetchCustomFields ( ) ;
}
} ,
error : function ( result ) {
msg = result . responseJSON . messages || result . responseJSON . error ;
$ ( '#modal_error_msg' ) . html ( "Server Error: " + msg ) . show ( ) ;
}
} ) ;
} ) ;
2017-10-16 20:12:11 -07:00
} ) ;
2018-07-16 14:22:25 -07:00
2021-02-16 04:06:34 -08:00
function formatDatalistSafe ( datalist ) {
// console.warn("What in the hell is going on with Select2?!?!!?!?");
// console.warn($.select2);
if ( datalist . loading ) {
2021-09-26 01:11:08 -07:00
return $ ( '<i class="fas fa-spinner fa-spin" aria-hidden="true"></i> Loading...' ) ;
2021-02-16 04:06:34 -08:00
}
var root _div = $ ( "<div class='clearfix'>" ) ;
var left _pull = $ ( "<div class='pull-left' style='padding-right: 10px;'>" ) ;
if ( datalist . image ) {
var inner _div = $ ( "<div style='width: 30px;'>" ) ;
/ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* We are specifically chosing empty alt - text below , because this
* image conveys no additional information , relative to the text
* that will * always * be there in any select2 list that is in use
* in Snipe - IT . If that changes , we would probably want to change
* some signatures of some functions , but right now , we don ' t want
* screen readers to say " HP SuperJet 5000 , ... . picture of HP
* SuperJet 5000. . . " and so on , for every single row in a list of
* assets or models or whatever .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
var img = $ ( "<img src='' style='max-height: 20px; max-width: 30px;' alt=''>" ) ;
// console.warn("Img is: ");
// console.dir(img);
// console.warn("Strigularly, that's: ");
// console.log(img);
img . attr ( "src" , datalist . image ) ;
inner _div . append ( img )
} else {
var inner _div = $ ( "<div style='height: 20px; width: 30px;'></div>" ) ;
}
left _pull . append ( inner _div ) ;
root _div . append ( left _pull ) ;
var name _div = $ ( "<div>" ) ;
name _div . text ( datalist . text ) ;
root _div . append ( name _div )
var safe _html = root _div . get ( 0 ) . outerHTML ;
var old _html = formatDatalist ( datalist ) ;
2022-05-06 08:34:30 -07:00
if ( safe _html != old _html ) {
// console.log("HTML MISMATCH: ");
// console.log("FormatDatalistSafe: ");
2021-02-16 04:06:34 -08:00
// console.dir(root_div.get(0));
2022-05-06 08:34:30 -07:00
// console.log(safe_html);
// console.log("FormatDataList: ");
// console.log(old_html);
2021-02-16 04:06:34 -08:00
}
return root _div ;
}
2018-07-16 14:22:25 -07:00
function formatDatalist ( datalist ) {
2021-09-26 01:11:08 -07:00
var loading _markup = '<i class="fas fa-spinner fa-spin" aria-hidden="true"></i> Loading...' ;
2018-07-16 14:22:25 -07:00
if ( datalist . loading ) {
return loading _markup ;
}
var markup = "<div class='clearfix'>" ;
markup += "<div class='pull-left' style='padding-right: 10px;'>" ;
if ( datalist . image ) {
2020-03-27 22:03:30 -07:00
markup += "<div style='width: 30px;'><img src='" + datalist . image + "' alt='" + datalist . tex + "' style='max-height: 20px; max-width: 30px;'></div>" ;
2018-07-16 14:22:25 -07:00
} else {
markup += "<div style='height: 20px; width: 30px;'></div>" ;
}
markup += "</div><div>" + datalist . text + "</div>" ;
markup += "</div>" ;
return markup ;
}
function formatDataSelection ( datalist ) {
2019-05-21 18:29:50 -07:00
return datalist . text . replace ( />/g , '>' )
. replace ( /</g , '<' )
. replace ( /"/g , '"' )
. replace ( /'/g , ''' ) ;
2018-07-16 14:22:25 -07:00
}