Skip to content

Commit

Permalink
Move WordPress & Gutenberg PR Preview to Playground website (#1938)
Browse files Browse the repository at this point in the history
## Motivation for the change, related issues

#1655 (comment)

I moved wordpress.html and gutenberg.html to Playground itself.
By the way, I also made a mini appearance refactor for the modal, based
on Figma. And I used components from WordPress packages.

## Implementation details
- [x] Add modals with input to fill PR number
- [x] Move & unify logic to fetch PR by number
- [x] Error handling
- [x] Appearance refactor for Modals
- [x] Implement new Modal to other components
- [x] Fetch PR number directly from query
- [x] New Dropdown Menu in main sidebar (thanks to this, we can import
playground when we don't have any active one)

## Testing Instructions (or ideally a Blueprint)
- Any blueprint
- Go to Playground settings
- Click three dots next to ~~Homepage button~~ future Logo place
- Select Preview a WordPress PR or Preview a Gutenberg PR

It is also possible to open modal via URL params:
/?modal=preview-pr-wordpress or /?modal=preview-pr-gutenberg


![image](https://github.com/user-attachments/assets/56bf1e59-2186-47b0-8991-b55f32237289)

![image](https://github.com/user-attachments/assets/821703ed-0fe4-4a7d-a266-2981a312370c)

![image](https://github.com/user-attachments/assets/765f3b91-c42a-4635-8e6b-00d4a631291b)

---------

Co-authored-by: Brandon Payton <[email protected]>
  • Loading branch information
ajotka and brandonpayton authored Nov 22, 2024
1 parent 07200bf commit c795006
Show file tree
Hide file tree
Showing 30 changed files with 575 additions and 280 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ import {
useAppDispatch,
} from '../../lib/state/redux/store';
import { SyncLocalFilesButton } from '../sync-local-files-button';
import { Dropdown, Icon, Modal } from '@wordpress/components';
import { Dropdown, Icon } from '@wordpress/components';
import { Modal } from '../../components/modal';
import { cog } from '@wordpress/icons';
import Button from '../button';
import { ActiveSiteSettingsForm } from '../site-manager/site-settings-form';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,6 @@
import { useEffect, useState } from 'react';
import Modal from '../modal';
import React, { useEffect, useState } from 'react';
import { logger } from '@php-wasm/logger';
import { Button, TextareaControl, TextControl } from '@wordpress/components';

import css from './style.module.css';

import { TextareaControl, TextControl } from '@wordpress/components';
import { Blueprint } from '@wp-playground/blueprints';
import { useDispatch } from 'react-redux';
import {
Expand All @@ -13,6 +9,8 @@ import {
useAppSelector,
} from '../../lib/state/redux/store';
import { setActiveModal } from '../../lib/state/redux/slice-ui';
import { Modal } from '../../components/modal';
import ModalButtons from '../modal/modal-buttons';

export function ErrorReportModal(props: { blueprint: Blueprint }) {
const activeModal = useAppSelector(
Expand Down Expand Up @@ -157,49 +155,32 @@ export function ErrorReportModal(props: { blueprint: Blueprint }) {
}

return (
<Modal isOpen={true} onRequestClose={onClose}>
<header
className={css.errorReportModalHeader}
aria-label="Error reporting form header"
>
<h2>{getTitle()}</h2>
<p>{getContent()}</p>
</header>
<Modal title={getTitle()} onRequestClose={onClose} small>
<p>{getContent()}</p>
{showForm() && (
<>
<main>
<TextareaControl
label="How can we recreate this error?"
help="Describe what caused the error and how can we recreate it."
value={text}
onChange={setText}
className={css.errorReportModalTextarea}
required={true}
/>
<TextareaControl
label="Logs"
value={logs}
onChange={setLogs}
className={css.errorReportModalTextarea}
/>

<TextControl
label="Url"
value={url}
onChange={setUrl}
/>
</main>
<footer className={css.errorReportModalFooter}>
<Button
variant="primary"
onClick={onSubmit}
isBusy={loading}
disabled={loading || !text}
>
Report error
</Button>
<Button onClick={onClose}>Cancel</Button>
</footer>
<TextareaControl
label="How can we recreate this error?"
help="Describe what caused the error and how can we recreate it."
value={text}
onChange={setText}
required={true}
/>
<TextareaControl
label="Logs"
value={logs}
onChange={setLogs}
/>

<TextControl label="Url" value={url} onChange={setUrl} />

<ModalButtons
areBusy={loading}
areDisabled={loading || !text}
onCancel={onClose}
onSubmit={onSubmit}
submitText="Report error"
/>
</>
)}
</Modal>
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import React from 'react';
import { useDispatch } from 'react-redux';
import { usePlaygroundClient } from '../../lib/use-playground-client';
import ImportForm from './index';
import Modal from '../modal';
import ImportForm from '../import-form/index';
import { Modal } from '../../components/modal';
import { setActiveModal } from '../../lib/state/redux/slice-ui';
import { PlaygroundDispatch } from '../../lib/state/redux/store';
import { useDispatch } from 'react-redux';

export const ImportFormModal = () => {
const playground = usePlaygroundClient();
Expand All @@ -23,7 +24,7 @@ export const ImportFormModal = () => {

return (
<Modal
isOpen={!!playground}
title="Import Playground"
contentLabel='This is a dialog window which overlays the main content of the
page. The modal begins with a heading 2 called "Import
Playground". Pressing the Close Import Window will close
Expand Down
32 changes: 11 additions & 21 deletions packages/playground/website/src/components/import-form/index.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
import React from 'react';
import { useRef, useState } from 'react';
import { PlaygroundClient, importWordPressFiles } from '@wp-playground/client';

import css from './style.module.css';
import forms from '../../forms.module.css';
import Button from '../button';
import { logger } from '@php-wasm/logger';
import ModalButtons from '../modal/modal-buttons';

interface ImportFormProps {
playground: PlaygroundClient;
Expand All @@ -18,7 +16,6 @@ export default function ImportForm({
onImported,
onClose,
}: ImportFormProps) {
const form = useRef<any>();
const fileInputRef = useRef<any>();
const [file, setFile] = useState<File | null>(null);
const [error, setError] = useState<string>('');
Expand Down Expand Up @@ -46,11 +43,8 @@ export default function ImportForm({
}

return (
<form id="import-playground-form" ref={form} onSubmit={handleSubmit}>
<h2 tabIndex={0} style={{ marginTop: 0, textAlign: 'center' }}>
Import Playground
</h2>
<p className={css.modalText}>
<>
<p>
You may replace the current WordPress Playground site with a
previously exported one.
</p>
Expand All @@ -64,17 +58,13 @@ export default function ImportForm({
accept="application/zip"
/>
</div>
<div className={forms.submitRow}>
<Button
id="import-submit--btn"
className={forms.btn}
disabled={!file}
variant="primary"
size="large"
>
Import
</Button>
</div>
</form>

<ModalButtons
areDisabled={!file}
onCancel={onClose}
onSubmit={handleSubmit}
submitText="Import"
/>
</>
);
}
11 changes: 9 additions & 2 deletions packages/playground/website/src/components/layout/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ import {
setActiveModal,
setSiteManagerOpen,
} from '../../lib/state/redux/slice-ui';
import { ImportFormModal } from '../import-form/modal';
import { ImportFormModal } from '../import-form-modal';
import { PreviewPRModal } from '../../github/preview-pr';

acquireOAuthTokenIfNeeded();

Expand All @@ -42,7 +43,9 @@ export const modalSlugs = {
START_ERROR: 'start-error',
IMPORT_FORM: 'import-form',
GITHUB_IMPORT: 'github-import',
GITHUB_EXPORT: 'github-export'
GITHUB_EXPORT: 'github-export',
PREVIEW_PR_WP: 'preview-pr-wordpress',
PREVIEW_PR_GUTENBERG: 'preview-pr-gutenberg',
}

const displayMode = getDisplayModeFromQuery();
Expand Down Expand Up @@ -178,6 +181,10 @@ function Modals(blueprint: Blueprint) {
return <StartErrorModal />;
} else if (currentModal === modalSlugs.IMPORT_FORM) {
return <ImportFormModal />;
} else if (currentModal === modalSlugs.PREVIEW_PR_WP) {
return <PreviewPRModal target="wordpress" />;
} else if (currentModal === modalSlugs.PREVIEW_PR_GUTENBERG) {
return <PreviewPRModal target="gutenberg" />;
} else if (currentModal === modalSlugs.GITHUB_IMPORT) {
return <GithubImportModal
onImported={({
Expand Down
16 changes: 4 additions & 12 deletions packages/playground/website/src/components/log-modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { useEffect, useState } from 'react';
import Modal from '../modal';
import { logEventType, logger } from '@php-wasm/logger';

import classNames from 'classnames';
import css from './style.module.css';

import { Modal } from '../modal';
import { TextControl } from '@wordpress/components';
import {
PlaygroundDispatch,
Expand All @@ -23,16 +22,9 @@ export function LogModal(props: { description?: JSX.Element; title?: string }) {
dispatch(setActiveModal(null));
}

const styles = {
content: { width: 800 },
};

return (
<Modal isOpen={true} onRequestClose={onClose} styles={styles}>
<header aria-label="Error logs list header">
<h2>{props.title || 'Error Logs'}</h2>
{props.description}
</header>
<Modal title={props.title || 'Error Logs'} onRequestClose={onClose}>
<div>{props.description}</div>
<SiteLogs key={activeModal} className={css.logsInsideModal} />
</Modal>
);
Expand Down Expand Up @@ -91,7 +83,7 @@ export function SiteLogs({ className }: { className?: string }) {
No matching logs found.
</div>
) : (
<div className={css.logEmptyPlaceholder}>
<div>
Error logs for Playground, WordPress, and PHP will show
up here when something goes wrong.
<br />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,6 @@
flex-grow: 1;
}

.log__list {
padding-bottom: 20px;
flex-grow: 1;
max-height: 100%;
}

.log__empty_placeholder {
padding-bottom: 20px;
}

.log__entry {
font-family: monospace;
word-wrap: break-word;
Expand Down
73 changes: 18 additions & 55 deletions packages/playground/website/src/components/modal/index.tsx
Original file line number Diff line number Diff line change
@@ -1,61 +1,24 @@
import ReactModal from 'react-modal';
import React from 'react';
import { Modal as WordPressModal } from '@wordpress/components';
import type { ModalProps as WordPressModalProps } from '@wordpress/components/build-types/modal/types';
import classNames from 'classnames';
import css from './style.module.css';

ReactModal.setAppElement('#root');

interface ModalProps extends ReactModal.Props {
styles?: ReactModal.Styles;
interface ModalProps extends WordPressModalProps {
small?: boolean;
}
export const defaultStyles: ReactModal.Styles = {
content: {
top: '50%',
left: '50%',
right: 'auto',
bottom: 'auto',
marginRight: '-50%',
transform: 'translate(-50%, -50%)',
width: 400,
maxWidth: '100vw',
zIndex: 200,
textAlign: 'center',
color: '#000',
border: '#000 1px solid',
borderRadius: '6px',
background: '#fff',
},
overlay: {
background: '#1e2327d0',
zIndex: 10,
},
};
export default function Modal(props: ModalProps) {
const styles = {
overlay: { ...defaultStyles.overlay, ...props.styles?.overlay },
content: { ...defaultStyles.content, ...props.styles?.content },
};
export function Modal({ small, className, children, ...rest }: ModalProps) {
const modalClass = classNames(
css.modal,
{
[css.modalSmall]: small,
},
className
);

return (
<ReactModal style={styles} {...props}>
<div className={css.modalInner} id="modal-content">
<button
id="import-close-modal--btn"
onClick={props.onRequestClose}
className={`${css.btn} ${css.btnClose}`}
aria-label="Close"
title="Close"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="32"
height="32"
aria-hidden="true"
focusable="false"
>
<path d="M13 11.8l6.1-6.3-1-1-6.1 6.2-6.1-6.2-1 1 6.1 6.3-6.5 6.7 1 1 6.5-6.6 6.5 6.6 1-1z"></path>
</svg>
</button>
{props.children}
</div>
</ReactModal>
<WordPressModal className={modalClass} {...rest}>
{children}
</WordPressModal>
);
}
Loading

0 comments on commit c795006

Please sign in to comment.