Skip to content

Commit 300653e

Browse files
Move "Change schema" into the main lib (#296)
1 parent c8e9d8e commit 300653e

File tree

4 files changed

+50
-47
lines changed

4 files changed

+50
-47
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ module system it is exported as `GraphQLVoyager` global variable.
3737
- `displayOptions.sortByAlphabet` [`boolean`, default `false`] - sort fields on graph by alphabet
3838
- `displayOptions.showLeafFields` [`boolean`, default `true`] - show all scalars and enums
3939
- `displayOptions.hideRoot` [`boolean`, default `false`] - hide the root type
40+
- `allowToChangeSchema` [`boolean`, default `false`] - allow users to change schema
4041
- `hideDocs` [`boolean`, default `false`] - hide the docs sidebar
4142
- `hideSettings` [`boolean`, default `false`] - hide settings panel
4243
- `hideVoyagerLogo` [`boolean`, default `true`] - hide voyager logo

demo/index.tsx

+8-41
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,8 @@
1-
import Button from '@mui/material/Button';
2-
import Stack from '@mui/material/Stack';
3-
import { ThemeProvider } from '@mui/material/styles';
4-
import { useState } from 'react';
51
import * as ReactDOMClient from 'react-dom/client';
62

73
import { GraphQLVoyager } from '../src';
8-
import { theme } from '../src/components/MUITheme';
9-
import { IntrospectionModal } from './IntrospectionModal';
104
import { defaultPreset, PRESETS } from './presets';
115

12-
interface DemoProps {
13-
introspection: any;
14-
presets?: { [name: string]: any };
15-
}
16-
17-
function Demo(props: DemoProps) {
18-
const [introspection, setIntrospection] = useState(() => props.introspection);
19-
const [changeSchemaModalOpen, setChangeSchemaModalOpen] = useState(false);
20-
21-
return (
22-
<ThemeProvider theme={theme}>
23-
<GraphQLVoyager introspection={introspection} hideVoyagerLogo={false}>
24-
<GraphQLVoyager.PanelHeader>
25-
<Stack padding={({ panelSpacing }) => `0 ${panelSpacing}`}>
26-
<Button
27-
color="primary"
28-
style={{ color: 'white' }}
29-
variant="contained"
30-
onClick={() => setChangeSchemaModalOpen(true)}
31-
>
32-
Change Schema
33-
</Button>
34-
</Stack>
35-
</GraphQLVoyager.PanelHeader>
36-
</GraphQLVoyager>
37-
<IntrospectionModal
38-
open={changeSchemaModalOpen}
39-
presets={props.presets}
40-
onClose={() => setChangeSchemaModalOpen(false)}
41-
onChange={setIntrospection}
42-
/>
43-
</ThemeProvider>
44-
);
45-
}
466
const currentUrl = new URL(window.location.href);
477
const url = currentUrl.searchParams.get('url');
488
const withCredentials = currentUrl.searchParams.get('withCredentials');
@@ -66,4 +26,11 @@ const introspection =
6626
: defaultPreset;
6727

6828
const reactRoot = ReactDOMClient.createRoot(document.getElementById('root'));
69-
reactRoot.render(<Demo introspection={introspection} presets={PRESETS} />);
29+
reactRoot.render(
30+
<GraphQLVoyager
31+
introspection={introspection}
32+
introspectionPresets={PRESETS}
33+
allowToChangeSchema={true}
34+
hideVoyagerLogo={false}
35+
/>,
36+
);

demo/IntrospectionModal.tsx renamed to src/components/IntrospectionModal.tsx

+5-6
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import Grid from '@mui/material/Unstable_Grid2';
1515
import { buildSchema, introspectionFromSchema } from 'graphql/utilities';
1616
import { useState } from 'react';
1717

18-
import { voyagerIntrospectionQuery } from '../src/utils/introspection-query';
18+
import { voyagerIntrospectionQuery } from '../utils/introspection-query';
1919

2020
enum InputType {
2121
Presets = 'Presets',
@@ -102,15 +102,14 @@ export function IntrospectionModal(props: IntrospectionModalProps) {
102102
function handleSubmit() {
103103
switch (inputType) {
104104
case InputType.Presets:
105-
onChange(presets[activePreset]);
105+
onChange(presets[activePreset].data);
106106
break;
107107
case InputType.Introspection:
108-
onChange(JSON.parse(jsonText));
108+
// check for errors and check if valid
109+
onChange(JSON.parse(jsonText).data);
109110
break;
110111
case InputType.SDL:
111-
onChange({
112-
data: introspectionFromSchema(buildSchema(sdlText)),
113-
});
112+
onChange(introspectionFromSchema(buildSchema(sdlText)));
114113
break;
115114
}
116115
setSubmitted({ inputType, sdlText, jsonText, activePreset });

src/components/Voyager.tsx

+36
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import './Voyager.css';
22
import './viewport.css';
33

4+
import Button from '@mui/material/Button';
5+
import Stack from '@mui/material/Stack';
46
import { ThemeProvider } from '@mui/material/styles';
57
import {
68
Children,
@@ -17,6 +19,7 @@ import { extractTypeId, getSchema } from '../introspection';
1719
import { voyagerIntrospectionQuery } from '../utils/introspection-query';
1820
import DocExplorer from './doc-explorer/DocExplorer';
1921
import GraphViewport from './GraphViewport';
22+
import { IntrospectionModal } from './IntrospectionModal';
2023
import { theme } from './MUITheme';
2124
import Settings from './settings/Settings';
2225
import PoweredBy from './utils/PoweredBy';
@@ -45,6 +48,8 @@ const defaultDisplayOptions = {
4548
export interface VoyagerProps {
4649
introspection: IntrospectionProvider | unknown;
4750
displayOptions?: VoyagerDisplayOptions;
51+
introspectionPresets?: { [name: string]: any };
52+
allowToChangeSchema?: boolean;
4853
hideDocs?: boolean;
4954
hideSettings?: boolean;
5055
hideVoyagerLogo?: boolean;
@@ -53,6 +58,7 @@ export interface VoyagerProps {
5358
}
5459

5560
export default function Voyager(props: VoyagerProps) {
61+
const [introspectionModalOpen, setIntrospectionModalOpen] = useState(false);
5662
const [introspectionData, setIntrospectionData] = useState(null);
5763
const [displayOptions, setDisplayOptions] = useState({
5864
...defaultDisplayOptions,
@@ -103,6 +109,7 @@ export default function Voyager(props: VoyagerProps) {
103109
const [selected, setSelected] = useState({ typeID: null, edgeID: null });
104110

105111
const {
112+
allowToChangeSchema = false,
106113
hideDocs = false,
107114
hideSettings = false,
108115
// TODO: switch to false in the next major version
@@ -121,10 +128,22 @@ export default function Voyager(props: VoyagerProps) {
121128
{!hideDocs && renderPanel()}
122129
{!hideSettings && renderSettings()}
123130
{renderGraphViewport()}
131+
{allowToChangeSchema && renderIntrospectionModal()}
124132
</div>
125133
</ThemeProvider>
126134
);
127135

136+
function renderIntrospectionModal() {
137+
return (
138+
<IntrospectionModal
139+
open={introspectionModalOpen}
140+
presets={props.introspectionPresets}
141+
onClose={() => setIntrospectionModalOpen(false)}
142+
onChange={setIntrospectionData}
143+
/>
144+
);
145+
}
146+
128147
function renderPanel() {
129148
const children = Children.toArray(props.children);
130149
const panelHeader = children.find(
@@ -135,6 +154,7 @@ export default function Voyager(props: VoyagerProps) {
135154
<div className="doc-panel">
136155
<div className="contents">
137156
{!hideVoyagerLogo && <VoyagerLogo />}
157+
{allowToChangeSchema && renderChangeSchemaButton()}
138158
{panelHeader}
139159
<DocExplorer
140160
typeGraph={typeGraph}
@@ -150,6 +170,22 @@ export default function Voyager(props: VoyagerProps) {
150170
);
151171
}
152172

173+
function renderChangeSchemaButton() {
174+
// TODO: generalize padding by applying it to the whole panel
175+
return (
176+
<Stack padding={({ panelSpacing }) => `0 ${panelSpacing}`}>
177+
<Button
178+
color="primary"
179+
style={{ color: 'white' }}
180+
variant="contained"
181+
onClick={() => setIntrospectionModalOpen(true)}
182+
>
183+
Change Schema
184+
</Button>
185+
</Stack>
186+
);
187+
}
188+
153189
function renderSettings() {
154190
if (schema == null) return null;
155191

0 commit comments

Comments
 (0)