Skip to content
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
15 changes: 15 additions & 0 deletions packages/playground/personal-wp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,21 @@ Response:
Blueprint URLs must be `https:`, `data:`, or local `http:` URLs. Dependent tabs
cannot install blueprints and will return an error result.

#### Open Site Tools

Use `personal-wp-open-site-tools` to ask Personal Playground to open the Site
Tools panel.

```js
window.parent.postMessage(
{
type: 'relay',
relayType: 'personal-wp-open-site-tools',
},
'*'
);
```

### Offline Support

Works as a Progressive Web App (PWA) for offline use. Install it on your device for a native app-like experience.
Expand Down
24 changes: 21 additions & 3 deletions packages/playground/personal-wp/playwright/e2e/smoke.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,32 @@ test('should apply a blueprint passed via URL hash', async ({ website }) => {
await expect(website.page).toHaveURL(/sample-page/);
});

test('should display the seamless viewport and Site Tools latch', async ({
test('should display the wp-admin Site Tools admin bar item', async ({
website,
wordpress,
}) => {
await website.goto('./');
await website.goto('./wp-admin/');
await expect(
website.page.locator('.playground-viewport:visible')
).toBeVisible();
await expect(
website.page.getByRole('button', { name: /Open Site Tools/ })
website.page.getByRole('button', { name: 'Open Site Tools' })
).toBeHidden();
await expect(
wordpress.getByRole('link', { name: 'Open Site Tools' })
).toBeVisible();
});

test('should open Site Tools from the wp-admin admin bar item', async ({
website,
wordpress,
}) => {
await website.goto('./wp-admin/');
await website.ensureSiteToolsIsClosed();

await wordpress.getByRole('link', { name: 'Open Site Tools' }).click();

await expect(
website.page.getByRole('button', { name: 'Close Site Tools' })
).toBeVisible();
});
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ function SeamlessViewport({ siteSlug }: { siteSlug: string }) {
clientInfo?.mainTabStatus ??
(isDependentMode ? 'missing' : 'connected');
const hasLocalRuntimeClient = !isDependentMode && !!playground;
const showViewportLatch = !siteManagerIsOpen && !isWpAdminUrl(url);

const [installingBlueprint, setInstallingBlueprint] = useState<
string | null
Expand Down Expand Up @@ -230,6 +231,11 @@ function SeamlessViewport({ siteSlug }: { siteSlug: string }) {
);
if (installBlueprintMessage) {
void installBlueprintFromRelay(event, installBlueprintMessage);
return;
}

if (isOpenSiteToolsMessage(relayValidation.data)) {
dispatch(setSiteManagerOpen(true));
}
}
window.addEventListener('message', handleMessage);
Expand All @@ -239,6 +245,7 @@ function SeamlessViewport({ siteSlug }: { siteSlug: string }) {
}, [
applyBlueprint,
applyBlueprintInMainTab,
dispatch,
hasLocalRuntimeClient,
isDependentMode,
siteSlug,
Expand Down Expand Up @@ -331,7 +338,7 @@ function SeamlessViewport({ siteSlug }: { siteSlug: string }) {

<div
className={classNames(css.sidebarLatch, {
[css.sidebarLatchHidden]: siteManagerIsOpen,
[css.sidebarLatchHidden]: !showViewportLatch,
})}
>
<Button
Expand Down Expand Up @@ -415,6 +422,10 @@ function confirmBlueprintInstall(blueprintUrl: string): boolean {
);
}

function isWpAdminUrl(url: string | undefined): boolean {
return !!url && /^\/?wp-admin(\/|$|\?)/.test(url);
}

type RelayMessageData = {
type: 'relay';
relayType?: unknown;
Expand All @@ -429,6 +440,11 @@ type InstallBlueprintMessageData = {
requestId?: string;
};

type OpenSiteToolsMessageData = {
type: 'relay';
relayType: 'personal-wp-open-site-tools';
};

type ApplyBlueprintOptions = {
allowNavigation?: boolean;
};
Expand Down Expand Up @@ -494,6 +510,12 @@ function getInstallBlueprintMessageData(
};
}

function isOpenSiteToolsMessage(
data: RelayMessageData
): data is OpenSiteToolsMessageData {
return data.relayType === 'personal-wp-open-site-tools';
}

function getRequestId(data: RelayMessageData): string | undefined {
return typeof data.requestId === 'string' ? data.requestId : undefined;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,72 @@ function playground_report_url_to_parent() {
add_action('wp_head', 'playground_report_url_to_parent');
add_action('admin_head', 'playground_report_url_to_parent');

/**
* Adds the Personal WP Site Tools latch inside wp-admin.
*/
function playground_personal_wp_should_render_site_tools_admin_bar_node() {
if ( empty( $_SERVER['REQUEST_URI'] ) ) {
return false;
}
$path = parse_url( $_SERVER['REQUEST_URI'], PHP_URL_PATH );
if ( ! is_string( $path ) ) {
return false;
}
return (
$path === '/scope:default/wp-admin' ||
strpos( $path, '/scope:default/wp-admin/' ) === 0
);
}

function playground_personal_wp_add_site_tools_admin_bar_node( $wp_admin_bar ) {
if ( ! playground_personal_wp_should_render_site_tools_admin_bar_node() ) {
return;
}

$wp_admin_bar->add_node(
array(
'id' => 'playground-personal-wp-site-tools',
'title' => 'Open Site Tools',
'href' => '#',
)
);
}
add_action( 'admin_bar_menu', 'playground_personal_wp_add_site_tools_admin_bar_node' );

function playground_personal_wp_render_site_tools_admin_bar_script() {
if ( ! playground_personal_wp_should_render_site_tools_admin_bar_node() ) {
return;
}
?>
<script>
(function () {
function openSiteTools(event) {
event.preventDefault();
window.parent.postMessage(
{
type: 'relay',
relayType: 'personal-wp-open-site-tools'
},
'*'
);
}

var item = document.querySelector(
'#wp-admin-bar-playground-personal-wp-site-tools > .ab-item'
);
if (!item || window.parent === window) {
return;
}
item.addEventListener('click', openSiteTools);
})();
</script>
<?php
}
add_action(
'admin_footer',
'playground_personal_wp_render_site_tools_admin_bar_script'
);

/**
* The default WordPress requests transports have been disabled
* at this point. However, the Requests class requires at least
Expand Down
Loading