application-passwords.js 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. /**
  2. * @output wp-admin/js/application-passwords.js
  3. */
  4. ( function( $ ) {
  5. var $appPassSection = $( '#application-passwords-section' ),
  6. $newAppPassForm = $appPassSection.find( '.create-application-password' ),
  7. $newAppPassField = $newAppPassForm.find( '.input' ),
  8. $newAppPassButton = $newAppPassForm.find( '.button' ),
  9. $appPassTwrapper = $appPassSection.find( '.application-passwords-list-table-wrapper' ),
  10. $appPassTbody = $appPassSection.find( 'tbody' ),
  11. $appPassTrNoItems = $appPassTbody.find( '.no-items' ),
  12. $removeAllBtn = $( '#revoke-all-application-passwords' ),
  13. tmplNewAppPass = wp.template( 'new-application-password' ),
  14. tmplAppPassRow = wp.template( 'application-password-row' ),
  15. userId = $( '#user_id' ).val();
  16. $newAppPassButton.on( 'click', function( e ) {
  17. e.preventDefault();
  18. if ( $newAppPassButton.prop( 'aria-disabled' ) ) {
  19. return;
  20. }
  21. var name = $newAppPassField.val();
  22. if ( 0 === name.length ) {
  23. $newAppPassField.trigger( 'focus' );
  24. return;
  25. }
  26. clearNotices();
  27. $newAppPassButton.prop( 'aria-disabled', true ).addClass( 'disabled' );
  28. var request = {
  29. name: name
  30. };
  31. /**
  32. * Filters the request data used to create a new Application Password.
  33. *
  34. * @since 5.6.0
  35. *
  36. * @param {Object} request The request data.
  37. * @param {number} userId The id of the user the password is added for.
  38. */
  39. request = wp.hooks.applyFilters( 'wp_application_passwords_new_password_request', request, userId );
  40. wp.apiRequest( {
  41. path: '/wp/v2/users/' + userId + '/application-passwords?_locale=user',
  42. method: 'POST',
  43. data: request
  44. } ).always( function() {
  45. $newAppPassButton.removeProp( 'aria-disabled' ).removeClass( 'disabled' );
  46. } ).done( function( response ) {
  47. $newAppPassField.val( '' );
  48. $newAppPassButton.prop( 'disabled', false );
  49. $newAppPassForm.after( tmplNewAppPass( {
  50. name: response.name,
  51. password: response.password
  52. } ) );
  53. $( '.new-application-password-notice' ).trigger( 'focus' );
  54. $appPassTbody.prepend( tmplAppPassRow( response ) );
  55. $appPassTwrapper.show();
  56. $appPassTrNoItems.remove();
  57. /**
  58. * Fires after an application password has been successfully created.
  59. *
  60. * @since 5.6.0
  61. *
  62. * @param {Object} response The response data from the REST API.
  63. * @param {Object} request The request data used to create the password.
  64. */
  65. wp.hooks.doAction( 'wp_application_passwords_created_password', response, request );
  66. } ).fail( handleErrorResponse );
  67. } );
  68. $appPassTbody.on( 'click', '.delete', function( e ) {
  69. e.preventDefault();
  70. if ( ! window.confirm( wp.i18n.__( 'Are you sure you want to revoke this password? This action cannot be undone.' ) ) ) {
  71. return;
  72. }
  73. var $submitButton = $( this ),
  74. $tr = $submitButton.closest( 'tr' ),
  75. uuid = $tr.data( 'uuid' );
  76. clearNotices();
  77. $submitButton.prop( 'disabled', true );
  78. wp.apiRequest( {
  79. path: '/wp/v2/users/' + userId + '/application-passwords/' + uuid + '?_locale=user',
  80. method: 'DELETE'
  81. } ).always( function() {
  82. $submitButton.prop( 'disabled', false );
  83. } ).done( function( response ) {
  84. if ( response.deleted ) {
  85. if ( 0 === $tr.siblings().length ) {
  86. $appPassTwrapper.hide();
  87. }
  88. $tr.remove();
  89. addNotice( wp.i18n.__( 'Application password revoked.' ), 'success' ).trigger( 'focus' );
  90. }
  91. } ).fail( handleErrorResponse );
  92. } );
  93. $removeAllBtn.on( 'click', function( e ) {
  94. e.preventDefault();
  95. if ( ! window.confirm( wp.i18n.__( 'Are you sure you want to revoke all passwords? This action cannot be undone.' ) ) ) {
  96. return;
  97. }
  98. var $submitButton = $( this );
  99. clearNotices();
  100. $submitButton.prop( 'disabled', true );
  101. wp.apiRequest( {
  102. path: '/wp/v2/users/' + userId + '/application-passwords?_locale=user',
  103. method: 'DELETE'
  104. } ).always( function() {
  105. $submitButton.prop( 'disabled', false );
  106. } ).done( function( response ) {
  107. if ( response.deleted ) {
  108. $appPassTbody.children().remove();
  109. $appPassSection.children( '.new-application-password' ).remove();
  110. $appPassTwrapper.hide();
  111. addNotice( wp.i18n.__( 'All application passwords revoked.' ), 'success' ).trigger( 'focus' );
  112. }
  113. } ).fail( handleErrorResponse );
  114. } );
  115. $appPassSection.on( 'click', '.notice-dismiss', function( e ) {
  116. e.preventDefault();
  117. var $el = $( this ).parent();
  118. $el.removeAttr( 'role' );
  119. $el.fadeTo( 100, 0, function () {
  120. $el.slideUp( 100, function () {
  121. $el.remove();
  122. $newAppPassField.trigger( 'focus' );
  123. } );
  124. } );
  125. } );
  126. $newAppPassField.on( 'keypress', function ( e ) {
  127. if ( 13 === e.which ) {
  128. e.preventDefault();
  129. $newAppPassButton.trigger( 'click' );
  130. }
  131. } );
  132. // If there are no items, don't display the table yet. If there are, show it.
  133. if ( 0 === $appPassTbody.children( 'tr' ).not( $appPassTrNoItems ).length ) {
  134. $appPassTwrapper.hide();
  135. }
  136. /**
  137. * Handles an error response from the REST API.
  138. *
  139. * @since 5.6.0
  140. *
  141. * @param {jqXHR} xhr The XHR object from the ajax call.
  142. * @param {string} textStatus The string categorizing the ajax request's status.
  143. * @param {string} errorThrown The HTTP status error text.
  144. */
  145. function handleErrorResponse( xhr, textStatus, errorThrown ) {
  146. var errorMessage = errorThrown;
  147. if ( xhr.responseJSON && xhr.responseJSON.message ) {
  148. errorMessage = xhr.responseJSON.message;
  149. }
  150. addNotice( errorMessage, 'error' );
  151. }
  152. /**
  153. * Displays a message in the Application Passwords section.
  154. *
  155. * @since 5.6.0
  156. *
  157. * @param {string} message The message to display.
  158. * @param {string} type The notice type. Either 'success' or 'error'.
  159. * @returns {jQuery} The notice element.
  160. */
  161. function addNotice( message, type ) {
  162. var $notice = $( '<div></div>' )
  163. .attr( 'role', 'alert' )
  164. .attr( 'tabindex', '-1' )
  165. .addClass( 'is-dismissible notice notice-' + type )
  166. .append( $( '<p></p>' ).text( message ) )
  167. .append(
  168. $( '<button></button>' )
  169. .attr( 'type', 'button' )
  170. .addClass( 'notice-dismiss' )
  171. .append( $( '<span></span>' ).addClass( 'screen-reader-text' ).text( wp.i18n.__( 'Dismiss this notice.' ) ) )
  172. );
  173. $newAppPassForm.after( $notice );
  174. return $notice;
  175. }
  176. /**
  177. * Clears notice messages from the Application Passwords section.
  178. *
  179. * @since 5.6.0
  180. */
  181. function clearNotices() {
  182. $( '.notice', $appPassSection ).remove();
  183. }
  184. }( jQuery ) );