wp/wp-admin/js/privacy-tools.js
changeset 16 a86126ab1dd4
child 18 be944660c56a
equal deleted inserted replaced
15:3d4e9c994f10 16:a86126ab1dd4
       
     1 /**
       
     2  * Interactions used by the User Privacy tools in WordPress.
       
     3  *
       
     4  * @output wp-admin/js/privacy-tools.js
       
     5  */
       
     6 
       
     7 // Privacy request action handling.
       
     8 jQuery( document ).ready( function( $ ) {
       
     9 	var __ = wp.i18n.__,
       
    10 		copiedNoticeTimeout;
       
    11 
       
    12 	function setActionState( $action, state ) {
       
    13 		$action.children().addClass( 'hidden' );
       
    14 		$action.children( '.' + state ).removeClass( 'hidden' );
       
    15 	}
       
    16 
       
    17 	function clearResultsAfterRow( $requestRow ) {
       
    18 		$requestRow.removeClass( 'has-request-results' );
       
    19 
       
    20 		if ( $requestRow.next().hasClass( 'request-results' ) ) {
       
    21 			$requestRow.next().remove();
       
    22 		}
       
    23 	}
       
    24 
       
    25 	function appendResultsAfterRow( $requestRow, classes, summaryMessage, additionalMessages ) {
       
    26 		var itemList = '',
       
    27 			resultRowClasses = 'request-results';
       
    28 
       
    29 		clearResultsAfterRow( $requestRow );
       
    30 
       
    31 		if ( additionalMessages.length ) {
       
    32 			$.each( additionalMessages, function( index, value ) {
       
    33 				itemList = itemList + '<li>' + value + '</li>';
       
    34 			});
       
    35 			itemList = '<ul>' + itemList + '</ul>';
       
    36 		}
       
    37 
       
    38 		$requestRow.addClass( 'has-request-results' );
       
    39 
       
    40 		if ( $requestRow.hasClass( 'status-request-confirmed' ) ) {
       
    41 			resultRowClasses = resultRowClasses + ' status-request-confirmed';
       
    42 		}
       
    43 
       
    44 		if ( $requestRow.hasClass( 'status-request-failed' ) ) {
       
    45 			resultRowClasses = resultRowClasses + ' status-request-failed';
       
    46 		}
       
    47 
       
    48 		$requestRow.after( function() {
       
    49 			return '<tr class="' + resultRowClasses + '"><th colspan="5">' +
       
    50 				'<div class="notice inline notice-alt ' + classes + '">' +
       
    51 				'<p>' + summaryMessage + '</p>' +
       
    52 				itemList +
       
    53 				'</div>' +
       
    54 				'</td>' +
       
    55 				'</tr>';
       
    56 		});
       
    57 	}
       
    58 
       
    59 	$( '.export-personal-data-handle' ).click( function( event ) {
       
    60 		var $this          = $( this ),
       
    61 			$action        = $this.parents( '.export-personal-data' ),
       
    62 			$requestRow    = $this.parents( 'tr' ),
       
    63 			$progress      = $requestRow.find( '.export-progress' ),
       
    64 			$rowActions    = $this.parents( '.row-actions' ),
       
    65 			requestID      = $action.data( 'request-id' ),
       
    66 			nonce          = $action.data( 'nonce' ),
       
    67 			exportersCount = $action.data( 'exporters-count' ),
       
    68 			sendAsEmail    = $action.data( 'send-as-email' ) ? true : false;
       
    69 
       
    70 		event.preventDefault();
       
    71 		event.stopPropagation();
       
    72 
       
    73 		$rowActions.addClass( 'processing' );
       
    74 
       
    75 		$action.blur();
       
    76 		clearResultsAfterRow( $requestRow );
       
    77 		setExportProgress( 0 );
       
    78 
       
    79 		function onExportDoneSuccess( zipUrl ) {
       
    80 			var summaryMessage = __( 'The personal data export link for this user was sent.' );
       
    81 
       
    82 			setActionState( $action, 'export-personal-data-success' );
       
    83 
       
    84 			appendResultsAfterRow( $requestRow, 'notice-success', summaryMessage, [] );
       
    85 
       
    86 			if ( 'undefined' !== typeof zipUrl ) {
       
    87 				window.location = zipUrl;
       
    88 			} else if ( ! sendAsEmail ) {
       
    89 				onExportFailure( __( 'No personal data export file was generated.' ) );
       
    90 			}
       
    91 
       
    92 			setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 );
       
    93 		}
       
    94 
       
    95 		function onExportFailure( errorMessage ) {
       
    96 			var summaryMessage = __( 'An error occurred while attempting to export personal data.' );
       
    97 
       
    98 			setActionState( $action, 'export-personal-data-failed' );
       
    99 
       
   100 			if ( errorMessage ) {
       
   101 				appendResultsAfterRow( $requestRow, 'notice-error', summaryMessage, [ errorMessage ] );
       
   102 			}
       
   103 
       
   104 			setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 );
       
   105 		}
       
   106 
       
   107 		function setExportProgress( exporterIndex ) {
       
   108 			var progress       = ( exportersCount > 0 ? exporterIndex / exportersCount : 0 ),
       
   109 				progressString = Math.round( progress * 100 ).toString() + '%';
       
   110 
       
   111 			$progress.html( progressString );
       
   112 		}
       
   113 
       
   114 		function doNextExport( exporterIndex, pageIndex ) {
       
   115 			$.ajax(
       
   116 				{
       
   117 					url: window.ajaxurl,
       
   118 					data: {
       
   119 						action: 'wp-privacy-export-personal-data',
       
   120 						exporter: exporterIndex,
       
   121 						id: requestID,
       
   122 						page: pageIndex,
       
   123 						security: nonce,
       
   124 						sendAsEmail: sendAsEmail
       
   125 					},
       
   126 					method: 'post'
       
   127 				}
       
   128 			).done( function( response ) {
       
   129 				var responseData = response.data;
       
   130 
       
   131 				if ( ! response.success ) {
       
   132 					// e.g. invalid request ID.
       
   133 					setTimeout( function() { onExportFailure( response.data ); }, 500 );
       
   134 					return;
       
   135 				}
       
   136 
       
   137 				if ( ! responseData.done ) {
       
   138 					setTimeout( doNextExport( exporterIndex, pageIndex + 1 ) );
       
   139 				} else {
       
   140 					setExportProgress( exporterIndex );
       
   141 					if ( exporterIndex < exportersCount ) {
       
   142 						setTimeout( doNextExport( exporterIndex + 1, 1 ) );
       
   143 					} else {
       
   144 						setTimeout( function() { onExportDoneSuccess( responseData.url ); }, 500 );
       
   145 					}
       
   146 				}
       
   147 			}).fail( function( jqxhr, textStatus, error ) {
       
   148 				// e.g. Nonce failure.
       
   149 				setTimeout( function() { onExportFailure( error ); }, 500 );
       
   150 			});
       
   151 		}
       
   152 
       
   153 		// And now, let's begin.
       
   154 		setActionState( $action, 'export-personal-data-processing' );
       
   155 		doNextExport( 1, 1 );
       
   156 	});
       
   157 
       
   158 	$( '.remove-personal-data-handle' ).click( function( event ) {
       
   159 		var $this         = $( this ),
       
   160 			$action       = $this.parents( '.remove-personal-data' ),
       
   161 			$requestRow   = $this.parents( 'tr' ),
       
   162 			$progress     = $requestRow.find( '.erasure-progress' ),
       
   163 			$rowActions   = $this.parents( '.row-actions' ),
       
   164 			requestID     = $action.data( 'request-id' ),
       
   165 			nonce         = $action.data( 'nonce' ),
       
   166 			erasersCount  = $action.data( 'erasers-count' ),
       
   167 			hasRemoved    = false,
       
   168 			hasRetained   = false,
       
   169 			messages      = [];
       
   170 
       
   171 		event.preventDefault();
       
   172 		event.stopPropagation();
       
   173 
       
   174 		$rowActions.addClass( 'processing' );
       
   175 
       
   176 		$action.blur();
       
   177 		clearResultsAfterRow( $requestRow );
       
   178 		setErasureProgress( 0 );
       
   179 
       
   180 		function onErasureDoneSuccess() {
       
   181 			var summaryMessage = __( 'No personal data was found for this user.' ),
       
   182 				classes = 'notice-success';
       
   183 
       
   184 			setActionState( $action, 'remove-personal-data-success' );
       
   185 
       
   186 			if ( false === hasRemoved ) {
       
   187 				if ( false === hasRetained ) {
       
   188 					summaryMessage = __( 'No personal data was found for this user.' );
       
   189 				} else {
       
   190 					summaryMessage = __( 'Personal data was found for this user but was not erased.' );
       
   191 					classes = 'notice-warning';
       
   192 				}
       
   193 			} else {
       
   194 				if ( false === hasRetained ) {
       
   195 					summaryMessage = __( 'All of the personal data found for this user was erased.' );
       
   196 				} else {
       
   197 					summaryMessage = __( 'Personal data was found for this user but some of the personal data found was not erased.' );
       
   198 					classes = 'notice-warning';
       
   199 				}
       
   200 			}
       
   201 			appendResultsAfterRow( $requestRow, classes, summaryMessage, messages );
       
   202 
       
   203 			setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 );
       
   204 		}
       
   205 
       
   206 		function onErasureFailure() {
       
   207 			var summaryMessage = __( 'An error occurred while attempting to find and erase personal data.' );
       
   208 
       
   209 			setActionState( $action, 'remove-personal-data-failed' );
       
   210 
       
   211 			appendResultsAfterRow( $requestRow, 'notice-error', summaryMessage, [] );
       
   212 
       
   213 			setTimeout( function() { $rowActions.removeClass( 'processing' ); }, 500 );
       
   214 		}
       
   215 
       
   216 		function setErasureProgress( eraserIndex ) {
       
   217 			var progress       = ( erasersCount > 0 ? eraserIndex / erasersCount : 0 ),
       
   218 				progressString = Math.round( progress * 100 ).toString() + '%';
       
   219 
       
   220 			$progress.html( progressString );
       
   221 		}
       
   222 
       
   223 		function doNextErasure( eraserIndex, pageIndex ) {
       
   224 			$.ajax({
       
   225 				url: window.ajaxurl,
       
   226 				data: {
       
   227 					action: 'wp-privacy-erase-personal-data',
       
   228 					eraser: eraserIndex,
       
   229 					id: requestID,
       
   230 					page: pageIndex,
       
   231 					security: nonce
       
   232 				},
       
   233 				method: 'post'
       
   234 			}).done( function( response ) {
       
   235 				var responseData = response.data;
       
   236 
       
   237 				if ( ! response.success ) {
       
   238 					setTimeout( function() { onErasureFailure(); }, 500 );
       
   239 					return;
       
   240 				}
       
   241 				if ( responseData.items_removed ) {
       
   242 					hasRemoved = hasRemoved || responseData.items_removed;
       
   243 				}
       
   244 				if ( responseData.items_retained ) {
       
   245 					hasRetained = hasRetained || responseData.items_retained;
       
   246 				}
       
   247 				if ( responseData.messages ) {
       
   248 					messages = messages.concat( responseData.messages );
       
   249 				}
       
   250 				if ( ! responseData.done ) {
       
   251 					setTimeout( doNextErasure( eraserIndex, pageIndex + 1 ) );
       
   252 				} else {
       
   253 					setErasureProgress( eraserIndex );
       
   254 					if ( eraserIndex < erasersCount ) {
       
   255 						setTimeout( doNextErasure( eraserIndex + 1, 1 ) );
       
   256 					} else {
       
   257 						setTimeout( function() { onErasureDoneSuccess(); }, 500 );
       
   258 					}
       
   259 				}
       
   260 			}).fail( function() {
       
   261 				setTimeout( function() { onErasureFailure(); }, 500 );
       
   262 			});
       
   263 		}
       
   264 
       
   265 		// And now, let's begin.
       
   266 		setActionState( $action, 'remove-personal-data-processing' );
       
   267 
       
   268 		doNextErasure( 1, 1 );
       
   269 	});
       
   270 
       
   271 	// Privacy Policy page, copy action.
       
   272 	$( document ).on( 'click', function( event ) {
       
   273 		var $parent,
       
   274 			$container,
       
   275 			range,
       
   276 			$target = $( event.target ),
       
   277 			copiedNotice = $target.siblings( '.success' );
       
   278 
       
   279 		clearTimeout( copiedNoticeTimeout );
       
   280 
       
   281 		if ( $target.is( 'button.privacy-text-copy' ) ) {
       
   282 			$parent = $target.parent().parent();
       
   283 			$container = $parent.find( 'div.wp-suggested-text' );
       
   284 
       
   285 			if ( ! $container.length ) {
       
   286 				$container = $parent.find( 'div.policy-text' );
       
   287 			}
       
   288 
       
   289 			if ( $container.length ) {
       
   290 				try {
       
   291 					var documentPosition = document.documentElement.scrollTop,
       
   292 						bodyPosition     = document.body.scrollTop;
       
   293 
       
   294 					// Setup copy.
       
   295 					window.getSelection().removeAllRanges();
       
   296 
       
   297 					// Hide tutorial content to remove from copied content.
       
   298 					range = document.createRange();
       
   299 					$container.addClass( 'hide-privacy-policy-tutorial' );
       
   300 
       
   301 					// Copy action.
       
   302 					range.selectNodeContents( $container[0] );
       
   303 					window.getSelection().addRange( range );
       
   304 					document.execCommand( 'copy' );
       
   305 
       
   306 					// Reset section.
       
   307 					$container.removeClass( 'hide-privacy-policy-tutorial' );
       
   308 					window.getSelection().removeAllRanges();
       
   309 
       
   310 					// Return scroll position - see #49540.
       
   311 					if ( documentPosition > 0 && documentPosition !== document.documentElement.scrollTop ) {
       
   312 						document.documentElement.scrollTop = documentPosition;
       
   313 					} else if ( bodyPosition > 0 && bodyPosition !== document.body.scrollTop ) {
       
   314 						document.body.scrollTop = bodyPosition;
       
   315 					}
       
   316 
       
   317 					// Display and speak notice to indicate action complete.
       
   318 					copiedNotice.addClass( 'visible' );
       
   319 					wp.a11y.speak( __( 'The section has been copied to your clipboard.' ) );
       
   320 
       
   321 					// Delay notice dismissal.
       
   322 					copiedNoticeTimeout = setTimeout( function() {
       
   323 						copiedNotice.removeClass( 'visible' );
       
   324 					}, 3000 );
       
   325 				} catch ( er ) {}
       
   326 			}
       
   327 		}
       
   328 	});
       
   329 });