Skip to content

Allow reordering widgets (drag & drop) #236

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions assets/css/admin.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

Expand All @@ -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);
}
}
}

/*------------------------------------*\
Expand Down
55 changes: 55 additions & 0 deletions assets/js/draggable.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/* 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.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;
} );
} )();
58 changes: 56 additions & 2 deletions classes/admin/class-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@
\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' ] );
\add_action( 'in_admin_header', [ $this, 'remove_admin_notices' ], PHP_INT_MAX );
}

Expand All @@ -37,7 +39,7 @@
* @return array<\Progress_Planner\Widgets\Widget>
*/
public function get_widgets() {
$widgets = [
return [
\progress_planner()->get_widgets__activity_scores(),
\progress_planner()->get_widgets__suggested_tasks(),
\progress_planner()->get_widgets__todo(),
Expand All @@ -47,15 +49,47 @@
\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() {

Check failure on line 59 in classes/admin/class-page.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Progress_Planner\Admin\Page::get_widgets_filtered() has invalid return type Progress_Planner\Widget.
/**
* Filter the widgets.
*
* @param array<\Progress_Planner\Widgets\Widget> $widgets The widgets.
*
* @return array<\Progress_Planner\Widgets\Widget>
*/
return \apply_filters( 'progress_planner_admin_widgets', $widgets );
return \apply_filters( 'progress_planner_admin_widgets', $this->get_widgets() );

Check failure on line 67 in classes/admin/class-page.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Progress_Planner\Admin\Page::get_widgets_filtered() should return array<Progress_Planner\Widget> but returns array<Progress_Planner\Widgets\Widget>.
}

/**
* Filter the widgets.
*
* @param \Progress_Planner\Widget[] $widgets The widgets.
*
* @return \Progress_Planner\Widget[]
*/
public function filter_active_widgets( $widgets ) {

Check failure on line 77 in classes/admin/class-page.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Progress_Planner\Admin\Page::filter_active_widgets() has invalid return type Progress_Planner\Widget.

Check failure on line 77 in classes/admin/class-page.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Parameter $widgets of method Progress_Planner\Admin\Page::filter_active_widgets() has invalid type Progress_Planner\Widget.
$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;

Check failure on line 92 in classes/admin/class-page.php

View workflow job for this annotation

GitHub Actions / Static Analysis

Method Progress_Planner\Admin\Page::filter_active_widgets() should return array<Progress_Planner\Widget> but returns list<Progress_Planner\Widgets\Widget>.
}

/**
Expand Down Expand Up @@ -138,6 +172,7 @@
\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' );
}
Expand Down Expand Up @@ -236,4 +271,23 @@

\remove_all_actions( 'admin_notices' );
}

/**
* 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' ),
]
);
}
}
12 changes: 12 additions & 0 deletions classes/admin/class-scripts.php
Original file line number Diff line number Diff line change
Expand Up @@ -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 [];
}
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 5 additions & 1 deletion classes/widgets/class-widget.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,11 @@ public function render() {
$this->enqueue_styles();
$this->enqueue_scripts();
?>
<div class="prpl-widget-wrapper prpl-<?php echo \esc_attr( $this->id ); ?>">
<div
class="prpl-widget-wrapper prpl-<?php echo \esc_attr( $this->id ); ?>"
data-id="<?php echo \esc_attr( $this->id ); ?>"
draggable="false"
>
<div class="widget-inner-container">
<?php \progress_planner()->the_view( "page-widgets/{$this->id}.php" ); ?>
</div>
Expand Down
4 changes: 4 additions & 0 deletions views/admin-page-header.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
<?php \progress_planner()->the_asset( 'images/icon_tour.svg' ); ?>
<span class="screen-reader-text"><?php \esc_html_e( 'Start tour', 'progress-planner' ); ?>
</button>
<button class="prpl-info-icon prpl-draggable-icon" id="prpl-draggable-icon-button" title="<?php \esc_html_e( 'Reorder widgets', 'progress-planner' ); ?>">
<span class="screen-reader-text"><?php \esc_html_e( 'Reorder widgets', 'progress-planner' ); ?>
</button>
<?php
// Render the settings button.
\progress_planner()->get_popover()->the_popover( 'settings' )->render_button(
Expand Down
2 changes: 1 addition & 1 deletion views/admin-page.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<h1 class="screen-reader-text"><?php \esc_html_e( 'Progress Planner', 'progress-planner' ); ?></h1>
<?php \progress_planner()->the_view( 'admin-page-header.php' ); ?>
<div class="prpl-widgets-container">
<?php foreach ( \progress_planner()->get_admin__page()->get_widgets() as $prpl_admin_widget ) : ?>
<?php foreach ( \progress_planner()->get_admin__page()->get_widgets_filtered() as $prpl_admin_widget ) : ?>
<?php $prpl_admin_widget->render(); ?>
<?php endforeach; ?>
</div>
Expand Down
Loading