From 6d791c949a4e2475711dfe1e20cee3c7ee087f5d Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Tue, 4 Feb 2025 10:27:59 +0200 Subject: [PATCH 1/2] Allow reordering widgets --- assets/js/draggable.js | 47 ++++++++++++++++++++++++++ classes/admin/class-page.php | 58 +++++++++++++++++++++++++++++++-- classes/admin/class-scripts.php | 12 +++++++ classes/class-widget.php | 6 +++- views/admin-page.php | 2 +- 5 files changed, 121 insertions(+), 4 deletions(-) create mode 100644 assets/js/draggable.js diff --git a/assets/js/draggable.js b/assets/js/draggable.js new file mode 100644 index 000000000..2f8ba29ee --- /dev/null +++ b/assets/js/draggable.js @@ -0,0 +1,47 @@ +/* global progressPlannerDraggable */ + +const prplHandleDrag = ( event ) => { + const selectedItem = event.target; + let swapItem = + document.elementFromPoint( event.clientX, event.clientY ) === null + ? selectedItem + : document.elementFromPoint( event.clientX, event.clientY ); + + if ( selectedItem.parentNode === swapItem.parentNode ) { + swapItem = + swapItem !== selectedItem.nextSibling + ? swapItem + : swapItem.nextSibling; + selectedItem.parentNode.insertBefore( selectedItem, swapItem ); + } +}; + +const prplHandleDrop = () => { + const widgetIds = []; + document + .querySelector( '.prpl-widgets-container' ) + .querySelectorAll( '.prpl-widget-wrapper' ) + .forEach( ( child ) => { + if ( child.dataset.id ) { + widgetIds.push( child.dataset.id ); + } + } ); + + const dispatchGridEvent = new Event( 'prplResizeAllGridItemsEvent' ); + document.dispatchEvent( dispatchGridEvent ); + + const request = wp.ajax.post( 'progress_planner_save_widgets_order', { + _ajax_nonce: progressPlannerDraggable.nonce, + widgets: widgetIds.join( ',' ), + } ); + request.done( ( response ) => { + console.log( response.message ); // eslint-disable-line no-console + } ); +}; + +( () => { + document.querySelectorAll( '.prpl-widget-wrapper' ).forEach( ( item ) => { + item.ondrag = prplHandleDrag; + item.ondragend = prplHandleDrop; + } ); +} )(); diff --git a/classes/admin/class-page.php b/classes/admin/class-page.php index 614d5c50b..476a86500 100644 --- a/classes/admin/class-page.php +++ b/classes/admin/class-page.php @@ -28,6 +28,8 @@ private function register_hooks() { \add_action( 'admin_menu', [ $this, 'add_page' ] ); \add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] ); \add_action( 'wp_ajax_progress_planner_save_cpt_settings', [ $this, 'save_cpt_settings' ] ); + \add_action( 'wp_ajax_progress_planner_save_widgets_order', [ $this, 'save_widgets_order' ] ); + \add_filter( 'progress_planner_admin_widgets', [ $this, 'filter_active_widgets' ] ); } /** @@ -36,7 +38,7 @@ private function register_hooks() { * @return array<\Progress_Planner\Widget> */ public function get_widgets() { - $widgets = [ + return [ \progress_planner()->get_widgets__activity_scores(), \progress_planner()->get_widgets__suggested_tasks(), \progress_planner()->get_widgets__todo(), @@ -46,7 +48,14 @@ public function get_widgets() { \progress_planner()->get_widgets__published_content(), \progress_planner()->get_widgets__whats_new(), ]; + } + /** + * Get the widgets objects, filtered and sorted. + * + * @return array<\Progress_Planner\Widget> + */ + public function get_widgets_filtered() { /** * Filter the widgets. * @@ -54,7 +63,32 @@ public function get_widgets() { * * @return array<\Progress_Planner\Widget> */ - return \apply_filters( 'progress_planner_admin_widgets', $widgets ); + return \apply_filters( 'progress_planner_admin_widgets', $this->get_widgets() ); + } + + /** + * Filter the widgets. + * + * @param \Progress_Planner\Widget[] $widgets The widgets. + * + * @return \Progress_Planner\Widget[] + */ + public function filter_active_widgets( $widgets ) { + $active_widgets = \progress_planner()->get_settings()->get( 'active_widgets' ); + if ( empty( $active_widgets ) ) { + return $widgets; + } + + $filtered_widgets = []; + + foreach ( $active_widgets as $widget_id ) { + $widget = $this->get_widget( $widget_id ); + if ( $widget ) { + $filtered_widgets[] = $widget; + } + } + + return $filtered_widgets; } /** @@ -137,6 +171,7 @@ public function enqueue_scripts() { \wp_enqueue_script( 'progress-planner-header-filters' ); \wp_enqueue_script( 'progress-planner-settings' ); \wp_enqueue_script( 'progress-planner-grid-masonry' ); + \wp_enqueue_script( 'progress-planner-draggable' ); } else { \wp_enqueue_script( 'progress-planner-onboard' ); } @@ -211,4 +246,23 @@ public function save_cpt_settings() { ] ); } + + /** + * Save the widgets order. + * + * @return void + */ + public function save_widgets_order() { + \check_ajax_referer( 'progress_planner', 'nonce', false ); + $widgets = isset( $_POST['widgets'] ) ? \sanitize_text_field( \wp_unslash( $_POST['widgets'] ) ) : ''; + $widgets = \explode( ',', $widgets ); + + \progress_planner()->get_settings()->set( 'active_widgets', $widgets ); + + \wp_send_json_success( + [ + 'message' => \esc_html__( 'Widgets order saved.', 'progress-planner' ), + ] + ); + } } diff --git a/classes/admin/class-scripts.php b/classes/admin/class-scripts.php index 133fc6e1a..3395b621f 100644 --- a/classes/admin/class-scripts.php +++ b/classes/admin/class-scripts.php @@ -83,6 +83,9 @@ public function get_dependencies( $file ) { case 'settings-page': return [ 'wp-util', 'progress-planner-document-ready' ]; + case 'draggable': + return [ 'progress-planner-ajax-request' ]; + default: return []; } @@ -209,6 +212,15 @@ public function localize_script( $handle ) { ); break; + case 'progress-planner-draggable': + \wp_localize_script( + $handle, + 'progressPlannerDraggable', + [ + 'nonce' => \wp_create_nonce( 'progress_planner' ), + ] + ); + break; default: return; } diff --git a/classes/class-widget.php b/classes/class-widget.php index 951980fdf..2326a6d89 100644 --- a/classes/class-widget.php +++ b/classes/class-widget.php @@ -72,7 +72,11 @@ public function render() { $this->enqueue_styles(); $this->enqueue_scripts(); ?> -
+
the_view( "page-widgets/{$this->id}.php" ); ?>
diff --git a/views/admin-page.php b/views/admin-page.php index f379af8fd..8ff437917 100644 --- a/views/admin-page.php +++ b/views/admin-page.php @@ -23,7 +23,7 @@

the_view( 'admin-page-header.php' ); ?>
- get_admin__page()->get_widgets() as $prpl_admin_widget ) : ?> + get_admin__page()->get_widgets_filtered() as $prpl_admin_widget ) : ?> render(); ?>
From 87a696bc1af64eacd4a5341e18458d7443ee74b4 Mon Sep 17 00:00:00 2001 From: Ari Stathopoulos Date: Fri, 7 Feb 2025 10:02:38 +0200 Subject: [PATCH 2/2] Add a button in the header to allow reordering --- assets/css/admin.css | 12 ++++++++++++ assets/js/draggable.js | 8 ++++++++ classes/widgets/class-widget.php | 2 +- views/admin-page-header.php | 4 ++++ 4 files changed, 25 insertions(+), 1 deletion(-) diff --git a/assets/css/admin.css b/assets/css/admin.css index ee7404133..bcf75edfd 100644 --- a/assets/css/admin.css +++ b/assets/css/admin.css @@ -202,6 +202,11 @@ button.prpl-info-icon { border-color: var(--prpl-color-link); background-color: var(--prpl-background-blue); } + + &.active { + background-color: var(--prpl-color-link); + color: #fff; + } } } @@ -223,6 +228,13 @@ button.prpl-info-icon { font-size: 1.15rem; margin-top: 0; } + + &.prpl-draggable { + .prpl-widget-wrapper { + cursor: move; + outline: 2px dashed var(--prpl-color-gray-4); + } + } } /*------------------------------------*\ diff --git a/assets/js/draggable.js b/assets/js/draggable.js index 2f8ba29ee..ffbfdad26 100644 --- a/assets/js/draggable.js +++ b/assets/js/draggable.js @@ -40,6 +40,14 @@ const prplHandleDrop = () => { }; ( () => { + document.querySelector( '.prpl-info-icon.prpl-draggable-icon' ).addEventListener( 'click', ( event ) => { + event.preventDefault(); + event.target.classList.toggle( 'active' ); + document.querySelector( '.prpl-widgets-container' ).classList.toggle( 'prpl-draggable' ); + document.querySelectorAll( '.prpl-widget-wrapper' ).forEach( ( item ) => { + item.draggable = ! item.draggable; + } ); + } ); document.querySelectorAll( '.prpl-widget-wrapper' ).forEach( ( item ) => { item.ondrag = prplHandleDrag; item.ondragend = prplHandleDrop; diff --git a/classes/widgets/class-widget.php b/classes/widgets/class-widget.php index 8997369fa..4dd97d416 100644 --- a/classes/widgets/class-widget.php +++ b/classes/widgets/class-widget.php @@ -75,7 +75,7 @@ public function render() {
the_view( "page-widgets/{$this->id}.php" ); ?> diff --git a/views/admin-page-header.php b/views/admin-page-header.php index 493fc10b0..161b5f6f8 100644 --- a/views/admin-page-header.php +++ b/views/admin-page-header.php @@ -33,6 +33,10 @@ the_asset( 'images/icon_tour.svg' ); ?> + get_popover()->the_popover( 'settings' )->render_button(