@@ -360,3 +360,270 @@ document.addEventListener('widgetTitleChanged', function(evt) {
360360 title . innerHTML = evt . detail . value ;
361361 }
362362} ) ;
363+
364+ /* Load the owner dropdown when the user clicks the pencil in basics */
365+ jQuery ( document ) . on ( 'click' , '.ticket-info-basics .inline-edit-toggle.edit .rt-inline-icon' , function ( e ) {
366+ /* htmx will run for many portlets. Only run for ticket-info-basics to avoid multiple
367+ calls to the helper for the same dropdown. */
368+ if ( e . delegateTarget . className === "ticket-info-basics" ) {
369+ var owner_dropdown_delay = jQuery ( 'div.ticket-info-basics div.select-owner-dropdown-delay:not(.loaded)' ) ;
370+ loadOwnerDropdownDelay ( owner_dropdown_delay ) ;
371+ }
372+ } ) ;
373+
374+ jQuery ( document ) . on ( 'click' , '.inline-edit-toggle' , function ( e ) {
375+ e . preventDefault ( ) ;
376+ e . stopPropagation ( ) ;
377+ toggleInlineEdit ( jQuery ( this ) ) ;
378+ } ) ;
379+
380+ jQuery ( document ) . on ( 'click' , '.titlebox[data-inline-edit-behavior="click"] > .titlebox-content' , function ( e ) {
381+ if ( jQuery ( e . target ) . is ( 'input, select, textarea' ) ) {
382+ return ;
383+ }
384+
385+ // Bypass links, buttons and radio/checkbox controls too
386+ if ( jQuery ( e . target ) . closest ( 'a, button, div.custom-radio, div.custom-checkbox' ) . length ) {
387+ return ;
388+ }
389+
390+ e . preventDefault ( ) ;
391+ e . stopPropagation ( ) ;
392+ var container = jQuery ( this ) . closest ( '.titlebox' ) ;
393+ if ( container . hasClass ( 'editing' ) ) {
394+ return ;
395+ }
396+ toggleInlineEdit ( container . find ( '.inline-edit-toggle:visible' ) ) ;
397+ } ) ;
398+
399+
400+ // Hide the tooltip everywhere when the element is clicked
401+ jQuery ( document ) . on ( 'click' , '[data-bs-toggle="tooltip"]' , function ( e ) {
402+ jQuery ( '[data-bs-toggle="tooltip"]' ) . tooltip ( "hide" ) ;
403+ } ) ;
404+
405+ jQuery ( document ) . on ( 'click' , 'a.delete-attach' , function ( ) {
406+ var parent = jQuery ( this ) . closest ( 'div' ) ;
407+ var name = jQuery ( this ) . attr ( 'data-name' ) ;
408+ var token = jQuery ( this ) . closest ( 'form' ) . find ( 'input[name=Token]' ) . val ( ) ;
409+ jQuery . post ( RT . Config . WebHomePath + '/Helpers/Upload/Delete' , { Name : name , Token : token } , function ( data ) {
410+ if ( data . status == 'success' ) {
411+ parent . remove ( ) ;
412+ }
413+ } , 'json' ) ;
414+ return false ;
415+ } ) ;
416+
417+ /* Show selected file name in UI */
418+ jQuery ( document ) . on ( 'change' , '.custom-file input' , function ( e ) {
419+ jQuery ( this ) . next ( '.custom-file-label' ) . html ( e . target . files [ 0 ] . name ) ;
420+ } ) ;
421+
422+
423+ jQuery ( document ) . on ( 'input propertychange' , ':input[data-type=json]' , function ( ) {
424+ var form = jQuery ( this ) . closest ( 'form' ) ;
425+ try {
426+ JSON . parse ( jQuery ( this ) . val ( ) ) ;
427+ form . find ( 'input[type=submit]' ) . prop ( 'disabled' , false ) ;
428+ form . find ( '.invalid-json' ) . addClass ( 'hidden' ) ;
429+ } catch ( e ) {
430+ form . find ( 'input[type=submit]' ) . prop ( 'disabled' , true ) ;
431+ form . find ( '.invalid-json' ) . removeClass ( 'hidden' ) ;
432+ }
433+ } ) ;
434+
435+ jQuery ( document ) . on ( 'click' , 'a.permalink' , function ( ) {
436+ htmx . ajax ( 'GET' , RT . Config . WebPath + "/Helpers/Permalink" , {
437+ target : '#dynamic-modal' ,
438+ values : {
439+ Code : this . getAttribute ( 'data-code' ) ,
440+ URL : this . getAttribute ( 'data-url' )
441+ } ,
442+ } ) . then ( ( ) => {
443+ bootstrap . Modal . getOrCreateInstance ( '#dynamic-modal' ) . show ( ) ;
444+ } ) ;
445+ return false ;
446+ } ) ;
447+
448+ // My Week auto submit
449+ jQuery ( document ) . on ( 'change change.td' , 'div.time-tracking input[name=Date]' , function ( ) {
450+ htmx . trigger ( this . closest ( 'form' ) , 'submit' ) ;
451+ } ) ;
452+
453+ jQuery ( document ) . on ( 'change' , 'div.time-tracking input[name=UserString]' , function ( ) {
454+ this . closest ( 'form' ) . querySelector ( 'input[name=User]' ) . value = this . value ;
455+ htmx . trigger ( this . closest ( 'form' ) , 'submit' ) ;
456+ } ) ;
457+
458+ jQuery ( document ) . on ( 'click' , 'a.search-filter' , function ( e ) {
459+ const target = document . querySelector ( e . target . closest ( '.search-filter' ) . getAttribute ( 'hx-target' ) ) ;
460+ if ( target . children . length > 0 ) {
461+ bootstrap . Modal . getOrCreateInstance ( target . closest ( '.modal.search-results-filter' ) ) . show ( ) ;
462+ }
463+ else {
464+ htmx . trigger ( e . target . closest ( '.search-filter' ) , 'manual' ) ;
465+ }
466+ return false ;
467+ } ) ;
468+
469+ // Automatically reveal history widget so anchor links like #txn-586 can work
470+ jQuery ( document ) . on ( 'click' , 'a.jump-to-unread' , function ( ) {
471+ revealHistoryWidget ( ) ;
472+ } ) ;
473+
474+ // Clip content
475+ jQuery ( document ) . on ( 'click' , 'a.unclip' , function ( ) {
476+ jQuery ( this ) . siblings ( 'div.clip' ) . css ( 'height' , 'auto' ) ;
477+ jQuery ( this ) . hide ( ) ;
478+ jQuery ( this ) . siblings ( 'a.reclip' ) . show ( ) ;
479+ return false ;
480+ } ) ;
481+
482+ jQuery ( document ) . on ( 'click' , 'a.reclip' , function ( ) {
483+ var clip_div = jQuery ( this ) . siblings ( 'div.clip' ) ;
484+ clip_div . height ( clip_div . attr ( 'clip-height' ) ) ;
485+ jQuery ( this ) . siblings ( 'a.unclip' ) . show ( ) ;
486+ jQuery ( this ) . hide ( ) ;
487+ return false ;
488+ } ) ;
489+
490+ jQuery ( document ) . on ( 'click' , '.asset-create-linked-ticket' , function ( e ) {
491+ e . preventDefault ( ) ;
492+ var url = this . href . replace ( / \/ A s s e t \/ C r e a t e L i n k e d T i c k e t \. h t m l \? / g,
493+ '/Asset/Helpers/CreateLinkedTicket?' ) ;
494+
495+ htmx . ajax ( 'GET' , url , '#dynamic-modal' ) . then ( ( ) => {
496+ bootstrap . Modal . getOrCreateInstance ( '#dynamic-modal' ) . show ( ) ;
497+ } ) ;
498+ } ) ;
499+ jQuery ( document ) . on ( 'click' , '#bulk-update-create-linked-ticket' , function ( e ) {
500+ e . preventDefault ( ) ;
501+ var chkArray = [ ] ;
502+
503+ jQuery ( "input[name='UpdateAsset']:checked" ) . each ( function ( ) {
504+ chkArray . push ( jQuery ( this ) . val ( ) ) ;
505+ } ) ;
506+
507+ var selected = '' ;
508+ for ( var i = 0 ; i < chkArray . length ; i ++ ) {
509+ selected += 'Asset=' + chkArray [ i ] + '&' ;
510+ }
511+ /* selected = chkArray.join(','); */
512+ var url = RT . Config . WebHomePath + '/Asset/Helpers/CreateLinkedTicket?' + selected ;
513+ htmx . ajax ( 'GET' , url , '#dynamic-modal' ) . then ( ( ) => {
514+ bootstrap . Modal . getOrCreateInstance ( '#dynamic-modal' ) . show ( ) ;
515+ } ) ;
516+ } ) ;
517+
518+ // Disable chosing individual objects when a scrip is applied globally
519+ jQuery ( document ) . on ( 'change' , 'form[name=AddRemoveScrip] input[type=checkbox][name^=AddScrip-][value=0], form input[type=checkbox][name^=AddCustomField-][value=0]' , function ( ) {
520+ var self = jQuery ( this ) ;
521+ var checked = self . prop ( "checked" ) ;
522+
523+ self . closest ( "form" )
524+ . find ( "table.collection input[type=checkbox]" )
525+ . prop ( "disabled" , checked ) ;
526+ } ) ;
527+
528+ jQuery ( document ) . on ( 'change' , 'input[type=file]' , function ( ) {
529+ var input = jQuery ( this ) ;
530+ var warning = input . next ( ".invalid" ) ;
531+
532+ if ( ! input . val ( ) . match ( / " / ) ) {
533+ warning . hide ( ) ;
534+ } else {
535+ if ( warning . length ) {
536+ warning . show ( ) ;
537+ } else {
538+ input . val ( "" ) ;
539+ jQuery ( "<span class='invalid'>" )
540+ . text ( loc_key ( "quote_in_filename" ) )
541+ . insertAfter ( input ) ;
542+ }
543+ }
544+ } ) ;
545+
546+ jQuery ( document ) . on ( 'change' , '#UpdateType' , function ( e ) {
547+ jQuery ( ".messagebox-container" )
548+ . removeClass ( "action-response action-private" )
549+ . addClass ( "action-" + e . target . value ) ;
550+ } ) ;
551+
552+ jQuery ( document ) . on ( 'click' , '.toggle-txn-details' , function ( e ) {
553+ return toggleTransactionDetails . apply ( this ) ;
554+ } ) ;
555+
556+ jQuery ( document ) . on ( 'change' , '.article-basics [name="Type"]' , function ( ) {
557+ if ( jQuery ( this ) . val ( ) == 'Content' ) {
558+ jQuery ( '#article-type-links' ) . addClass ( 'hidden' ) ;
559+ jQuery ( '#article-type-content' ) . removeClass ( 'hidden' ) ;
560+ }
561+ else {
562+ jQuery ( '#article-type-content' ) . addClass ( 'hidden' ) ;
563+ jQuery ( '#article-type-links' ) . removeClass ( 'hidden' ) ;
564+ }
565+ } ) ;
566+
567+ jQuery ( document ) . on ( 'focus' , '[name^="article-link-"]' , function ( ) {
568+ // if input focus in last row add another row of inputs
569+ const link_div = jQuery ( this ) . parent ( ) . parent ( ) ;
570+ const links_div = link_div . parent ( ) ;
571+ if ( link_div . attr ( 'data-link-number' ) == links_div . attr ( 'data-link-count' ) ) {
572+ const link_count = parseInt ( links_div . attr ( 'data-link-count' ) ) + 1 ;
573+ links_div . attr ( 'data-link-count' , link_count ) ;
574+ let new_link_div = link_div . clone ( ) ;
575+ new_link_div . attr ( 'data-link-number' , link_count ) ;
576+ new_link_div . find ( '[name^="article-link-"]' ) . each ( function ( ) {
577+ var oldName = jQuery ( this ) . attr ( 'name' ) ;
578+ var newName = oldName . replace ( / - \d + $ / , '-' + link_count ) ;
579+ jQuery ( this ) . attr ( 'name' , newName ) ;
580+ } ) ;
581+ links_div . append ( new_link_div ) ;
582+ }
583+ } ) ;
584+
585+ // Automatically sync to set input values to ones in config files.
586+ jQuery ( document ) . on ( 'change' , 'form[name=EditConfig] input[name$="-file"]' , function ( e ) {
587+ var file_input = jQuery ( this ) ;
588+ var form = file_input . closest ( 'form' ) ;
589+ var file_name = file_input . attr ( 'name' ) ;
590+ var file_value = form . find ( 'input[name=' + file_name + '-Current]' ) . val ( ) ;
591+ var checked = jQuery ( this ) . is ( ':checked' ) ? 1 : 0 ;
592+ if ( ! checked ) return ;
593+
594+ var db_name = file_name . replace ( / - f i l e $ / , '' ) ;
595+ var db_input = form . find ( ':input[name=' + db_name + ']' ) ;
596+ var db_input_type = db_input . attr ( 'type' ) || db_input . prop ( 'tagName' ) . toLowerCase ( ) ;
597+ if ( db_input_type == 'radio' ) {
598+ db_input . filter ( '[value=' + ( file_value || 0 ) + ']' ) . prop ( 'checked' , true ) ;
599+ }
600+ else if ( db_input_type == 'select' ) {
601+ // Silently update value, otherwise the radio would be unchecked again because of select's change event.
602+ db_input . get ( 0 ) . tomselect . setValue ( file_value . length ? file_value : '__empty_value__' , true ) ;
603+ }
604+ else {
605+ db_input . val ( file_value ) ;
606+ }
607+ } ) ;
608+
609+ jQuery ( document ) . on ( 'change' , 'form[name=BuildQuery] select[name^=SelectCustomField]' , function ( ) {
610+ var form = jQuery ( this ) . closest ( 'form' ) ;
611+ var row = jQuery ( this ) . closest ( 'div.row' ) ;
612+ var val = jQuery ( this ) . val ( ) ;
613+
614+ var new_operator = form . find ( ':input[name="' + val + 'Op"]:first' ) . clone ( ) ;
615+ new_operator . attr ( 'id' , null ) . removeClass ( 'tomselected ts-hidden-accessible' ) ;
616+ row . children ( 'div.rt-search-operator' ) . children ( ) . remove ( ) ;
617+ row . children ( 'div.rt-search-operator' ) . append ( new_operator ) ;
618+
619+ var new_value = form . find ( ':input[name="ValueOf' + val + '"]:first' ) ;
620+ new_value = new_value . clone ( ) ;
621+
622+ new_value . attr ( 'id' , null ) . removeClass ( 'tomselected ts-hidden-accessible' ) ;
623+ row . children ( 'div.rt-search-value' ) . children ( ) . remove ( ) ;
624+ row . children ( 'div.rt-search-value' ) . append ( new_value ) ;
625+ if ( new_value . hasClass ( 'datepicker' ) ) {
626+ initDatePicker ( row . get ( 0 ) ) ;
627+ }
628+ initializeSelectElements ( row . get ( 0 ) ) ;
629+ } ) ;
0 commit comments