/* eslint-disable import/no-webpack-loader-syntax */
import React from 'react';
import CheckboxTree from 'react-checkbox-tree';
import { Voyager } from 'graphql-voyager';
import 'graphql-voyager/dist/voyager.css';
import PropTypes from 'prop-types';
import 'react-checkbox-tree/lib/react-checkbox-tree.css';
import './Preview.css';
import Worker from 'worker-loader!./graphql.worker';
const worker = new Worker();
/**
* @file Preview
* Handles the graphql voyager preview window
* @module Preview
* @extends React.Component
*/
export default class Preview extends React.Component {
constructor(props) {
super(props);
const { translationFile } = this.props;
this.state = {
nodes: this.initNodes(),
checked: this.initChecked(),
graphql: this.getGraphQL(translationFile),
};
}
/**
* Called after everytime preview window's checkbox tree gets updated
* @method
* @param {Object} nextProps - new props
*/
componentDidUpdate(nextProps) {
const { translationFile } = this.props;
if (nextProps.translationFile !== translationFile) {
const nodes = [];
const checked = [];
Object.keys(translationFile.endpoints).forEach((realEndpoint) => {
Object.keys(translationFile.endpoints[realEndpoint]).forEach((endpoint) => {
nodes.push({
value: `${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`,
label: endpoint,
});
checked.push(`${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`);
});
});
this.setState({ nodes, checked }, () => this.getGraphQL(translationFile));
}
}
/**
* Initalize the checkbox tree nodes
* @method
* @returns array of nodes
*/
initNodes = () => {
const { translationFile } = this.props;
const nodes = [];
Object.keys(translationFile.endpoints).forEach((realEndpoint) => {
Object.keys(translationFile.endpoints[realEndpoint]).forEach((endpoint) => {
nodes.push({
value: `${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`,
label: endpoint,
});
});
});
return nodes;
};
/**
* Initalize the checkbox tree nodes checked states
* @method
* @returns array of checked nodes
*/
initChecked = () => {
const { translationFile } = this.props;
const checked = [];
Object.keys(translationFile.endpoints).forEach((realEndpoint) => {
Object.keys(translationFile.endpoints[realEndpoint]).forEach((endpoint) => {
checked.push(`${endpoint.replace(/%2F/gi, '/')}${realEndpoint}`);
});
});
return checked;
};
/**
* Handle new checked nodes
* @method
* @param {Array} newChecked - array of the newly checked nodes
*/
onCheckHandler = (newChecked) => {
const { swaggerFile, translationFile } = this.props;
const newFile = { sourceVersion: swaggerFile.info.version, endpoints: {} };
// update translation file contents
newChecked.forEach((node) => {
const endpointName = node.substring(0, node.indexOf('/'));
const endpoint = node.substring(node.indexOf('/'));
newFile.endpoints[endpoint] = newFile.endpoints[endpoint] || {};
newFile.endpoints[endpoint][endpointName] = translationFile.endpoints[endpoint][endpointName];
});
this.setState(
{
checked: newChecked,
},
() => this.getGraphQL(newFile),
);
};
/**
* Generate the graphql schema
* @method
* @param {Object} translationFile - the translation file
*/
getGraphQL = (translationFile) => {
const { swaggerFile } = this.props;
worker.postMessage({ swaggerFile, translationFile });
worker.addEventListener('message', (event) => {
console.log(event.data);
this.setState({ graphql: event.data });
});
};
render() {
const { nodes, checked, graphql } = this.state;
return (
<>
<h3 className="filter-endpoints-text">Filter Endpoints</h3>
<CheckboxTree
checked={checked}
nodes={nodes}
onCheck={(newChecked) => this.onCheckHandler(newChecked)}
/>
{ graphql
&& <Voyager introspection={graphql} workerURI={`${process.env.PUBLIC_URL}/voyager.worker.js`} /> }
</>
);
}
}
Preview.defaultProps = {
swaggerFile: PropTypes.objectOf(PropTypes.object),
translationFile: PropTypes.objectOf(PropTypes.object),
};
Preview.propTypes = {
translationFile: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
swaggerFile: PropTypes.oneOfType([PropTypes.object, PropTypes.string]),
};