Skip to content

Commit 591c1ea

Browse files
authored
Merge pull request #61 from wp-graphql/feat/plugin-registry
feat: support plugin registration for the IDE
2 parents e54ffdb + 8ccdc28 commit 591c1ea

17 files changed

+339
-48
lines changed

package-lock.json

Lines changed: 32 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"@wordpress/data": "^9.22.0",
4040
"@wordpress/element": "^5.23.0",
4141
"@wordpress/hooks": "^3.49.0",
42+
"@wordpress/icons": "^9.43.0",
4243
"graphiql": "^3.0.10",
4344
"graphql": "^16.8.1",
4445
"graphql-ws": "^5.14.2",

phpcs.xml.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
<!-- What to scan: include any root-level PHP files, and the /src folder -->
66
<file>./wpgraphql-ide.php</file>
7+
<file>./plugins</file>
78
<exclude-pattern>./phpstan/*</exclude-pattern>
89
<exclude-pattern>*/**/tests/</exclude-pattern>
910
<exclude-pattern>*/node_modules/*</exclude-pattern>

plugins/README.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Plugins
2+
3+
This directory contains plugins intended to showcase how 3rd parties can hook into the GraphiQL IDE.
4+
5+
These are core features built as plugins do showcase how to extend the GraphiQL IDE.
6+
7+
Each of these plugins is configured as a separate "build" in the webpack.config.js, which generates a different bundle and *.asset.php, much like would happen for a standalone WordPress plugin using wp-scripts.
8+
9+
Each plugin enqueues it's own scripts, similar to how a 3rd party plugin would do it.
10+
11+
## Plugin: Explorer
12+
13+
## Plugin: Extensions
14+
15+
## Plugin: Help Screen
16+
17+
## Plugin: Persisted Queries
18+
19+
## Plugin: Code Exporter

plugins/help/HelpCard.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
const HelpCard = ({ card }) => {
2+
const { title, description, linkUrl, linkText } = card;
3+
return (
4+
<div className="wpgraphql-ide-help-card" style={{
5+
backgroundColor: `hsla(var(--color-neutral), var(--alpha-background-light))`,
6+
borderRadius: `calc(var(--border-radius-12) + var(--px-8))`,
7+
padding: `var(--px-20)`,
8+
marginTop: `var(--px-20)`,
9+
}}>
10+
<div className="wpgraphql-ide-help-card-title" style={{
11+
color: `hsla(var(--color-neutral), 1)`,
12+
fontFamily: `var(--font-family)`,
13+
fontSize: `var(--font-size-h4)`
14+
}}>{title}</div>
15+
<p className="wpgraphql-ide-help-card-description">{description}</p>
16+
<a className="wpgraphql-ide-help-card-link" href={linkUrl} target="_blank">{linkText}</a>
17+
</div>
18+
)
19+
}
20+
21+
export default HelpCard;

plugins/help/HelpPanel.js

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
import HelpCard from "./HelpCard";
2+
3+
export const helpCards = [
4+
{
5+
title: "Getting Started",
6+
description: "In the Getting Started section of the WPGraphQL website you will find resources to learn about GraphQL, WordPress, how they work together, and more.",
7+
linkText: "Get Started with WPGraphQL",
8+
linkUrl: "https://www.wpgraphql.com/docs/intro-to-graphql/"
9+
},
10+
{
11+
title: "Beginner Guides",
12+
description: "The Beginner guides go over specific topics such as GraphQL, WordPress, tools and techniques to interact with GraphQL APIs and more.",
13+
linkText: "Beginner Guides",
14+
linkUrl: "https://www.wpgraphql.com/docs/introduction/"
15+
},
16+
{
17+
title: "Using WPGraphQL",
18+
description: "Learn how WPGraphQL exposes WordPress data to the Graph, and shows how you can interact with this data using GraphQL.",
19+
linkText: "Using WPGraphQL",
20+
linkUrl: "https://www.wpgraphql.com/docs/posts-and-pages/"
21+
},
22+
{
23+
title: "Advanced Concepts",
24+
description: "Learn about concepts such as \"connections\", \"edges\", \"nodes\", what is an application data graph?\" and more",
25+
linkText: "Advanced Concepts",
26+
linkUrl: "https://www.wpgraphql.com/docs/wpgraphql-concepts/"
27+
},
28+
{
29+
title: "Recipes",
30+
description: "Here you will find snippets of code you can use to customize WPGraphQL. Most snippets are PHP and intended to be included in your theme or plugin.",
31+
linkText: "Recipes",
32+
linkUrl: "https://www.wpgraphql.com/recipes"
33+
},
34+
{
35+
title: "Actions",
36+
description: "Here you will find an index of the WordPress \"actions\" that are used in the WPGraphQL codebase. Actions can be used to customize behaviors.",
37+
linkText: "Actions",
38+
linkUrl: "https://www.wpgraphql.com/actions"
39+
},
40+
{
41+
title: "Filters",
42+
description: "Here you will find an index of the WordPress \"filters\" that are\ used in the WPGraphQL codebase. Filters are used to customize the Schema and more.",
43+
linkText: "Filters",
44+
linkUrl: "https://www.wpgraphql.com/filters"
45+
},
46+
{
47+
title: "Functions",
48+
description: "Here you will find functions that can be used to customize the WPGraphQL Schema. Learn how to register GraphQL \"fields\", \"types\", and more.",
49+
linkText: "Functions",
50+
linkUrl: "https://www.wpgraphql.com/functions"
51+
},
52+
{
53+
title: "Blog",
54+
description: "Keep up to date with the latest news and updates from the WPGraphQL team.",
55+
linkText: "Blog",
56+
linkUrl: "https://www.wpgraphql.com/Blog"
57+
},
58+
{
59+
title: "Extensions",
60+
description: "Browse the list of extensions that are available to extend WPGraphQL to work with other popular WordPress plugins.",
61+
linkText: "View Extensions",
62+
linkUrl: "https://www.wpgraphql.com/Extensions"
63+
},
64+
{
65+
title: "Join us in Slack",
66+
description: "There are ~3,000 people in the WPGraphQL Slack community asking questions and helping each other. Join us today!",
67+
linkText: "Join us in Slack",
68+
linkUrl: "https://join.slack.com/t/wp-graphql/shared_invite/zt-3vloo60z-PpJV2PFIwEathWDOxCTTLA"
69+
}
70+
];
71+
72+
const HelpPanel = () => {
73+
return (
74+
<div className="wpgraphql-ide-help-panel">
75+
<div className="graphiql-doc-explorer-title">Help</div>
76+
{helpCards.map((card, i) => {
77+
return <HelpCard key={i} card={card} />
78+
})}
79+
</div>
80+
)
81+
}
82+
83+
export default HelpPanel

plugins/help/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Help
2+
3+
The "Help" panel in the GraphiQL IDE provides users with quick access to links to helpful resources such as articles on the WPGraphQL website and access to join the WPGraphQL Slack community.
4+
5+
This panel is built as if it were a 3rd party plugin, leveraging APIs provided by the WPGraphQL API.
6+
7+
![Screenshot of the Help panel](./img/readme-img.png)
8+

plugins/help/help.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<?php
2+
/**
3+
* Plugin Name: GraphiQL Help Screen
4+
* Plugin Author: WPGraphQL
5+
* Description: Example of how third parties can register plugins that extend the WPGraphQL IDE
6+
*
7+
* @package WPGraphQLIDE
8+
*/
9+
10+
namespace WPGraphQLIDE\Plugins\Help;
11+
12+
/**
13+
* Hook into the GraphiQL enqueue lifecycle, ensuring scripts are only loaded if the GraphiQL IDE
14+
* is also loaded.
15+
*/
16+
add_action( 'wpgraphqlide_enqueue_script', __NAMESPACE__ . '\\enqueue_plugin' );
17+
18+
/**
19+
* Enqueue the plugin scripts and styles.
20+
*
21+
* @return void
22+
*/
23+
function enqueue_plugin() {
24+
25+
$asset_file = include WPGRAPHQL_IDE_PLUGIN_DIR_PATH . 'build/help.asset.php';
26+
27+
wp_enqueue_script(
28+
'wpgraphql-ide-help-plugin',
29+
WPGRAPHQL_IDE_PLUGIN_URL . 'build/help.js',
30+
array_merge( $asset_file['dependencies'], [ 'wpgraphql-ide' ] ),
31+
$asset_file['version'],
32+
true
33+
);
34+
}

plugins/help/img/readme-img.png

131 KB
Loading

plugins/help/index.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// wpgraphql-ide is registered as an external in the webpack config as it's made available
2+
// on the window object by the main wpgraphql-ide/index.js
3+
import { registerPlugin } from "wpgraphql-ide";
4+
import { Icon, help } from "@wordpress/icons";
5+
import HelpPanel from "./HelpPanel";
6+
7+
registerPlugin( 'help', {
8+
title: 'Help',
9+
icon: () => <Icon icon={help} style={{ fill: 'hsla(var(--color-neutral), var(--alpha-tertiary))' }} />,
10+
content: () => <HelpPanel />
11+
}
12+
)

src/App.jsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { useEffect } from '@wordpress/element';
2-
import { doAction } from '@wordpress/hooks';
1+
/* global WPGRAPHQL_IDE_DATA */
2+
import {createRoot, useEffect} from '@wordpress/element';
3+
import {doAction} from '@wordpress/hooks';
34
import { useDispatch, useSelect } from '@wordpress/data';
45
import { EditorDrawer } from './components/EditorDrawer';
56
import { Editor } from './components/Editor';
@@ -125,3 +126,17 @@ export function RenderApp() {
125126
</div>
126127
);
127128
}
129+
130+
/**
131+
* Get the ID of the HTML element where the React app will be placed.
132+
*
133+
* @constant {string} rootElementId - The ID of the HTML element.
134+
*
135+
* Localized in wpgraphql-ide.php
136+
*/
137+
const { rootElementId } = WPGRAPHQL_IDE_DATA;
138+
139+
const rootElement = document.getElementById(rootElementId);
140+
const root = createRoot(rootElement)
141+
root.render( <App /> );
142+

src/components/Editor.jsx

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,25 @@ const fetcher = async ( graphQLParams ) => {
2121
};
2222

2323
export function Editor() {
24-
const query = useSelect( ( select ) => {
25-
return select( 'wpgraphql-ide' ).getQuery();
26-
} );
27-
28-
const shouldRenderStandalone = useSelect( ( select ) => {
29-
return select( 'wpgraphql-ide' ).shouldRenderStandalone();
30-
} );
31-
32-
console.log( {
33-
query,
34-
shouldRenderStandalone,
35-
} );
24+
const { query, shouldRenderStandalone, plugins } = useSelect(select => {
25+
const wpgraphqlIde = select('wpgraphql-ide');
26+
return {
27+
query: wpgraphqlIde.getQuery(),
28+
shouldRenderStandalone: wpgraphqlIde.shouldRenderStandalone(),
29+
plugins: wpgraphqlIde.getPluginsArray()
30+
}
31+
});
3632

37-
const { setDrawerOpen } = useDispatch( 'wpgraphql-ide' );
33+
const { setDrawerOpen, setQuery } = useDispatch( 'wpgraphql-ide' );
3834

3935
return (
40-
<GraphiQL query={ query } fetcher={ fetcher }>
36+
<GraphiQL
37+
query={ query }
38+
onEditQuery={ query => {
39+
setQuery(query)
40+
}}
41+
fetcher={ fetcher }
42+
plugins={plugins.length > 0 ? plugins : null}>
4143
<GraphiQL.Logo>
4244
{ ! shouldRenderStandalone ? (
4345
<button

src/components/EditorDrawer.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,12 @@ import { useDispatch, useSelect } from '@wordpress/data';
55
export function EditorDrawer( { children } ) {
66
const buttonLabel = 'GraphQL IDE';
77

8-
const isDrawerOpen = useSelect( ( select ) => {
9-
return select( 'wpgraphql-ide' ).isDrawerOpen();
10-
} );
8+
const { isDrawerOpen } = useSelect( select => {
9+
const wpgraphqlIde = select( 'wpgraphql-ide' );
10+
return {
11+
isDrawerOpen: wpgraphqlIde.isDrawerOpen()
12+
};
13+
} )
1114

1215
const { setDrawerOpen } = useDispatch( 'wpgraphql-ide' );
1316

src/index.js

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,30 @@
11
/* global WPGRAPHQL_IDE_DATA */
2-
import { createRoot } from '@wordpress/element';
32
import { createHooks } from '@wordpress/hooks';
4-
import { register } from '@wordpress/data';
5-
import { App } from './App';
3+
import { register, dispatch } from '@wordpress/data';
64
import { store } from './store';
75

86
/**
9-
* Get the ID of the HTML element where the React app will be placed.
10-
*
11-
* @constant {string} rootElementId - The ID of the HTML element.
12-
*
13-
* Localized in wpgraphql-ide.php
7+
* Register the store to wp.data for use throughout the plugin and extending plugins
148
*/
15-
const { rootElementId } = WPGRAPHQL_IDE_DATA;
16-
17-
const rootElement = document.getElementById( rootElementId );
9+
register( store );
1810

19-
if ( rootElement ) {
20-
const root = createRoot( rootElement );
21-
root.render( <App /> );
11+
/**
12+
* Registers a plugin to the WPGraphQL IDE
13+
*
14+
* @param string name The name of the plugin to register
15+
* @param object config The config array to define the plugin
16+
*/
17+
const registerPlugin = (name, config) => {
18+
dispatch( store ).registerPlugin(name, config)
2219
}
2320

24-
register( store );
25-
26-
// Initialize hook system.
27-
App.hooks = createHooks();
21+
export const hooks = createHooks();
2822

29-
// Expose app as a global variable to utilize in gutenberg.
30-
window.WPGraphQLIDE = App;
23+
// Expose WPGraphQLIDE as a global variable.
24+
// This allows plugins to be enqueued as external JS
25+
// and make use of functions provideded by the IDE.
26+
window.WPGraphQLIDE = {
27+
registerPlugin,
28+
hooks,
29+
store
30+
};

0 commit comments

Comments
 (0)