Skip to content

Commit aa53380

Browse files
committed
Slight refactor of tab handling.
A tab 'key' was a misnomer -- it should be called an index. Added a "uuid" to each tab, so that the tab data is stored correctly within GraphiQL. This will prevent GraphiQL.app from restoring stale data from closed tabs when a new tab is created.
1 parent 8c42380 commit aa53380

2 files changed

Lines changed: 45 additions & 41 deletions

File tree

app/components/App.js

Lines changed: 43 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/*global Mousetrap*/
22
import _ from 'lodash';
3+
import uuid from 'uuid';
34
import React from 'react';
45
import ReactDOM from 'react-dom';
56
import fetch from 'isomorphic-fetch';
@@ -19,7 +20,7 @@ export default class App extends React.Component {
1920

2021
this.state = {
2122
headerEditOpen: false,
22-
currentTabKey: storage.getItem('currentTab') ? parseInt(storage.getItem('currentTab')) : 0,
23+
currentTabIndex: storage.getItem('currentTabIndex') ? parseInt(storage.getItem('currentTabIndex')) : 0,
2324
tabs: storage.getItem('tabs') ? JSON.parse(storage.getItem('tabs')) : [
2425
{
2526
name: null,
@@ -67,37 +68,39 @@ export default class App extends React.Component {
6768

6869
createNewTab() {
6970
const currentTab = this.getCurrentTab();
70-
const newTabKey = this.state.tabs.length;
71+
const newTabIndex = this.state.tabs.length;
7172

7273
this.setState({
7374
tabs: [...this.state.tabs, {
75+
uuid: uuid.v1(),
7476
headers: currentTab.headers,
7577
endpoint: currentTab.endpoint,
7678
method: currentTab.method
7779
}],
78-
currentTabKey: newTabKey
80+
currentTabIndex: newTabIndex
7981
}, () => {
8082
this.updateLocalStorage();
8183
});
8284
}
8385

8486
closeCurrentTab() {
85-
const currentTabKey = this.state.currentTabKey;
86-
let gotoTabKey = currentTabKey - 1;
87-
if (currentTabKey === 0) {
88-
gotoTabKey = 0;
87+
const currentTabIndex = this.state.currentTabIndex;
88+
let gotoTabIndex = currentTabIndex - 1;
89+
if (currentTabIndex === 0) {
90+
gotoTabIndex = 0;
8991
}
9092

9193
let newTabs = [
9294
...this.state.tabs
9395
];
9496

95-
newTabs.splice(currentTabKey, 1);
97+
newTabs.splice(currentTabIndex, 1);
9698

9799
if (newTabs.length === 0) {
98100
newTabs = [
99101
{
100102
name: null,
103+
uuid: uuid.v1(),
101104
headers: {},
102105
endpoint: '',
103106
method: 'post'
@@ -107,43 +110,43 @@ export default class App extends React.Component {
107110

108111
this.setState({
109112
tabs: newTabs,
110-
currentTabKey: gotoTabKey
113+
currentTabIndex: gotoTabIndex
111114
}, () => {
112115
this.updateLocalStorage();
113116
});
114117
}
115118

116119
gotoNextTab() {
117-
let nextTab = this.state.currentTabKey + 1;
120+
let nextTab = this.state.currentTabIndex + 1;
118121
if (nextTab >= this.state.tabs.length) {
119122
nextTab = 0;
120123
}
121124
this.setState({
122-
currentTabKey: nextTab
125+
currentTabIndex: nextTab
123126
}, () => {
124127
this.updateLocalStorage();
125128
});
126129
}
127130

128131
gotoPreviousTab() {
129-
let prevTab = this.state.currentTabKey - 1;
132+
let prevTab = this.state.currentTabIndex - 1;
130133
if (prevTab < 0) {
131134
prevTab = this.state.tabs.length - 1;
132135
}
133136
this.setState({
134-
currentTabKey: prevTab
137+
currentTabIndex: prevTab
135138
}, () => {
136139
this.updateLocalStorage();
137140
});
138141
}
139142

140143
getCurrentTab() {
141-
return this.state.tabs[this.state.currentTabKey];
144+
return this.state.tabs[this.state.currentTabIndex];
142145
}
143146

144147
updateLocalStorage() {
145148
window.localStorage.setItem('tabs', JSON.stringify(this.state.tabs));
146-
window.localStorage.setItem('currentTab', this.state.currentTabKey);
149+
window.localStorage.setItem('currentTabIndex', this.state.currentTabIndex);
147150
}
148151

149152
graphQLFetcher = (graphQLParams) => {
@@ -160,7 +163,7 @@ export default class App extends React.Component {
160163
}
161164

162165
url += url.indexOf('?') == -1 ? "?" : "&";
163-
166+
164167
return fetch(url + "query=" + encodeURIComponent(graphQLParams['query']) + "&variables=" + encodeURIComponent(graphQLParams['variables']), {
165168
method: method,
166169
headers: Object.assign({}, defaultHeaders, headers),
@@ -178,17 +181,17 @@ export default class App extends React.Component {
178181
if (typeof eOrKey === 'number') {
179182
this.updateFieldForTab(eOrKey, field, e.target.value);
180183
} else {
181-
this.updateFieldForTab(this.state.currentTabKey, field, eOrKey.target.value);
184+
this.updateFieldForTab(this.state.currentTabIndex, field, eOrKey.target.value);
182185
}
183186
}
184187

185-
updateFieldForTab(tabKey, field, value) {
188+
updateFieldForTab(tabIndex, field, value) {
186189
const { tabs } = this.state;
187190

188191
const newTabs = [...tabs];
189192

190-
newTabs[tabKey] = {
191-
...tabs[tabKey],
193+
newTabs[tabIndex] = {
194+
...tabs[tabIndex],
192195
[field]: value
193196
};
194197

@@ -199,18 +202,18 @@ export default class App extends React.Component {
199202
});
200203
}
201204

202-
handleTabClick = (tabKey) => {
203-
if (tabKey !== this.state.editingTab) {
205+
handleTabClick = (tabIndex) => {
206+
if (tabIndex !== this.state.editingTab) {
204207
this.setState({
205-
currentTabKey: tabKey,
208+
currentTabIndex: tabIndex,
206209
editingTab: null
207210
});
208211
}
209212
}
210213

211-
handleTabDoubleClick = (tabKey) => {
214+
handleTabDoubleClick = (tabIndex) => {
212215
this.setState({
213-
editingTab: tabKey
216+
editingTab: tabIndex
214217
}, () => {
215218
ReactDOM.findDOMNode(this.refs.editingTabNameInput).focus();
216219
});
@@ -237,15 +240,15 @@ export default class App extends React.Component {
237240
}
238241

239242
getHeadersFromModal = (headers) => {
240-
this.updateFieldForTab(this.state.currentTabKey, 'headers', headers);
243+
this.updateFieldForTab(this.state.currentTabIndex, 'headers', headers);
241244
}
242245

243246
render() {
244247
const currentTab = this.getCurrentTab();
245248

246-
const { currentTabKey } = this.state;
249+
const { currentTabIndex } = this.state;
247250
const tabEl = (
248-
<div key={currentTabKey} className="tabs__tab">
251+
<div key={currentTabIndex} className="tabs__tab">
249252
<div className="config-form clearfix">
250253
<div className="field endpoint-box">
251254
<label htmlFor="endpoint">GraphQL Endpoint</label>
@@ -268,8 +271,8 @@ export default class App extends React.Component {
268271
// THIS IS THE GROSSEST THING I'VE EVER DONE AND I HATE IT. FIXME ASAP
269272
}
270273
<GraphiQL
271-
key={currentTabKey + currentTab.endpoint + JSON.stringify(currentTab.headers)}
272-
storage={getStorage(`graphiql:${currentTabKey}`)}
274+
key={currentTabIndex + currentTab.endpoint + JSON.stringify(currentTab.headers)}
275+
storage={getStorage(`graphiql:${currentTab.uuid}`)}
273276
fetcher={this.graphQLFetcher} />
274277
</div>
275278
</div>
@@ -279,21 +282,21 @@ export default class App extends React.Component {
279282
<div className="wrapper">
280283
<div className="tab-bar">
281284
<div className="tab-bar-inner">
282-
{_.map(this.state.tabs, (tab, tabKey) => {
285+
{_.map(this.state.tabs, (tab, tabIndex) => {
283286
return (
284287
<li
285-
key={tabKey}
286-
className={tabKey === this.state.currentTabKey ? 'active' : ''}>
288+
key={tabIndex}
289+
className={tabIndex === this.state.currentTabIndex ? 'active' : ''}>
287290
<a href="javascript:;"
288-
onClick={this.handleTabClick.bind(this, tabKey)}
289-
onDoubleClick={this.handleTabDoubleClick.bind(this, tabKey)}>
290-
{ this.state.editingTab === tabKey ?
291+
onClick={this.handleTabClick.bind(this, tabIndex)}
292+
onDoubleClick={this.handleTabDoubleClick.bind(this, tabIndex)}>
293+
{ this.state.editingTab === tabIndex ?
291294
<input ref="editingTabNameInput"
292295
type="text"
293-
value={tab.name}
296+
value={tab.name || ''}
294297
onKeyUp={this.handleEditTabKeyUp}
295-
onChange={this.handleChange.bind(this, 'name', tabKey)} />
296-
: tab.name || `Untitled Query ${tabKey + 1}` }
298+
onChange={this.handleChange.bind(this, 'name', tabIndex)} />
299+
: tab.name || `Untitled Query ${tabIndex + 1}` }
297300
</a>
298301
</li>
299302
);
@@ -305,7 +308,7 @@ export default class App extends React.Component {
305308
</div>
306309
<Modal isOpen={this.state.headerEditOpen} onRequestClose={this.closeModal}>
307310
<HTTPHeaderEditor
308-
headers={_.map(this.state.tabs[this.state.currentTabKey].headers, (value, key) => ({ key, value }))}
311+
headers={_.map(this.state.tabs[this.state.currentTabIndex].headers, (value, key) => ({ key, value }))}
309312
onCreateHeaders={this.getHeadersFromModal}
310313
closeModal={this.closeModal} />
311314
</Modal>

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@
3434
"radium": "^0.14.1",
3535
"react": "^15.1.0",
3636
"react-dom": "^15.1.0",
37-
"react-modal": "^1.3.0"
37+
"react-modal": "^1.3.0",
38+
"uuid": "^2.0.2"
3839
},
3940
"devDependencies": {
4041
"asar": "^0.8.0",

0 commit comments

Comments
 (0)