From eba1a3c3841a0e3c6250e20a41ad2df2738cef87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Amieiro=20Becerra?= <1667814+amieiro@users.noreply.github.com> Date: Fri, 16 Feb 2024 14:23:53 +0100 Subject: [PATCH] Add the delete button in the edit form of an event (#69) * Add the delete button in the edit form of an event * Check that a trashed event can not be edited * Move some logic outside the template * Fix style * Check if the show_delete_button variable exists in the template * Add the delete_event in the action * Remove some unnecesary conditions * Fix some problems with the Delete button visibility * Add a method to know if an event has stats * Change the $_POST['form_name'] to $action to know if the action is 'delete_event' * Fix styles --- assets/js/translation-events.js | 34 ++++++++++-- ...lass-wporg-gp-translation-events-route.php | 35 ++++++++---- ...gp-translation-events-stats-calculator.php | 17 ++++++ templates/events-form.php | 4 ++ wporg-gp-translation-events.php | 54 +++++++++++++------ 5 files changed, 113 insertions(+), 31 deletions(-) diff --git a/assets/js/translation-events.js b/assets/js/translation-events.js index 2087e31c..28b7bd4b 100644 --- a/assets/js/translation-events.js +++ b/assets/js/translation-events.js @@ -22,6 +22,7 @@ jQuery(document).ready(function($) { } $('#event-form-action').val( btnClicked ); var $form = $('.translation-event-form'); + var $is_creation = $('#form-name').val() == 'create_event' ? true : false; $.ajax({ type: 'POST', @@ -41,6 +42,9 @@ jQuery(document).ready(function($) { $('button[data-event-status="draft"]').text('Update Draft'); } $('#event-url').removeClass('hide-event-url').find('a').attr('href', response.data.eventUrl).text(response.data.eventUrl); + if ( $is_creation ) { + $('#delete-button').toggle(); + } $gp.notices.success(response.data.message); } }, @@ -50,7 +54,27 @@ jQuery(document).ready(function($) { }); }); - function validateEventDates() { + $('.delete-event').on('click', function(e) { + e.preventDefault(); + if ( ! confirm( 'Are you sure you want to delete this event?' ) ) { + return; + } + var $form = $('.translation-event-form'); + $('#form-name').val('delete_event'); + $('#event-form-action').val( 'delete' ); + $.ajax({ + type: 'POST', + url: $translation_event.url, + data:$form.serialize(), + success: function(response) { + window.location = response.data.eventDeleteUrl; + }, + error: function(error) { + $gp.notices.error(response.data.message); + }, + }); + }); + function validateEventDates() { var startDateTimeInput = $('#event-start'); var endDateTimeInput = $('#event-end'); if ( ! startDateTimeInput.length || ! endDateTimeInput.length ) { @@ -65,7 +89,7 @@ jQuery(document).ready(function($) { }); } function selectUserTimezone() { - document.querySelector(`#event-timezone option[value="${Intl.DateTimeFormat().resolvedOptions().timeZone}"]`).selected = true + document.querySelector(`#event-timezone option[value="${Intl.DateTimeFormat().resolvedOptions().timeZone}"]`).selected = true } function convertToUserLocalTime() { @@ -80,11 +104,11 @@ jQuery(document).ready(function($) { var userLocalDateTime = new Date(eventDateObj.getTime() - userTimezoneOffsetMs); var options = { weekday: 'short', year: 'numeric', month: 'long', day: 'numeric', hour: 'numeric', minute: 'numeric', hour12: true, timeZoneName: 'short' }; - + timeEl.textContent = userLocalDateTime.toLocaleString('en-US', options); }); } - + }); }( jQuery, $gp ) -); \ No newline at end of file +); diff --git a/includes/class-wporg-gp-translation-events-route.php b/includes/class-wporg-gp-translation-events-route.php index 7e809ed8..aeb7ecc2 100644 --- a/includes/class-wporg-gp-translation-events-route.php +++ b/includes/class-wporg-gp-translation-events-route.php @@ -108,16 +108,18 @@ public function events_create() { if ( ! is_user_logged_in() ) { $this->die_with_error( 'You must be logged in to create an event', 403 ); } - $event_form_title = 'Create Event'; - $event_form_name = 'create_event'; - $css_show_url = 'hide-event-url'; - $event_id = null; - $event_title = ''; - $event_description = ''; - $event_timezone = ''; - $event_start = ''; - $event_end = ''; - $event_url = ''; + $event_form_title = 'Create Event'; + $event_form_name = 'create_event'; + $css_show_url = 'hide-event-url'; + $event_id = null; + $event_title = ''; + $event_description = ''; + $event_timezone = ''; + $event_start = ''; + $event_end = ''; + $event_url = ''; + $create_delete_button = true; + $visibility_delete_button = 'none'; $this->tmpl( 'events-form', get_defined_vars() ); } @@ -137,6 +139,9 @@ public function events_edit( int $event_id ) { if ( ! $event || 'event' !== $event->post_type || ! ( current_user_can( 'edit_post', $event->ID ) || intval( $event->post_author ) === get_current_user_id() ) ) { $this->die_with_error( 'Event does not exist, or you do not have permission to edit it.', 403 ); } + if ( 'trash' === $event->post_status ) { + $this->die_with_error( 'You cannot edit a trashed event', 403 ); + } include ABSPATH . 'wp-admin/includes/post.php'; $event_form_title = 'Edit Event'; @@ -149,6 +154,16 @@ public function events_edit( int $event_id ) { $permalink = str_replace( '%pagename%', $post_name, $permalink ); $event_url = get_site_url() . gp_url( wp_make_link_relative( $permalink ) ); $event_timezone = get_post_meta( $event_id, '_event_timezone', true ) ?: ''; + $create_delete_button = false; + $visibility_delete_button = 'inline-flex'; + + $stats_calculator = new WPORG_GP_Translation_Events_Stats_Calculator(); + if ( ! $stats_calculator->event_has_stats( $event ) ) { + $current_user = wp_get_current_user(); + if ( $current_user->ID === $event->post_author || current_user_can( 'manage_options' ) ) { + $create_delete_button = true; + } + } try { $event_start = self::convertToTimezone( get_post_meta( $event_id, '_event_start', true ), $event_timezone ); diff --git a/includes/class-wporg-gp-translation-events-stats-calculator.php b/includes/class-wporg-gp-translation-events-stats-calculator.php index e2cfda89..b66e2dc7 100644 --- a/includes/class-wporg-gp-translation-events-stats-calculator.php +++ b/includes/class-wporg-gp-translation-events-stats-calculator.php @@ -109,4 +109,21 @@ public function for_event( WP_Post $event ): WPORG_GP_Translation_Events_Event_S return $stats; } + + /** + * Check if an event has stats. + * + * @param WP_Post $event The event to check. + * + * @return bool True if the event has stats, false otherwise. + */ + public function event_has_stats( WP_Post $event ): bool { + try { + $stats = $this->for_event( $event ); + } catch ( Exception $e ) { + return false; + } + + return ! empty( $stats->rows() ); + } } diff --git a/templates/events-form.php b/templates/events-form.php index 31cce4f4..04100425 100644 --- a/templates/events-form.php +++ b/templates/events-form.php @@ -76,5 +76,9 @@ + + + + diff --git a/wporg-gp-translation-events.php b/wporg-gp-translation-events.php index 77bd5cfb..e086d8ab 100644 --- a/wporg-gp-translation-events.php +++ b/wporg-gp-translation-events.php @@ -140,7 +140,7 @@ function validate_event_dates( string $event_start, string $event_end ): bool { function submit_event_ajax() { $event_id = null; $response_message = ''; - $form_actions = array( 'draft', 'publish' ); + $form_actions = array( 'draft', 'publish', 'delete' ); $is_nonce_valid = false; $nonce_name = '_event_nonce'; @@ -179,7 +179,7 @@ function submit_event_ajax() { wp_send_json_error( 'Form name must be set' ); } $action = sanitize_text_field( wp_unslash( $_POST['form_name'] ) ); - if ( ! in_array( $action, array( 'create_event', 'edit_event' ), true ) ) { + if ( ! in_array( $action, array( 'create_event', 'edit_event', 'delete_event' ), true ) ) { wp_send_json_error( 'Invalid form name' ); } @@ -213,18 +213,40 @@ function submit_event_ajax() { ); $response_message = 'Event updated successfully!'; } + if ( 'delete_event' === $action ) { + $event_id = sanitize_text_field( wp_unslash( $_POST['event_id'] ) ); + $event = get_post( $event_id ); + if ( ! $event || 'event' !== $event->post_type ) { + wp_send_json_error( 'Event does not exist' ); + } + if ( ! ( current_user_can( 'delete_post', $event->ID ) || get_current_user_id() === $event->post_author ) ) { + wp_send_json_error( 'You do not have permission to delete this event' ); + } + $stats_calculator = new WPORG_GP_Translation_Events_Stats_Calculator(); + try { + $event_stats = $stats_calculator->for_event( $event ); + } catch ( Exception $e ) { + wp_send_json_error( 'Failed to calculate event stats' ); + } + if ( ! empty( $event_stats->rows() ) ) { + wp_send_json_error( 'Event has translations and cannot be deleted' ); + } + wp_trash_post( $event_id ); + $response_message = 'Event deleted successfully!'; + } if ( ! $event_id ) { wp_send_json_error( 'Event could not be created or updated' ); } - try { - update_post_meta( $event_id, '_event_start', convert_to_utc( $event_start, $event_timezone ) ); - update_post_meta( $event_id, '_event_end', convert_to_utc( $event_end, $event_timezone ) ); - } catch ( Exception $e ) { - wp_send_json_error( 'Invalid start or end' ); - } - - update_post_meta( $event_id, '_event_timezone', $event_timezone ); + if ( 'delete_event' !== $_POST['form_name'] ) { + try { + update_post_meta( $event_id, '_event_start', convert_to_utc( $event_start, $event_timezone ) ); + update_post_meta( $event_id, '_event_end', convert_to_utc( $event_end, $event_timezone ) ); + } catch ( Exception $e ) { + wp_send_json_error( 'Invalid start or end' ); + } + update_post_meta( $event_id, '_event_timezone', $event_timezone ); + } try { WPORG_GP_Translation_Events_Active_Events_Cache::invalidate(); } catch ( Exception $e ) { @@ -234,14 +256,14 @@ function submit_event_ajax() { list( $permalink, $post_name ) = get_sample_permalink( $event_id ); $permalink = str_replace( '%pagename%', $post_name, $permalink ); - wp_send_json_success( array( - 'message' => $response_message, - 'eventId' => $event_id, - 'eventUrl' => str_replace( '%pagename%', $post_name, $permalink ), - 'eventStatus' => $event_status, - 'eventEditUrl' => esc_url( gp_url( '/events/edit/' . $event_id ) ), + 'message' => $response_message, + 'eventId' => $event_id, + 'eventUrl' => str_replace( '%pagename%', $post_name, $permalink ), + 'eventStatus' => $event_status, + 'eventEditUrl' => esc_url( gp_url( '/events/edit/' . $event_id ) ), + 'eventDeleteUrl' => esc_url( gp_url( '/events/my-events/' ) ), ) ); }