My Pledges: Create template and block to list users' pledges.

This commit is contained in:
Kelly Dwan 2024-08-30 17:35:28 -04:00
parent f412bc8fba
commit 284016141b
No known key found for this signature in database
GPG key ID: 8BA5575F3D11575D
10 changed files with 424 additions and 3 deletions

View file

@ -9,6 +9,7 @@ require_once __DIR__ . '/inc/block-config.php';
require_once __DIR__ . '/inc/block-bindings.php';
// Block files.
require_once __DIR__ . '/src/my-pledge-list/index.php';
require_once __DIR__ . '/src/pledge-contributors/index.php';
require_once __DIR__ . '/src/pledge-edit-button/index.php';
require_once __DIR__ . '/src/pledge-teams/index.php';
@ -98,3 +99,27 @@ function add_body_class( $classes ) {
}
return $classes;
}
/**
* Filter the featured image to show an avatar on the `my-pledges` page.
*
* @param string $html The post thumbnail HTML.
* @param int $post_id The post ID.
* @param int $post_thumbnail_id The post thumbnail ID, or 0 if there isn't one.
* @param string|int[] $size Requested image size. Can be any registered image size name, or
* an array of width and height values in pixels (in that order).
* @param string|array $attr Query string or array of attributes.
*
* @return string Updated HTML.
*/
function swap_avatar_for_featured_image( $html, $post_id, $post_thumbnail_id, $size, $attr ) {
if ( is_page( 'my-pledges' ) && empty( $html ) ) {
$attr_str = '';
foreach ( $attr as $name => $value ) {
$attr_str .= " $name=" . '"' . $value . '"';
}
$html = get_avatar( wp_get_current_user(), 110, 'mystery', '', array( 'extra_attr' => $attr_str ) );
}
return $html;
}
add_filter( 'post_thumbnail_html', __NAMESPACE__ . '\swap_avatar_for_featured_image', 10, 5 );

View file

@ -5,8 +5,9 @@
namespace WordPressdotorg\Theme\FiveForTheFuture_2024\Block_Bindings;
use WordPressDotOrg\FiveForTheFuture\XProfile;
use function WordPressDotOrg\FiveForTheFuture\PledgeMeta\get_pledge_meta;
use function WordPressDotOrg\FiveForTheFuture\XProfile\get_aggregate_contributor_data_for_pledge;
use const WordPressDotOrg\FiveForTheFuture\Contributor\CPT_ID as CONTRIBUTOR_POST_TYPE;
add_action( 'init', __NAMESPACE__ . '\register_block_bindings' );
@ -48,7 +49,7 @@ function get_meta_binding_value( $args, $block ) {
esc_html( $data['org-domain'] )
);
case 'org-contribution-details':
$contribution_data = get_aggregate_contributor_data_for_pledge( $block->context['postId'] );
$contribution_data = XProfile\get_aggregate_contributor_data_for_pledge( $block->context['postId'] );
return sprintf(
__( '%1$s sponsors %2$s for a total of <strong>%3$s hours</strong> per week across <strong>%4$d teams</strong>.', 'wporg-5ftf' ),
get_the_title( $block->context['postId'] ),
@ -60,10 +61,42 @@ function get_meta_binding_value( $args, $block ) {
count( $contribution_data['teams'] )
);
case 'org-contribution-short-details':
$contribution_data = get_aggregate_contributor_data_for_pledge( $block->context['postId'] );
$contribution_data = XProfile\get_aggregate_contributor_data_for_pledge( $block->context['postId'] );
return sprintf(
__( 'Has pledged %s hours per week.', 'wporg-5ftf' ),
number_format_i18n( absint( $contribution_data['hours'] ) ),
);
case 'user-contribution-details':
$user = wp_get_current_user();
if ( ! $user ) {
return '';
}
$profile_data = XProfile\get_contributor_user_data( $user->ID );
$contributor_publish_query = new \WP_Query( array(
'title' => $user->user_login,
'post_type' => CONTRIBUTOR_POST_TYPE,
'post_status' => array( 'publish' ),
'posts_per_page' => 100,
'fields' => 'ids',
) );
$pledge_count = $contributor_publish_query->found_posts;
return wp_kses_data( sprintf(
/* translators: %1$s is the number of hours, %2$s is the number of organizations, and %3$s is an edit link. */
_n(
'Pledged <strong>%1$s hours a week</strong> %3$s across %2$s organization.',
'Pledged <strong>%1$s hours a week</strong> %3$s across %2$s organizations.',
$pledge_count,
'wporg-5ftf'
),
$profile_data['hours_per_week'],
$pledge_count,
sprintf(
'<a aria-label="%1$s" href="https://profiles.wordpress.org/me/profile/edit/group/5/">%2$s</a>',
__( 'edit hours pledged', 'wporg-5ftf' ),
__( '(edit)', 'wporg-5ftf' )
)
) );
}
}

View file

@ -0,0 +1,37 @@
<?php
/**
* Title: My Pledges
* Slug: wporg-5ftf-2024/my-pledges
* Inserter: no
*/
?>
<!-- wp:group {"align":"wide","style":{"spacing":{"margin":{"bottom":"var:preset|spacing|40"},"blockGap":"var:preset|spacing|40"}},"layout":{"type":"flex","flexWrap":"nowrap"}} -->
<div class="wp-block-group alignwide" style="margin-bottom:var(--wp--preset--spacing--40)">
<!-- wp:group {"style":{"border":{"radius":"50%"}},"backgroundColor":"light-grey-2","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-light-grey-2-background-color has-background" style="border-radius:50%">
<!-- wp:post-featured-image {"aspectRatio":"1","width":"110px","scale":"contain","style":{"border":{"radius":"50%"}}} /-->
</div>
<!-- /wp:group -->
<!-- wp:group {"style":{"spacing":{"blockGap":"var:preset|spacing|10"}},"layout":{"type":"flex","orientation":"vertical"}} -->
<div class="wp-block-group">
<!-- wp:post-title {"level":1,"style":{"spacing":{"margin":{"top":"0"}}}} /-->
<!-- wp:paragraph {"metadata":{"bindings":{"content":{"source":"wporg-5ftf/pledge-meta","args":{"key":"user-contribution-details"}}}}} -->
<p>Pledged <strong>40 hours a week</strong> (edit) across 1 organization.</p>
<!-- /wp:paragraph -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<!-- wp:group {"align":"wide","layout":{"type":"default"}} -->
<div class="wp-block-group alignwide">
<!-- wp:wporg/my-pledge-list /-->
<!-- wp:spacer {"height":"var:preset|spacing|40","style":{"spacing":{"margin":{"top":"var:preset|spacing|40"}}}} -->
<div style="margin-top:var(--wp--preset--spacing--40);height:0" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
</div>
<!-- /wp:group -->

View file

@ -0,0 +1,17 @@
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 2,
"name": "wporg/my-pledge-list",
"version": "0.1.0",
"title": "My pledges",
"category": "design",
"icon": "",
"description": "List out the pledges for this user.",
"textdomain": "wporg",
"supports": {
"html": false
},
"editorScript": "file:./index.js",
"style": "file:./style-index.css",
"render": "file:./render.php"
}

View file

@ -0,0 +1,26 @@
/**
* WordPress dependencies
*/
import { registerBlockType } from '@wordpress/blocks';
import { useBlockProps } from '@wordpress/block-editor';
import ServerSideRender from '@wordpress/server-side-render';
/**
* Internal dependencies
*/
import metadata from './block.json';
import './style.scss';
const Edit = ( { attributes, name } ) => {
const blockProps = useBlockProps();
return (
<div { ...blockProps }>
<ServerSideRender block={ name } attributes={ attributes } skipBlockSupportAttributes />
</div>
);
};
registerBlockType( metadata.name, {
edit: Edit,
save: () => null,
} );

View file

@ -0,0 +1,135 @@
<?php
/**
* Block Name: My pledges
* Description: List out the pledges for this user.
*
* @package wporg
*/
namespace WordPressdotorg\Theme\FiveForTheFuture_2024\My_Pledge_List;
defined( 'WPINC' ) || die();
add_action( 'init', __NAMESPACE__ . '\init' );
/**
* Register the block.
*/
function init() {
register_block_type( dirname( __DIR__, 2 ) . '/build/my-pledge-list' );
}
/**
* Helper function to render single pledges in My Pledge list.
*/
function render_single_pledge( $contributor_post, $has_profile_data ) {
global $post;
// phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited -- Intentionally overriding so it's available in post blocks.
$post = get_post( $contributor_post->post_parent );
setup_postdata( $post );
ob_start();
?>
<!-- wp:group {"style":{"spacing":{"blockGap":"var:preset|spacing|70"}},"layout":{"type":"flex","flexWrap":"nowrap","verticalAlignment":"top"},"className":"my-pledges__pledge"} -->
<div class="wp-block-group my-pledges__pledge">
<!-- wp:group {"style":{"border":{"style":"solid","width":"1px","color":"#d9d9d9","radius":"2px"},"spacing":{"padding":{"top":"var:preset|spacing|20","bottom":"var:preset|spacing|20","left":"var:preset|spacing|20","right":"var:preset|spacing|20"}}},"backgroundColor":"light-grey-2","layout":{"type":"constrained"}} -->
<div class="wp-block-group has-border-color has-light-grey-2-background-color has-background" style="border-color:#d9d9d9;border-style:solid;border-width:1px;border-radius:2px;padding-top:var(--wp--preset--spacing--20);padding-right:var(--wp--preset--spacing--20);padding-bottom:var(--wp--preset--spacing--20);padding-left:var(--wp--preset--spacing--20)">
<!-- wp:post-featured-image {"aspectRatio":"1","width":"275px","scale":"contain"} /-->
</div>
<!-- /wp:group -->
<!-- wp:group {"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:group {"style":{"spacing":{"blockGap":"var:preset|spacing|10"}},"layout":{"type":"constrained"}} -->
<div class="wp-block-group">
<!-- wp:post-title {"level":3,"isLink":true,"style":{"typography":{"fontStyle":"normal","fontWeight":"600"}},"fontSize":"heading-4","fontFamily":"inter"} /-->
<!-- wp:paragraph -->
<p>
<?php
if ( 'publish' === $contributor_post->post_status ) {
echo esc_html( sprintf(
__( 'You confirmed this pledge on %s', 'wporg-5ftf' ),
gmdate( get_option( 'date_format' ), strtotime( $contributor_post->post_date ) )
) );
} else {
echo esc_html_e( 'This organization would like to pledge your time', 'wporg-5ftf' );
}
?>
</p>
<!-- /wp:paragraph -->
<div class="my-pledges__pledge-actions">
<form action="" method="post">
<input type="hidden" name="contributor_post_id" value="<?php echo esc_attr( $contributor_post->ID ); ?>" />
<?php if ( 'pending' === $contributor_post->post_status ) : ?>
<?php wp_nonce_field( 'join_decline_organization_' . $contributor_post->ID ); ?>
<div class="wp-block-button is-small">
<input
type="submit"
class="button button-default wp-block-button__link wp-element-button"
name="join_organization"
value="Join Organization"
<?php if ( ! $has_profile_data ) : ?>
disabled="disabled"
<?php endif; ?>
/>
</div>
<div class="wp-block-button is-style-outline is-small">
<input
type="submit"
class="button button-danger button-link wp-block-button__link wp-element-button"
name="decline_invitation"
value="Decline Invitation"
/>
</div>
<?php elseif ( 'publish' === $contributor_post->post_status ) : ?>
<?php wp_nonce_field( 'leave_organization_' . $contributor_post->ID ); ?>
<div class="wp-block-button is-style-outline is-destructive is-small">
<input
type="submit"
class="button button-danger wp-block-button__link wp-element-button"
name="leave_organization"
value="Leave Organization"
/>
</div>
<?php endif; ?>
</form>
</div>
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
</div>
<!-- /wp:group -->
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content escaped inline.
echo do_blocks( ob_get_clean() );
wp_reset_postdata();
}
/**
* Helper function to render notices using the notice block styles.
*
* @param string $type Type of message to render, one of `tip`, `info`, `alert`, `warning`.
* @param string $message The message to display.
*/
function render_notice( $type, $message ) {
ob_start();
?>
<!-- wp:wporg/notice {"type":"<?php echo esc_attr( $type ); ?>"} -->
<div class="wp-block-wporg-notice is-<?php echo esc_attr( $type ); ?>-notice">
<div class="wp-block-wporg-notice__icon"></div>
<div class="wp-block-wporg-notice__content"><p><?php echo wp_kses_data( $message ); ?></p></div>
</div>
<!-- /wp:wporg/notice -->
<?php
// phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped -- Content escaped inline.
echo do_blocks( ob_get_clean() );
}

View file

@ -0,0 +1,97 @@
<?php
/**
* Render the pledge list for the current user.
* Mostly copied from Contributor\render_my_pledges, updated markup to use blocks.
*/
use WordPressDotOrg\FiveForTheFuture\{ Contributor, XProfile };
use function WordPressdotorg\Theme\FiveForTheFuture_2024\My_Pledge_List\{render_single_pledge, render_notice};
use const WordPressDotOrg\FiveForTheFuture\Contributor\CPT_ID as CONTRIBUTOR_POST_TYPE;
if ( ! is_user_logged_in() ) {
// @todo — add error message.
return;
}
$user = wp_get_current_user();
$profile_data = XProfile\get_contributor_user_data( $user->ID );
$pledge_url = get_permalink( get_page_by_path( 'for-organizations' ) );
$success_message = Contributor\process_my_pledges_form();
$contributor_pending_posts = get_posts( array(
'title' => $user->user_login,
'post_type' => CONTRIBUTOR_POST_TYPE,
'post_status' => array( 'pending' ),
'numberposts' => 100,
) );
$contributor_publish_posts = get_posts( array(
'title' => $user->user_login,
'post_type' => CONTRIBUTOR_POST_TYPE,
'post_status' => array( 'publish' ),
'numberposts' => 100,
) );
$has_contributions = $contributor_pending_posts || $contributor_publish_posts;
$has_profile_data = $profile_data['hours_per_week'] && $profile_data['team_names'];
?>
<div
<?php echo get_block_wrapper_attributes(); // phpcs:ignore ?>
>
<?php
if ( $success_message ) {
render_notice( 'info', $success_message );
echo '<div style="margin-top:var(--wp--preset--spacing--20);height:0" aria-hidden="true" class="wp-block-spacer"></div>';
}
?>
<?php if ( $has_contributions ) : ?>
<?php if ( $contributor_publish_posts ) : ?>
<div class="my-pledges__list">
<?php
foreach ( $contributor_publish_posts as $contributor_post ) {
render_single_pledge( $contributor_post, $has_profile_data );
}
?>
</div>
<?php endif; ?>
<?php if ( $contributor_pending_posts ) : ?>
<div class="my-pledges__list is-pending-list">
<h2><?php esc_html_e( 'Pending Pledges', 'wporg-5ftf' ); ?></h2>
<?php
if ( ! $has_profile_data ) {
render_notice(
'warning',
sprintf(
__( 'You need to <a href="%s">update your profile</a> before joining an organization.', 'wporg-5ftf' ),
'https://profiles.wordpress.org/me/profile/edit/group/5/'
)
);
}
foreach ( $contributor_pending_posts as $contributor_post ) {
render_single_pledge( $contributor_post, $has_profile_data );
}
?>
</div>
<?php endif; ?>
<?php else : ?>
<?php echo wp_kses_data( sprintf(
__( 'You dont currently have any sponsorships. If your employer is sponsoring part of your time to contribute to WordPress, please ask them to <a href="%s">submit a pledge</a> and list you as a contributor.', 'wporg-5ftf' ),
esc_url( $pledge_url )
) ); ?>
<?php // todo add some resources here about how they can convince their boss to sponsor some of their time? ?>
<?php endif; ?>
</div>

View file

@ -0,0 +1,18 @@
.my-pledges__list > * + * {
margin-top: var(--wp--preset--spacing--60);
}
.my-pledges__list.is-pending-list > .wp-block-wporg-notice {
margin-top: var(--wp--preset--spacing--20);
}
.my-pledges__pledge-actions {
.wp-block-button {
display: inline-block;
[disabled="disabled"] {
--wp--custom--button--color--background: var(--wp--preset--color--blueberry-2);
pointer-events: none;
}
}
}

View file

@ -51,6 +51,24 @@
}
}
.form-field__logo-display {
box-sizing: content-box;
padding: var(--wp--preset--spacing--20);
border-color: var(--wp--preset--color--light-grey-1);
border-style: solid;
border-width: 1px;
border-radius: 2px;
background-color: var(--wp--preset--color--light-grey-2);
aspect-ratio: 1;
width: 275px;
img {
width: 100%;
height: 100%;
object-fit: contain;
}
}
.form-field__agree {
display: flex;
gap: var(--wp--preset--spacing--10);

View file

@ -0,0 +1,15 @@
<!-- wp:template-part {"slug":"header","className":"has-display-contents"} /-->
<!-- wp:group {"tagName":"article","layout":{"inherit":true,"type":"constrained"}} -->
<article class="wp-block-group">
<!-- wp:pattern {"slug":"wporg-5ftf-2024/my-pledges"} /-->
</article>
<!-- /wp:group -->
<!-- wp:spacer {"height":"var:preset|spacing|40","style":{"spacing":{"margin":{"top":"var:preset|spacing|40"}}}} -->
<div style="margin-top:var(--wp--preset--spacing--40);height:0" aria-hidden="true" class="wp-block-spacer"></div>
<!-- /wp:spacer -->
<!-- wp:template-part {"slug":"footer"} /-->