-
Notifications
You must be signed in to change notification settings - Fork 327
Enhancement/11433-pue-pointer #11673
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
Changes from all commits
0af1815
487f5a4
1b761b3
fd0f924
5f023e3
8e4c3d3
c0a6af6
5eba5ab
ff78207
47ebace
fce94da
d0adeb9
48c154f
bc41306
94cd93a
47e7457
9345c13
b34109c
841032a
90e884c
358156f
e7b5dea
a2b9b12
ba7e407
a3feaed
520c432
3938ab7
6da1d4f
53eac8d
a6a3b26
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| /** | ||
| * Open Email Reporting Selection Panel hook. | ||
| * | ||
| * Site Kit by Google, Copyright 2025 Google LLC | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| /** | ||
| * External dependencies | ||
| */ | ||
| import { useMount } from 'react-use'; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is an external dependency, not WP. |
||
|
|
||
| /** | ||
| * Internal dependencies | ||
| */ | ||
| import { useDispatch } from 'googlesitekit-data'; | ||
| import useQueryArg from '@/js/hooks/useQueryArg'; | ||
| import { CORE_UI } from '@/js/googlesitekit/datastore/ui/constants'; | ||
| import { USER_SETTINGS_SELECTION_PANEL_OPENED_KEY } from '@/js/components/email-reporting/constants'; | ||
|
|
||
| export default function useOpenEmailReportingSelectionPanelEffect() { | ||
| const [ emailReportingPanelOpen, setEmailReportingPanelOpen ] = useQueryArg( | ||
| 'email-reporting-panel' | ||
| ); | ||
| const { setValue: setUIValue } = useDispatch( CORE_UI ); | ||
|
|
||
| useMount( () => { | ||
| // If redirected from a pointer CTA or following link from email footer, open the Email Reporting selection panel. | ||
| if ( emailReportingPanelOpen !== undefined ) { | ||
| setUIValue( USER_SETTINGS_SELECTION_PANEL_OPENED_KEY, true ); | ||
| setEmailReportingPanelOpen( undefined ); | ||
| } | ||
| } ); | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,58 @@ | ||
| /** | ||
| * Pointers styles for WP Dashboard | ||
| * | ||
| * Site Kit by Google, Copyright 2025 Google LLC | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * https://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
|
|
||
| .googlesitekit-pointer-cta--dismiss { | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't quite look like the design. This is what I see
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In the designs the X icon takes the color from the Pointer header, however, to maintain compatibility with the WP theme the pointer header will take the primary color of the theme. Therefore I went with black for this icon to work across all possible customised theme colors.
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's iterate on this in a follow up as we should be able to match it even with custom admin themes. |
||
| align-items: center; | ||
| background-color: $c-white; | ||
| border: none; | ||
| border-radius: 50%; | ||
| display: flex; | ||
| justify-content: center; | ||
| position: absolute; | ||
| right: 10px; | ||
| top: 12px; | ||
|
|
||
| &:hover { | ||
| cursor: pointer; | ||
| } | ||
| } | ||
|
|
||
| .googlesitekit-pointer-buttons { | ||
| margin-top: 55px; | ||
| padding-bottom: 0; | ||
| padding-left: 20px; | ||
| padding-right: 20px; | ||
| } | ||
|
|
||
| .googlesitekit-email-pointer { | ||
| .wp-pointer-content h3::before { | ||
| content: "\f466"; // Email icon | ||
| font-family: dashicons, sans-serif; | ||
| margin-right: 8px; | ||
| } | ||
|
|
||
| .wp-pointer-content h4 { | ||
| line-height: 24px; | ||
| margin-bottom: 0; | ||
| margin-top: 16px; | ||
| } | ||
|
|
||
| .wp-pointer-content p { | ||
| margin-top: 0; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -62,6 +62,8 @@ function ( Pointer $pointer ) use ( $hook_suffix ) { | |
| } | ||
|
|
||
| wp_enqueue_style( 'wp-pointer' ); | ||
| // Dashboard styles are required where pointers are used to ensure proper styling. | ||
| wp_enqueue_style( 'googlesitekit-wp-dashboard-css' ); | ||
| wp_enqueue_script( 'wp-pointer' ); | ||
|
|
||
| add_action( | ||
|
|
@@ -103,6 +105,7 @@ function ( $pointer ) { | |
| * Prints script for a given pointer. | ||
| * | ||
| * @since 1.83.0 | ||
| * @since n.e.x.t Updated to support buttons and header dismiss icon. | ||
| * | ||
| * @param Pointer $pointer Pointer to print. | ||
| */ | ||
|
|
@@ -112,38 +115,82 @@ private function print_pointer_script( $pointer ) { | |
| return; | ||
| } | ||
|
|
||
| $slug = $pointer->get_slug(); | ||
| $buttons = $pointer->get_buttons(); | ||
| if ( $buttons ) { | ||
| // Content including buttons escaped below in the inline script with wp_kses. | ||
| $content .= '<div class="googlesitekit-pointer-buttons">' . $buttons . '</div>'; | ||
| } | ||
|
|
||
| BC_Functions::wp_print_inline_script_tag( | ||
| sprintf( | ||
| ' | ||
| jQuery( function() { | ||
| var options = { | ||
| content: "<h3>%s</h3>%s", | ||
| position: %s, | ||
| pointerWidth: 420, | ||
| close: function() { | ||
| jQuery.post( | ||
| window.ajaxurl, | ||
| { | ||
| pointer: "%s", | ||
| action: "dismiss-wp-pointer", | ||
| } | ||
| ); | ||
| } | ||
| }; | ||
|
|
||
| jQuery( "#%s" ).pointer( options ).pointer( "open" ); | ||
| } ); | ||
| ', | ||
| esc_js( $pointer->get_title() ), | ||
| $content, | ||
| wp_json_encode( $pointer->get_position() ), | ||
| esc_js( $slug ), | ||
| esc_js( $pointer->get_target_id() ) | ||
| $class = array( 'wp-pointer' ); | ||
| if ( $pointer->get_class() ) { | ||
| $class[] = $pointer->get_class(); | ||
| } | ||
|
|
||
| $kses_title = array( | ||
| 'span' => array( 'class' => array() ), | ||
| 'button' => array( | ||
| 'class' => array(), | ||
| 'type' => array(), | ||
| 'data-action' => array(), | ||
| ), | ||
| ); | ||
|
|
||
| $kses_content = array( | ||
| 'a' => array( | ||
| 'href' => array(), | ||
| 'class' => array(), | ||
| 'target' => array(), | ||
| 'rel' => array(), | ||
| 'data-action' => array(), | ||
| ), | ||
| 'h4' => array(), | ||
| 'p' => array( 'class' => array() ), | ||
| 'br' => array(), | ||
| 'strong' => array(), | ||
| 'em' => array(), | ||
| 'button' => array( | ||
| 'class' => array(), | ||
| 'type' => array(), | ||
| 'data-action' => array(), | ||
| ), | ||
| 'div' => array( 'class' => array() ), | ||
| ); | ||
|
|
||
| BC_Functions::wp_print_inline_script_tag( | ||
| <<<'JS' | ||
| ( | ||
| function ( $, wp, config ) { | ||
| function initPointer() { | ||
| const options = { | ||
| content: '<h3>' + config.title + '</h3>' + config.content, | ||
| position: JSON.parse( config.position ), | ||
| pointerWidth: 420, | ||
| pointerClass: config.class, | ||
| close: function() { | ||
| wp.ajax.post( 'dismiss-wp-pointer', { pointer: config.slug } ); | ||
| }, | ||
| buttons: function( event, container ) { | ||
| container.pointer.on( 'click', '[data-action="dismiss"]', function() { | ||
| container.element.pointer( 'close' ); | ||
| } ); | ||
| } | ||
| }; | ||
|
|
||
| $( '#' + config.targetId ).pointer( options ).pointer( 'open' ); | ||
| } | ||
|
|
||
| $( initPointer ); | ||
| } | ||
| )( window.jQuery, window.wp, { ...document.currentScript.dataset } ); | ||
| JS | ||
| , | ||
| array( | ||
| 'id' => $slug, | ||
| 'data-slug' => $pointer->get_slug(), | ||
| 'data-class' => implode( ' ', $class ), | ||
| 'data-target-id' => $pointer->get_target_id(), | ||
| 'data-title' => wp_kses( $pointer->get_title(), $kses_title ), | ||
| 'data-content' => wp_kses( $content, $kses_content ), | ||
| 'data-position' => wp_json_encode( $pointer->get_position() ), | ||
|
Comment on lines
+188
to
+193
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These will all be escaped as attributes automatically so no escaping is needed here, but the values should still be sanitized/cleaned with |
||
| ) | ||
| ); | ||
| } | ||
|
|
||

There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One important difference here with the Module version is that modules can register two different effect components – one for the main and entity dashboards respectively. Core doesn't need to register its effects so its components are simpler, but it would make sense to follow the same pattern where this top level component renders the dashboard-specific variant based on the context.
If this is getting out of scope we could address it in a follow up too, I just wanted to highlight this detail for maintaining consistency.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've continued with a single component for now across main and entity dashboards and created #11712 to split this out in future.