From 2c7db46676b0bd0ba65a041d423c267f191bf575 Mon Sep 17 00:00:00 2001 From: Matus Fedak Date: Thu, 5 Dec 2019 01:32:25 +0100 Subject: [PATCH] Add possibility to listen on displayOptions changes --- README.md | 1 + demo/index.tsx | 36 ++++++++++++++++++++++++++++++++++-- src/components/Voyager.tsx | 5 +++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 36aaf257..9d781f2c 100644 --- a/README.md +++ b/README.md @@ -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`. diff --git a/demo/index.tsx b/demo/index.tsx index 0a0ae091..6fc94948 100644 --- a/demo/index.tsx +++ b/demo/index.tsx @@ -19,10 +19,25 @@ 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, { @@ -45,7 +60,11 @@ export default class Demo extends React.Component { return ( - +
@@ -71,6 +90,19 @@ export default class Demo extends React.Component { } } +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 = {}; diff --git a/src/components/Voyager.tsx b/src/components/Voyager.tsx index 209f26c0..41eb1e85 100644 --- a/src/components/Voyager.tsx +++ b/src/components/Voyager.tsx @@ -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; @@ -64,6 +65,7 @@ export default class Voyager extends React.Component { hideRoot: PropTypes.bool, showLeafFields: PropTypes.bool, }), + onDisplayOptionsChange: PropTypes.func, hideDocs: PropTypes.bool, hideSettings: PropTypes.bool, workerURI: PropTypes.string, @@ -232,6 +234,9 @@ export default class Voyager extends React.Component { handleDisplayOptionsChange = delta => { const displayOptions = { ...this.state.displayOptions, ...delta }; + if (this.props.onDisplayOptionsChange) { + this.props.onDisplayOptionsChange(displayOptions); + } this.updateIntrospection(this.state.introspectionData, displayOptions); };