|
5 | 5 | * This source code is licensed under the license found in the LICENSE file in
|
6 | 6 | * the root directory of this source tree.
|
7 | 7 | */
|
8 |
| -import PropTypes from 'lib/PropTypes'; |
9 |
| -import Button from 'components/Button/Button.react'; |
10 |
| -import DashboardView from 'dashboard/DashboardView.react'; |
11 |
| -import Dropdown from 'components/Dropdown/Dropdown.react'; |
12 |
| -import Field from 'components/Field/Field.react'; |
13 |
| -import Fieldset from 'components/Fieldset/Fieldset.react'; |
14 |
| -import fieldStyle from 'components/Field/Field.scss'; |
15 |
| -import FlowFooter from 'components/FlowFooter/FlowFooter.react'; |
16 |
| -import FormNote from 'components/FormNote/FormNote.react'; |
17 |
| -import generateCurl from 'dashboard/Data/ApiConsole/generateCurl'; |
18 |
| -import JsonPrinter from 'components/JsonPrinter/JsonPrinter.react'; |
19 |
| -import Label from 'components/Label/Label.react'; |
20 |
| -import Modal from 'components/Modal/Modal.react'; |
21 |
| -import Option from 'components/Dropdown/Option.react'; |
22 |
| -import Parse from 'parse'; |
23 |
| -import ParseApp from 'lib/ParseApp'; |
24 |
| -import React from 'react'; |
25 |
| -import request from 'dashboard/Data/ApiConsole/request'; |
26 |
| -import styles from 'dashboard/Data/ApiConsole/ApiConsole.scss'; |
27 |
| -import TextInput from 'components/TextInput/TextInput.react'; |
28 |
| -import Toggle from 'components/Toggle/Toggle.react'; |
29 |
| -import Toolbar from 'components/Toolbar/Toolbar.react'; |
| 8 | +import React from 'react' |
| 9 | +import CategoryList from 'components/CategoryList/CategoryList.react' |
| 10 | +import DashboardView from 'dashboard/DashboardView.react' |
30 | 11 |
|
31 | 12 | export default class ApiConsole extends DashboardView {
|
32 | 13 |
|
33 | 14 | constructor() {
|
34 | 15 | super();
|
35 | 16 | this.section = 'Core';
|
36 | 17 | this.subsection = 'API Console';
|
37 |
| - |
38 |
| - this.state = { |
39 |
| - method: 'GET', |
40 |
| - endpoint: '', |
41 |
| - useMasterKey: false, |
42 |
| - runAsIdentifier: '', |
43 |
| - sessionToken: null, |
44 |
| - parameters: '', |
45 |
| - response: {results:[]}, |
46 |
| - fetchingUser: false, |
47 |
| - inProgress: false, |
48 |
| - error: false, |
49 |
| - curlModal: false, |
50 |
| - }; |
51 |
| - } |
52 |
| - |
53 |
| - fetchUser() { |
54 |
| - if (this.state.runAsIdentifier.length === 0) { |
55 |
| - this.setState({ error: false, sessionToken: null }); |
56 |
| - return; |
57 |
| - } |
58 |
| - Parse.Query.or( |
59 |
| - new Parse.Query(Parse.User).equalTo('username', this.state.runAsIdentifier ), |
60 |
| - new Parse.Query(Parse.User).equalTo('objectId', this.state.runAsIdentifier ) |
61 |
| - ).first({ useMasterKey: true }).then((found) => { |
62 |
| - if (found) { |
63 |
| - if (found.getSessionToken()) { |
64 |
| - this.setState({ sessionToken: found.getSessionToken(), error: false, fetchingUser: false }); |
65 |
| - } else { |
66 |
| - // Check the Sessions table |
67 |
| - new Parse.Query(Parse.Session).equalTo('user', found).first({ useMasterKey: true }).then((session) => { |
68 |
| - if (session) { |
69 |
| - this.setState({ sessionToken: session.getSessionToken(), error: false, fetchingUser: false }); |
70 |
| - } else { |
71 |
| - this.setState({ error: 'Unable to find any active sessions for that user.', fetchingUser: false }); |
72 |
| - } |
73 |
| - }, () => { |
74 |
| - this.setState({ error: 'Unable to find any active sessions for that user.', fetchingUser: false }); |
75 |
| - }); |
76 |
| - } |
77 |
| - } else { |
78 |
| - this.setState({ error: 'Unable to find that user.', fetchingUser: false }); |
79 |
| - } |
80 |
| - }, () => { |
81 |
| - this.setState({ error: 'Unable to find that user.', fetchingUser: false }); |
82 |
| - }); |
83 |
| - this.setState({ fetchingUser: true }); |
84 | 18 | }
|
85 | 19 |
|
86 |
| - makeRequest() { |
87 |
| - let endpoint = this.state.endpoint + (this.state.method === 'GET' ? `?${this.state.parameters}` : ''); |
88 |
| - let payload = (this.state.method === 'DELETE' || this.state.method === 'GET') ? null : this.state.parameters; |
89 |
| - let options = {}; |
90 |
| - if (this.state.useMasterKey) { |
91 |
| - options.useMasterKey = true; |
92 |
| - } |
93 |
| - if (this.state.sessionToken) { |
94 |
| - options.sessionToken = this.state.sessionToken; |
95 |
| - } |
96 |
| - request( |
97 |
| - this.context.currentApp, |
98 |
| - this.state.method, |
99 |
| - endpoint, |
100 |
| - payload, |
101 |
| - options |
102 |
| - ).then((response) => { |
103 |
| - this.setState({ response }); |
104 |
| - document.body.scrollTop = 540; |
105 |
| - }); |
106 |
| - } |
107 |
| - |
108 |
| - showCurl() { |
109 |
| - this.setState({ curlModal: true }); |
| 20 | + renderSidebar() { |
| 21 | + const { path } = this.props.match |
| 22 | + const current = path.substr(path.lastIndexOf('/') + 1, path.length - 1) |
| 23 | + return ( |
| 24 | + <CategoryList current={current} linkPrefix={'api_console/'} categories={[ |
| 25 | + { name: 'REST Console', id: 'rest' }, |
| 26 | + { name: 'GraphQL Console', id: 'graphql' } |
| 27 | + ]} /> |
| 28 | + ) |
110 | 29 | }
|
111 | 30 |
|
112 | 31 | renderContent() {
|
113 |
| - const methodDropdown = |
114 |
| - <Dropdown onChange={(method) => this.setState({method})} value={this.state.method}> |
115 |
| - <Option value='GET'>GET</Option> |
116 |
| - <Option value='POST'>POST</Option> |
117 |
| - <Option value='PUT'>PUT</Option> |
118 |
| - <Option value='DELETE'>DELETE</Option> |
119 |
| - </Dropdown> |
120 |
| - |
121 |
| - let hasError = this.state.fetchingUser || |
122 |
| - this.state.endpoint.length === 0 || |
123 |
| - (this.state.runAsIdentifier.length > 0 && !this.state.sessionToken); |
124 |
| - let parameterPlaceholder = 'where={"username":"johndoe"}'; |
125 |
| - if (this.state.method === 'POST' || this.state.method === 'PUT') { |
126 |
| - parameterPlaceholder = '{"name":"John"}'; |
127 |
| - } |
128 |
| - |
129 |
| - let modal = null; |
130 |
| - if (this.state.curlModal) { |
131 |
| - let payload = this.state.method === 'DELETE' ? null : this.state.parameters; |
132 |
| - let options = {}; |
133 |
| - if (this.state.useMasterKey) { |
134 |
| - options.useMasterKey = true; |
135 |
| - } |
136 |
| - if (this.state.sessionToken) { |
137 |
| - options.sessionToken = this.state.sessionToken; |
138 |
| - } |
139 |
| - let content = generateCurl( |
140 |
| - this.context.currentApp, |
141 |
| - this.state.method, |
142 |
| - this.state.endpoint, |
143 |
| - payload, |
144 |
| - options |
145 |
| - ); |
146 |
| - modal = ( |
147 |
| - <Modal |
148 |
| - title='cURL Request' |
149 |
| - subtitle='Use this to replicate the request' |
150 |
| - icon='laptop-outline' |
151 |
| - customFooter={ |
152 |
| - <div className={styles.footer}> |
153 |
| - <Button primary={true} value='Close' onClick={() => this.setState({ curlModal: false })} /> |
154 |
| - </div> |
155 |
| - }> |
156 |
| - <div className={styles.curl}>{content}</div> |
157 |
| - </Modal> |
158 |
| - ); |
159 |
| - } |
160 |
| - |
161 |
| - return ( |
162 |
| - <div style={{ padding: '120px 0 60px 0' }}> |
163 |
| - <Fieldset |
164 |
| - legend='Send a test query' |
165 |
| - description='Try out some queries, and take a look at what they return.'> |
166 |
| - <Field |
167 |
| - label={<Label text='What type of request?' />} |
168 |
| - input={methodDropdown} /> |
169 |
| - <Field |
170 |
| - label={<Label text='Which endpoint?' description={<span>Not sure what endpoint you need?<br />Take a look at our <a href="http://docs.parseplatform.org/rest/guide/">REST API guide</a>.</span>} />} |
171 |
| - input={<TextInput value={this.state.endpoint} monospace={true} placeholder={'classes/_User'} onChange={(endpoint) => this.setState({endpoint})} />} /> |
172 |
| - <Field |
173 |
| - label={<Label text='Use Master Key?' description={'This will bypass any ACL/CLPs.'} />} |
174 |
| - input={<Toggle value={this.state.useMasterKey} onChange={(useMasterKey) => this.setState({ useMasterKey })} />} /> |
175 |
| - <Field |
176 |
| - label={<Label text='Run as...' description={'Send your query as a specific user. You can use their username or Object ID.'} />} |
177 |
| - input={<TextInput value={this.state.runAsIdentifier} monospace={true} placeholder={'Username or ID'} onChange={(runAsIdentifier) => this.setState({runAsIdentifier})} onBlur={this.fetchUser.bind(this)} />} /> |
178 |
| - <FormNote color='red' show={!!this.state.error}>{this.state.error}</FormNote> |
179 |
| - <Field |
180 |
| - label={<Label text='Query parameters' description={<span>Learn more about query parameters in our <a href="http://docs.parseplatform.org/rest/guide/#queries">REST API guide</a>.</span>} />} |
181 |
| - input={<TextInput value={this.state.parameters} monospace={true} multiline={true} placeholder={parameterPlaceholder} onChange={(parameters) => this.setState({parameters})} />} /> |
182 |
| - </Fieldset> |
183 |
| - <Fieldset |
184 |
| - legend='Results' |
185 |
| - description=''> |
186 |
| - <div className={fieldStyle.field}> |
187 |
| - <JsonPrinter object={this.state.response} /> |
188 |
| - </div> |
189 |
| - </Fieldset> |
190 |
| - <Toolbar section='Core' subsection='API Console' /> |
191 |
| - <FlowFooter |
192 |
| - primary={<Button primary={true} disabled={hasError} value='Send Query' progress={this.state.inProgress} onClick={this.makeRequest.bind(this)} />} |
193 |
| - secondary={<Button disabled={hasError} value='Export to cURL' onClick={this.showCurl.bind(this)} />} /> |
194 |
| - {modal} |
195 |
| - </div> |
196 |
| - ); |
| 32 | + const child = React.Children.only(this.props.children); |
| 33 | + return React.cloneElement( |
| 34 | + child, |
| 35 | + { ...child.props } |
| 36 | + ) |
197 | 37 | }
|
198 | 38 | }
|
199 |
| - |
200 |
| -ApiConsole.contextTypes = { |
201 |
| - currentApp: PropTypes.instanceOf(ParseApp) |
202 |
| -}; |
0 commit comments