',
+ $wrapper_attributes,
+ do_blocks( $content )
+ );
+}
+
+/**
+ * Get markup for a list of global events.
+ */
+function get_global_events_markup( string $filter, int $limit, bool $group_by_month ): string {
$facets = Events_2023\get_query_var_facets();
- $events = Google_Map\get_events( $attributes['events'], 0, 0, $facets );
+ $events = Google_Map\get_events( $filter, 0, 0, $facets );
// Get all the filters that are currently applied.
- $filtered_events = array_slice( filter_events( $events ), 0, (int) $attributes['limit'] );
+ $filtered_events = array_slice( filter_events( $events ), 0, $limit );
// The results are not guaranteed to be in order, so sort them.
usort( $filtered_events,
- function ( $a, $b ) {
+ function( $a, $b ) {
return $a->timestamp - $b->timestamp;
}
);
@@ -57,7 +99,7 @@ function ( $a, $b ) {
return get_no_result_view();
}
- if ( (bool) $attributes['groupByMonth'] ) {
+ if ( $group_by_month ) {
// Group events by month year.
$grouped_events = array();
foreach ( $filtered_events as $event ) {
@@ -74,12 +116,43 @@ function ( $a, $b ) {
$content = get_list_markup( $filtered_events );
}
- $wrapper_attributes = get_block_wrapper_attributes();
- return sprintf(
- '
%2$s
',
- $wrapper_attributes,
- do_blocks( $content )
- );
+ return $content;
+}
+
+/**
+ * Get markup for a list of nearby events.
+ *
+ * The events themselves are populated by an XHR, to avoid blocking the TTFB with an external HTTP request. See `view.js`.
+ */
+function get_nearby_events_markup(): string {
+ ob_start();
+
+ ?>
+
+
+
+
+ 0 ) {
+ for ( let i = 0; i < results.events.length; i++ ) {
+ const eventDiv = document.createElement( 'li' );
+ eventDiv.classList.add( 'wporg-marker-list-item' );
+ eventDiv.innerHTML = renderEvent( results.events[ i ] );
+ listContainer.appendChild( eventDiv );
+
+ // todo convert this to jsx to avoid xss
+ }
+
+ } else {
+ noEventsMessage.classList.remove( 'wporg-events__hidden' );
+ }
+
+ } catch ( error ) {
+ // This matches the format returned by the API for application-layer errors (e.g., invalid API key).
+ showGlobal();
+ chipsContainer.classList.add( 'wporg-events__hidden' );
+
+ } finally {
+ loadingElement.classList.add( 'wporg-events__hidden' );
+ }
+ }
+
+ /**
+ * Encode any HTML in a string to prevent XSS.
+ *
+ * @param {string} unsafe
+ *
+ * @returns {string}
+ */
+ function escapeHtml( unsafe ) {
+ const safe = document.createTextNode( unsafe ).textContent;
+
+ return safe;
+ }
+
+ // note needs to be in sync with get_list_markup
+ // maybe echo that as a template, then copy this into it? that might be just as tightly coupled though
+ // unless maybe pass a var to the function which tells it to php vs js, and then the value would be `${title}` for js and $event->title for php
+ function renderEvent( { title, url, location, start_unix_timestamp: timestamp } ) {
+ const markup = `
+
+
+ ${ getEventDateTime( title, timestamp ) }
+ `;
+
+ return markup;
+ }
+
+ /**
+ * Display a timestamp in the user's timezone and locale format.
+ *
+ * Note: The start time and day of the week are important pieces of information to include, since that helps
+ * attendees know at a glance if it's something they can attend. Otherwise they have to click to open it. The
+ * timezone is also important to make it clear that we're showing the user's timezone, not the venue's.
+ *
+ * @see https://make.wordpress.org/community/2017/03/23/showing-upcoming-local-events-in-wp-admin/#comment-23297
+ * @see https://make.wordpress.org/community/2017/03/23/showing-upcoming-local-events-in-wp-admin/#comment-23307
+ *
+ * @param {string} title
+ * @param {number} timestamp
+ *
+ * @return {string} The formatted date and time.
+ */
+ function getEventDateTime( title, timestamp ) {
+ const eventDate = new Date( escapeHtml( timestamp ) * 1000 );
+
+ const localeDate = eventDate.toLocaleDateString( [], {
+ weekday: 'long',
+ year: 'numeric',
+ month: 'short',
+ day: 'numeric',
+ } );
+
+ const localeTime = eventDate.toLocaleString( [], {
+ timeZoneName: 'short',
+ hour: 'numeric',
+ minute: '2-digit',
+ } );
+
+ return `
+
+ `;
+ }
+
+ init();
+ fetchLocalEvents();
+} );