Skip to content

Commit

Permalink
Add possibility to listen on displayOptions changes
Browse files Browse the repository at this point in the history
  • Loading branch information
matystl committed Dec 5, 2019
1 parent 3c1c382 commit 9cb44d0
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 17 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ module system it is exported as `GraphQLVoyager` global variable.
+ `displayOptions.sortByAlphabet` [`boolean`, default `false`] - sort fields on graph by alphabet
+ `displayOptions.showLeafFields` [`boolean`, default `true`] - show all scalars and enums
+ `displayOptions.hideRoot` [`boolean`, default `false`] - hide the root type
+ `onDisplayOptionsChange` [function: `(displayOptions) => void`] _(optional)_ - called when user change displayOptions with UI. Can be used to save settings into localstorage or query params
+ `hideDocs` [`boolean`, default `false`] - hide the docs sidebar
+ `hideSettings` [`boolean`, default `false`] - hide settings panel
+ `workerURI` [`string`] _(optional)_ - absolute or relative path to Voyager web worker. By default it will try to load it from `voyager.worker.js`.
Expand Down
63 changes: 46 additions & 17 deletions demo/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,24 +19,36 @@ export default class Demo extends React.Component {
introspection: defaultPreset,
};

// not part of state because we parse it in constructor and just use in render
displayOptions = {};

constructor(props) {
super(props);

const { url, withCredentials } = getQueryParams();
const { url, withCredentials, ...restQueryParams } = getQueryParams();
// parse rest of query params we expect them to be in JSON format
// we might pick also some options that are not valid displayOptions but they will be ignored
// by Voyager component
for (const [key, value] of Object.entries(restQueryParams)) {
try {
this.displayOptions[key] = JSON.parse(value);
} catch (_) {
console.log(
`Not expected value for key "${key}" or value >${value}< is not in json format so just ignoring it`,
);
}
}
if (url) {
this.state.introspection = introspectionQuery => fetch(url, {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ query: introspectionQuery }),
...(
withCredentials === 'true'
? { credentials: 'include', mode: 'cors' }
: {}
),
}).then(response => response.json());
this.state.introspection = introspectionQuery =>
fetch(url, {
method: 'post',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({ query: introspectionQuery }),
...(withCredentials === 'true' ? { credentials: 'include', mode: 'cors' } : {}),
}).then(response => response.json());
}
}

Expand All @@ -48,13 +60,17 @@ export default class Demo extends React.Component {

return (
<MuiThemeProvider theme={theme}>
<GraphQLVoyager introspection={introspection}>
<GraphQLVoyager
introspection={introspection}
displayOptions={this.displayOptions}
onDisplayOptionsChange={setQueryParamsWithoutRefresh}
>
<GraphQLVoyager.PanelHeader>
<div className="voyager-panel">
<Logo />
<Button
color="primary"
style={{color: 'white'}}
style={{ color: 'white' }}
variant="contained"
className="choosebutton"
onClick={openChangeSchema}
Expand All @@ -67,13 +83,26 @@ export default class Demo extends React.Component {
<IntrospectionModal
open={changeSchemaModalOpen}
onClose={closeChangeSchema}
onChange={(introspection) => this.setState({ introspection })}
onChange={introspection => this.setState({ introspection })}
/>
</MuiThemeProvider>
);
}
}

function setQueryParamsWithoutRefresh(displayOptions) {
if ('URLSearchParams' in window) {
const searchParams = new URLSearchParams(window.location.search);
for (const [key, value] of Object.entries(displayOptions)) {
searchParams.set(key, JSON.stringify(value));
}
var newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
history.pushState(null, '', newRelativePathQuery);
} else {
console.log('Missing URLSearchParams so just printing new displayOptions', displayOptions);
}
}

function getQueryParams(): { [key: string]: string } {
const query = window.location.search.substring(1);
const params = {};
Expand Down
5 changes: 5 additions & 0 deletions src/components/Voyager.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ function normalizeDisplayOptions(options) {
export interface VoyagerProps {
introspection: IntrospectionProvider | Object;
displayOptions?: VoyagerDisplayOptions;
onDisplayOptionsChange?: (displayOptions: VoyagerDisplayOptions) => void;
hideDocs?: boolean;
hideSettings?: boolean;
workerURI?: string;
Expand All @@ -64,6 +65,7 @@ export default class Voyager extends React.Component<VoyagerProps> {
hideRoot: PropTypes.bool,
showLeafFields: PropTypes.bool,
}),
onDisplayOptionsChange: PropTypes.func,
hideDocs: PropTypes.bool,
hideSettings: PropTypes.bool,
workerURI: PropTypes.string,
Expand Down Expand Up @@ -232,6 +234,9 @@ export default class Voyager extends React.Component<VoyagerProps> {

handleDisplayOptionsChange = delta => {
const displayOptions = { ...this.state.displayOptions, ...delta };
if (this.props.onDisplayOptionsChange) {
this.props.onDisplayOptionsChange(displayOptions);
}
this.updateIntrospection(this.state.introspectionData, displayOptions);
};

Expand Down

0 comments on commit 9cb44d0

Please sign in to comment.