Refactor to use JSON + templates for contributors

This will make it easier to show contributors as they're added
This commit is contained in:
Kelly Dwan 2019-11-13 15:35:39 -05:00
parent aa79c8147e
commit b0672a6f6e
No known key found for this signature in database
GPG key ID: 8BA5575F3D11575D
5 changed files with 151 additions and 69 deletions

View file

@ -1,7 +1,66 @@
/* global ajaxurl, FiveForTheFuture, jQuery */ /* global ajaxurl, FiveForTheFuture, fftfContributors, jQuery */
/* eslint no-alert: "off" */ /* eslint no-alert: "off" */
jQuery( document ).ready( function( $ ) { jQuery( document ).ready( function( $ ) {
/**
* Render the contributor lists using the contributors template into the pledge-contributors container. This
* uses `_renderContributors` to render a list of contributors per status (published, pending).
*
* @param {Object} contributors - An object listing all contributors on a pledge.
* @param {Object[]} contributors.publish - The list of published/confirmed contributors.
* @param {Object[]} contributors.pending - The list of pending/unconfirmed contributors.
* @param {Object} container - The parent container for this section.
*/
function render( contributors, container ) {
const listContainer = container.querySelector( '.pledge-contributors' );
const template = wp.template( '5ftf-contributor-lists' );
const data = {
publish: _renderContributors( contributors.publish ),
pending: _renderContributors( contributors.pending ),
};
$( listContainer ).html( template( data ) );
}
/**
* Render a given contributor list using the contributor template.
*
* @param {Object[]} contributors - An array of contributor data objects.
* @return {string} An HTML string of contributors.
*/
function _renderContributors( contributors ) {
if ( ! contributors ) {
return [];
}
const template = wp.template( '5ftf-contributor' );
return contributors.map( template ).join( '' );
}
/**
* The default callback for AJAX actions.
*
* @param {Object} response - An array of contributor data objects.
* @param {string} response.message - An optional message to display to the user.
* @param {Object[]} response.contributors - The new list of contributors.
*/
function defaultCallback( response ) {
if ( response.message ) {
alert( response.message );
}
if ( response.contributors ) {
render( response.contributors, container );
}
}
/**
* Send an ajax request using the `manage_contributors` action. This function also automatically adds the
* nonce, which should be defined in the global FiveForTheFuture variable.
*
* @param {Object} data - A list of data to send to the endpoint.
* @param {Function} callback - A function to be called when the request completes.
*/
function sendAjaxRequest( data, callback ) { function sendAjaxRequest( data, callback ) {
if ( ! callback ) {
callback = defaultCallback;
}
$.ajax( { $.ajax( {
type: 'POST', type: 'POST',
url: ajaxurl, url: ajaxurl,
@ -14,7 +73,9 @@ jQuery( document ).ready( function( $ ) {
} ); } );
} }
// Initialize.
const container = document.getElementById( '5ftf-contributors' ); const container = document.getElementById( '5ftf-contributors' );
render( fftfContributors, container );
// Remove Contributor button action. // Remove Contributor button action.
$( container ).on( 'click', '[data-action="remove-contributor"]', function( event ) { $( container ).on( 'click', '[data-action="remove-contributor"]', function( event ) {
@ -28,13 +89,6 @@ jQuery( document ).ready( function( $ ) {
pledge_id: data.pledgePost || 0, pledge_id: data.pledgePost || 0,
contributor_id: data.contributorPost || 0, contributor_id: data.contributorPost || 0,
manage_action: data.action || '', manage_action: data.action || '',
}, function( response ) {
if ( response.message ) {
alert( response.message );
}
if ( response.success ) {
$( event.currentTarget ).closest( 'li' ).remove();
}
} ); } );
} }
} ); } );
@ -48,10 +102,6 @@ jQuery( document ).ready( function( $ ) {
pledge_id: data.pledgePost || 0, pledge_id: data.pledgePost || 0,
contributor_id: data.contributorPost || 0, contributor_id: data.contributorPost || 0,
manage_action: data.action || '', manage_action: data.action || '',
}, function( response ) {
if ( response.message ) {
alert( response.message );
}
} ); } );
} ); } );
} ); } );

View file

@ -238,6 +238,41 @@ function get_pledge_contributors( $pledge_id, $status = 'publish', $contributor_
return $posts; return $posts;
} }
/**
* Get the contributor posts in the format used for the JS templates.
*
* @param int $pledge_id The post ID of the pledge.
*
* @return array An array of contributor data, ready to be used in the JS templates.
*/
function get_pledge_contributors_data( $pledge_id ) {
$contrib_data = array();
$contributors = get_pledge_contributors( $pledge_id, 'all' );
foreach ( $contributors as $contributor_status => $group ) {
$contrib_data[ $contributor_status ] = array_map(
function( $contributor_post ) use ( $contributor_status, $pledge_id ) {
$name = $contributor_post->post_title;
$contributor = get_user_by( 'login', $name );
return [
'pledgeId' => $pledge_id,
'contributorId' => $contributor_post->ID,
'status' => $contributor_status,
'avatar' => get_avatar( $contributor, 32 ),
// @todo Add full name, from `$contributor`?
'name' => $name,
'resendLabel' => __( 'Resend Confirmation', 'wporg' ),
'removeConfirm' => sprintf( __( 'Remove %s from this pledge?', 'wporg-5ftf' ), $name ),
'removeLabel' => sprintf( __( 'Remove %s', 'wporg' ), $name ),
];
},
$group
);
}
return $contrib_data;
}
/** /**
* Get the user objects that correspond with pledge contributor posts. * Get the user objects that correspond with pledge contributor posts.
* *

View file

@ -34,6 +34,7 @@ function handler() {
Contributor\remove_contributor( $contributor_id ); Contributor\remove_contributor( $contributor_id );
wp_die( wp_json_encode( [ wp_die( wp_json_encode( [
'success' => true, 'success' => true,
'contributors' => Contributor\get_pledge_contributors_data( $pledge_id ),
] ) ); ] ) );
break; break;
} }

View file

@ -210,7 +210,7 @@ function render_meta_boxes( $pledge, $box ) {
$data[ $key ] = get_post_meta( $pledge->ID, META_PREFIX . $key, $config['single'] ); $data[ $key ] = get_post_meta( $pledge->ID, META_PREFIX . $key, $config['single'] );
} }
$contributors = Contributor\get_pledge_contributors( $pledge->ID, 'all' ); $contributors = Contributor\get_pledge_contributors_data( $pledge->ID );
echo '<div class="pledge-form">'; echo '<div class="pledge-form">';

View file

@ -8,63 +8,59 @@ use function WordPressDotOrg\FiveForTheFuture\get_views_path;
/** @var bool $readonly */ /** @var bool $readonly */
?> ?>
<div id="5ftf-contributors"> <script type="text/template" id="tmpl-5ftf-contributor-lists">
<?php if ( ! empty( $contributors ) ) : ?> <# if ( data.publish.length ) { #>
<?php foreach ( $contributors as $contributor_status => $group ) : ?> <h3 class="contributor-list-heading"><?php esc_html_e( 'Confirmed', 'wporg' ); ?></h3>
<?php if ( ! empty( $group ) ) : ?> <ul class="contributor-list publish">{{{ data.publish }}}</ul>
<h3 class="contributor-list-heading"> <# } #>
<?php <# if ( data.pending.length ) { #>
switch ( $contributor_status ) { <h3 class="contributor-list-heading"><?php esc_html_e( 'Unconfirmed', 'wporg' ); ?></h3>
case 'pending': <ul class="contributor-list pending">{{{ data.pending }}}</ul>
esc_html_e( 'Unconfirmed', 'wporg' ); <# } #>
break; </script>
case 'publish':
esc_html_e( 'Confirmed', 'wporg' );
break;
}
?>
</h3>
<ul class="contributor-list <?php echo esc_attr( $contributor_status ); ?>"> <script type="text/template" id="tmpl-5ftf-contributor">
<?php foreach ( $group as $contributor_post ) :
$name = $contributor_post->post_title;
$contributor = get_user_by( 'login', $name );
$remove_confirm = sprintf( __( 'Remove %s from this pledge?', 'wporg-5ftf' ), $name );
$remove_label = sprintf( __( 'Remove %s', 'wporg' ), $name );
?>
<li> <li>
<button <button
class="button-link button-link-delete" class="button-link button-link-delete"
data-action="remove-contributor" data-action="remove-contributor"
data-pledge-post="<?php the_ID(); ?>" data-pledge-post="{{ data.pledgeId }}"
data-contributor-post="<?php echo esc_attr( $contributor_post->ID ); ?>" data-contributor-post="{{ data.contributorId }}"
data-confirm="<?php echo esc_attr( $remove_confirm ); ?>" data-confirm="{{ data.removeConfirm }}"
aria-label="<?php echo esc_attr( $remove_label ); ?>" aria-label="{{ data.removeLabel }}"
> >
<span class="dashicons dashicons-no-alt" aria-hidden="true"></span> <span class="dashicons dashicons-no-alt" aria-hidden="true"></span>
</button> </button>
<?php echo get_avatar( $contributor->user_email, 32 ); ?> {{{ data.avatar }}}
<span class="contributor-list__name"> <span class="contributor-list__name">
<?php echo esc_html( $name ); ?> {{ data.name }}
</span> </span>
<?php if ( 'pending' === $contributor_post->post_status ) : ?> <# if ( 'pending' === data.status ) { #>
<button <button
class="button" class="button"
data-action="resend-contributor-confirmation" data-action="resend-contributor-confirmation"
data-pledge-post="<?php the_ID(); ?>" data-pledge-post="{{ data.pledgeId }}"
data-contributor-post="<?php echo esc_attr( $contributor_post->ID ); ?>" data-contributor-post="{{ data.contributorId }}"
> >
<?php esc_html_e( 'Resend Confirmation', 'wporg' ); ?> {{ data.resendLabel }}
</button> </button>
<?php endif; ?> <# } #>
</li> </li>
<?php endforeach; ?> </script>
</ul>
<?php endif; ?> <div id="5ftf-contributors">
<?php endforeach; ?> <div class="pledge-contributors">
<?php if ( ! empty( $contributors ) ) : ?>
<?php
printf(
'<script>var fftfContributors = JSON.parse( decodeURIComponent( \'%s\' ) );</script>',
rawurlencode( wp_json_encode( $contributors ) )
);
?>
<?php else : ?> <?php else : ?>
<p><?php esc_html_e( 'There are no contributors added to this pledge yet.', 'wporg' ); ?></p> <p><?php esc_html_e( 'There are no contributors added to this pledge yet.', 'wporg' ); ?></p>
<?php endif; ?> <?php endif; ?>
</div>
<hr /> <hr />