diff --git a/includes/core/utilities/class-date-time-helpers.php b/includes/core/utilities/class-date-time-helpers.php index 44db5b6..d11182f 100644 --- a/includes/core/utilities/class-date-time-helpers.php +++ b/includes/core/utilities/class-date-time-helpers.php @@ -47,9 +47,9 @@ public static function get_formatted_relative_date_time( $date = null ) { /* translators: 1: Date, 2: Time. */ esc_html_x( '%1$s at %2$s', 'date at time', 'visual-regression-tests' ), /* translators: Date format. See https://www.php.net/manual/datetime.format.php */ - date_format( $date, esc_html_x( 'Y/m/d', 'date format', 'visual-regression-tests' ) ), + static::extract_date( $date ), /* translators: Time format. See https://www.php.net/manual/datetime.format.php */ - date_format( $date, esc_html_x( 'g:i a', 'time format', 'visual-regression-tests' ) ) + static::extract_time( $date ) ); return '' . $formatted_date . ''; } @@ -67,4 +67,31 @@ private static function date_from_gmt( $date ) { return $date; } + + private static function extract_date($inputDate) { + // Get today's date at midnight + $today = new DateTime('today'); + + // Clone input date and set time to midnight + $comparisonDate = clone $inputDate; + $comparisonDate->setTime(0, 0, 0); + + // Calculate the difference in days + $differenceInSeconds = $comparisonDate->getTimestamp() - $today->getTimestamp(); + $differenceInDays = (int) round($differenceInSeconds / (60 * 60 * 24)); + + // Determine if the date is today, tomorrow, or yesterday + if ($differenceInDays === 0) { + return __('Today', 'visual-regression-testing'); + } elseif ($differenceInDays === 1) { + return __('Tomorrow', 'visual-regression-testing'); + } elseif ($differenceInDays === -1) { + return __('Yesterday', 'visual-regression-testing'); + } + return $inputDate->format('D, Y/m/d'); + } + + private static function extract_time($inputDate) { + return $inputDate->setTimezone(wp_timezone())->format('g:i a'); + } } diff --git a/includes/features/class-admin.php b/includes/features/class-admin.php index 69cb7aa..f96eab5 100644 --- a/includes/features/class-admin.php +++ b/includes/features/class-admin.php @@ -18,7 +18,7 @@ public function __construct() { * Add main menu where other sub menus can be added to. */ public function add_main_menu() { - $count = Alert::get_total_items(); + $count = Alert::get_total_items_grouped_by_test_run(); add_menu_page( 'VRTs', diff --git a/includes/features/class-test-runs-page.php b/includes/features/class-test-runs-page.php index ac06949..fb4f2d8 100644 --- a/includes/features/class-test-runs-page.php +++ b/includes/features/class-test-runs-page.php @@ -21,10 +21,12 @@ public function __construct() { * Add submenu. */ public function add_submenu_page() { + $count = Alert::get_total_items_grouped_by_test_run(); + $submenu_page = add_submenu_page( 'vrts', __( 'Runs', 'visual-regression-tests' ), - __( 'Runs', 'visual-regression-tests' ), + $count ? esc_html__( 'Runs', 'visual-regression-tests' ) . ' ' . esc_html( $count ) . '' : esc_html__( 'Runs', 'visual-regression-tests' ), 'manage_options', 'vrts-runs', [ $this, 'render_page' ], diff --git a/includes/list-tables/class-test-runs-list-table.php b/includes/list-tables/class-test-runs-list-table.php index 6de0202..9f14464 100644 --- a/includes/list-tables/class-test-runs-list-table.php +++ b/includes/list-tables/class-test-runs-list-table.php @@ -81,8 +81,7 @@ public function get_columns() { */ public function get_sortable_columns() { $sortable_columns = [ - 'title' => [ 'title', true ], - 'status' => false, + 'title' => [ 'finished_at', true ], 'trigger' => [ 'trigger', true ], ]; @@ -147,7 +146,7 @@ public function prepare_items() { $order = isset( $_REQUEST['order'] ) && 'asc' === $_REQUEST['order'] ? 'ASC' : 'DESC'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- It's the list order by parameter. - $order_by = isset( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'id'; + $order_by = isset( $_REQUEST['orderby'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) ) : 'finished_at'; // phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing -- It's the list search query parameter. $filter_status_query = isset( $_REQUEST['status'] ) && '' !== $_REQUEST['status'] ? sanitize_text_field( wp_unslash( $_REQUEST['status'] ) ) : null; diff --git a/includes/list-tables/class-test-runs-queue-list-table.php b/includes/list-tables/class-test-runs-queue-list-table.php index 2139a5f..90ee9d0 100644 --- a/includes/list-tables/class-test-runs-queue-list-table.php +++ b/includes/list-tables/class-test-runs-queue-list-table.php @@ -243,7 +243,7 @@ public function column_status( $item ) { ); } else { $class = 'waiting'; - $text = esc_html__( 'Scheduled', 'visual-regression-tests' ); + $text = esc_html__( 'Pending', 'visual-regression-tests' ); $instructions = sprintf( '%2$s | %4$s', // translators: %s: number of tests. diff --git a/includes/models/class-alert.php b/includes/models/class-alert.php index 6c0cc17..fe98139 100644 --- a/includes/models/class-alert.php +++ b/includes/models/class-alert.php @@ -291,6 +291,59 @@ public static function get_total_items( $filter_status_query = null, $test_run_i return (int) $wpdb->get_var( $query ); } + /** + * Get total test items from database + * + * @param int $filter_status_query the id of status. + * @param int $test_run_id the id of the test run. + * + * @return array + */ + public static function get_total_items_grouped_by_test_run( $filter_status_query = null ) { + global $wpdb; + + $alerts_table = Alerts_Table::get_table_name(); + + // 0 = Open + // 1 = Archived. + // 2 = False Positive. + switch ( $filter_status_query ?? null ) { + case 'archived': + $alert_states = [ 1, 2 ]; + break; + case 'all': + $alert_states = []; + break; + default: + $alert_states = [ 0 ]; + break; + } + if ( ! empty( $alert_states ) ) { + $alert_states_placeholders = implode( ', ', array_fill( 0, count( $alert_states ), '%d' ) ); + + $status_where = $wpdb->prepare( + // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare -- It's ok. + "WHERE alert_state IN ($alert_states_placeholders)", + $alert_states + ); + } else { + $status_where = 'WHERE 1=1'; + } + + $where = "{$status_where} AND test_run_id IS NOT NULL"; + + + $query = " + SELECT COUNT(DISTINCT test_run_id) FROM $alerts_table + $where + "; + + // var_dump($query);die(); + + // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared -- It's prepared above + return (int) $wpdb->get_var( $query ); + } + /** * Update alert status. diff --git a/includes/models/class-test-run.php b/includes/models/class-test-run.php index f26fe36..8743f8c 100644 --- a/includes/models/class-test-run.php +++ b/includes/models/class-test-run.php @@ -46,7 +46,7 @@ public static function get_items( $args = [], $return_count = false ) { } } - $whitelist_orderby = [ 'id', 'title' ]; + $whitelist_orderby = [ 'id', 'title', 'started_at', 'finished_at', 'trigger' ]; $whitelist_order = [ 'ASC', 'DESC' ]; $orderby = in_array( $args['orderby'], $whitelist_orderby, true ) ? $args['orderby'] : 'id'; @@ -55,7 +55,7 @@ public static function get_items( $args = [], $return_count = false ) { if ( 'status' === $orderby ) { $orderby = "ORDER BY calculated_status $order, calculated_date $order"; } else { - $orderby = "ORDER BY $orderby $order"; + $orderby = "ORDER BY `$orderby` $order"; } $limit = $args['number'] > 100 ? 100 : $args['number']; @@ -307,9 +307,9 @@ public static function get_trigger_title( $test_run ) { $trigger_titles = [ 'manual' => __( 'Manual', 'visual-regression-tests' ), - 'scheduled' => __( 'Scheduled', 'visual-regression-tests' ), + 'scheduled' => __( 'Schedule', 'visual-regression-tests' ), 'api' => __( 'API', 'visual-regression-tests' ), - 'update' => __( 'WordPress', 'visual-regression-tests' ), + 'update' => __( 'Update', 'visual-regression-tests' ), ]; return $trigger_titles[ $test_run->trigger ] ?? __( 'Unknown', 'visual-regression-tests' ); @@ -469,7 +469,7 @@ public static function get_status_data( $test_run ) { break; case 'scheduled': $class = 'waiting'; - $text = esc_html__( 'Scheduled', 'visual-regression-tests' ); + $text = esc_html__( 'Pending', 'visual-regression-tests' ); $instructions .= sprintf( '%2$s', esc_url( admin_url( 'admin.php?page=vrts-settings' ) ),