app/addons/documents/mango/components/MangoIndexEditor.js (165 lines of code) (raw):

// Licensed under the Apache License, Version 2.0 (the "License"); you may not // use this file except in compliance with the License. You may obtain a copy of // the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the // License for the specific language governing permissions and limitations under // the License. import PropTypes from 'prop-types'; import React, { Component } from 'react'; import { Button } from 'react-bootstrap'; import ReactSelect from 'react-select'; import '../../../../../assets/js/plugins/prettify'; import app from '../../../../app'; import FauxtonAPI from '../../../../core/api'; import ReactComponents from '../../../components/react-components'; const PaddedBorderedBox = ReactComponents.PaddedBorderedBox; const CodeEditorPanel = ReactComponents.CodeEditorPanel; const LoadLines = ReactComponents.LoadLines; const getDocUrl = app.helpers.getDocUrl; export default class MangoIndexEditor extends Component { constructor(props) { super(props); this.state = { partitionedSelected: true }; this.onTemplateSelected = this.onTemplateSelected.bind(this); this.onTogglePartitioned = this.onTogglePartitioned.bind(this); this.saveIndex = this.saveIndex.bind(this); } componentDidMount() { prettyPrint(); this.props.loadIndexTemplates(); this.props.clearResults(); this.props.loadIndexList({ fetchParams: { ...this.props.fetchParams, skip: 0 } }); } componentDidUpdate(prevProps) { prettyPrint(); if (prevProps.templates != this.props.templates) { // Explicitly set value because updating 'CodeEditorPanel.defaultCode' won't change the editor once it's already loaded. this.setEditorValue(this.props.templates[0].value); } } setEditorValue(newValue = '') { if (this.codeEditor) { return this.codeEditor.getEditor().setValue(newValue); } } getEditorValue() { return this.codeEditor.getValue(); } editorHasErrors() { return this.codeEditor.getEditor().hasErrors(); } onTemplateSelected(selectedItem) { this.setEditorValue(selectedItem.value); } onTogglePartitioned() { this.setState({partitionedSelected: !this.state.partitionedSelected}); } partitionedCheckobx() { if (!this.props.isDbPartitioned) { return null; } return ( <label> <input id="js-partitioned-index" type="checkbox" checked={this.state.partitionedSelected} onChange={this.onTogglePartitioned} style={{margin: '0px 10px 0px 0px'}} /> Partitioned </label> ); } editor() { const encodedPartKey = this.props.partitionKey ? encodeURIComponent(this.props.partitionKey) : ''; const editQueryURL = '#' + FauxtonAPI.urls('mango', 'query-app', encodeURIComponent(this.props.databaseName), encodedPartKey); return ( <div className="mango-editor-wrapper"> <form className="form-horizontal" onSubmit={this.saveIndex}> <div className="padded-box"> <ReactSelect className="mango-select" options={this.props.templates} ref={node => this.templates = node} placeholder="Examples" searchable={false} clearable={false} autosize={false} onChange={this.onTemplateSelected} /> </div> <PaddedBorderedBox> <CodeEditorPanel id="query-field" ref={node => this.codeEditor = node} title="Index" docLink={getDocUrl('MANGO_INDEX')} defaultCode={this.props.queryIndexCode} setHeightToLineCount={false} className="mango-code-editor"/> {this.partitionedCheckobx()} </PaddedBorderedBox> <div className="padded-box"> <div className="actions-panel"> <Button variant="cf-primary" className="btn-space" id="create-index-btn" onClick={this.saveIndex}> Create Index </Button> <div className="right-side-actions"> <Button variant="cf-secondary" className="edit-link" href={editQueryURL}>Edit Query</Button> </div> </div> </div> </form> </div> ); } render() { if (this.props.isLoading) { return <LoadLines />; } return this.editor(); } saveIndex(event) { event.preventDefault(); const showInvalidCodeMsg = () => { FauxtonAPI.addNotification({ msg: 'Please fix the Javascript errors and try again.', type: 'error', clear: true }); }; if (this.editorHasErrors()) { showInvalidCodeMsg(); return; } let indexCode = this.getEditorValue(); if (this.props.isDbPartitioned) { // Set the partitioned property if not yet set try { const json = JSON.parse(indexCode); if (json.partitioned !== true && json.partitioned !== false) { json.partitioned = this.state.partitionedSelected; } indexCode = JSON.stringify(json); } catch (err) { showInvalidCodeMsg(); } } this.props.saveIndex({ databaseName: this.props.databaseName, indexCode: indexCode, fetchParams: this.props.fetchParams }); } } MangoIndexEditor.propTypes = { isLoading: PropTypes.bool.isRequired, databaseName: PropTypes.string.isRequired, isDbPartitioned: PropTypes.bool.isRequired, saveIndex: PropTypes.func.isRequired, queryIndexCode: PropTypes.string.isRequired, partitionKey: PropTypes.string, loadIndexTemplates: PropTypes.func.isRequired, clearResults: PropTypes.func.isRequired, loadIndexList: PropTypes.func.isRequired }; MangoIndexEditor.defaultProps = { isLoading: true, isDbPartitioned: false };