Remove concept of Panels
parent
3a7ed1a32f
commit
51b641b2c3
|
@ -1,11 +0,0 @@
|
|||
import reducer from 'src/data_explorer/reducers/dataExplorerUI';
|
||||
import {activatePanel} from 'src/data_explorer/actions/view';
|
||||
|
||||
describe('DataExplorer.Reducers.UI', () => {
|
||||
it('can set the active panel', () => {
|
||||
const activePanel = 123;
|
||||
const actual = reducer({}, activatePanel(activePanel));
|
||||
|
||||
expect(actual).to.deep.equal({activePanel});
|
||||
});
|
||||
});
|
|
@ -1,34 +0,0 @@
|
|||
import reducer from 'src/data_explorer/reducers/panels';
|
||||
import {deletePanel} from 'src/data_explorer/actions/view';
|
||||
|
||||
const fakeAddPanelAction = (panelID, queryID) => {
|
||||
return {
|
||||
type: 'CREATE_PANEL',
|
||||
payload: {panelID, queryID},
|
||||
};
|
||||
};
|
||||
|
||||
describe('Chronograf.Reducers.Panel', () => {
|
||||
let state;
|
||||
const panelID = 123;
|
||||
const queryID = 456;
|
||||
|
||||
beforeEach(() => {
|
||||
state = reducer({}, fakeAddPanelAction(panelID, queryID));
|
||||
});
|
||||
|
||||
it('can add a panel', () => {
|
||||
const actual = state[panelID];
|
||||
expect(actual).to.deep.equal({
|
||||
id: panelID,
|
||||
queryIds: [queryID],
|
||||
});
|
||||
});
|
||||
|
||||
it('can delete a panel', () => {
|
||||
const nextState = reducer(state, deletePanel(panelID));
|
||||
|
||||
const actual = nextState[panelID];
|
||||
expect(actual).to.equal(undefined);
|
||||
});
|
||||
});
|
|
@ -1,35 +1,6 @@
|
|||
import uuid from 'node-uuid';
|
||||
|
||||
export function createPanel() {
|
||||
return {
|
||||
type: 'CREATE_PANEL',
|
||||
payload: {
|
||||
panelID: uuid.v4(), // for the default Panel
|
||||
queryID: uuid.v4(), // for the default Query
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function renamePanel(panelId, name) {
|
||||
return {
|
||||
type: 'RENAME_PANEL',
|
||||
payload: {
|
||||
panelId,
|
||||
name,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function deletePanel(panelId) {
|
||||
return {
|
||||
type: 'DELETE_PANEL',
|
||||
payload: {
|
||||
panelId,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function addQuery(panelId, options) {
|
||||
export function addQuery(options = {}) {
|
||||
return {
|
||||
type: 'ADD_QUERY',
|
||||
payload: {
|
||||
|
@ -157,12 +128,3 @@ export function updateRawQuery(queryID, text) {
|
|||
},
|
||||
};
|
||||
}
|
||||
|
||||
export function activatePanel(panelID) {
|
||||
return {
|
||||
type: 'ACTIVATE_PANEL',
|
||||
payload: {
|
||||
panelID,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,183 +0,0 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import classNames from 'classnames';
|
||||
import QueryEditor from './QueryEditor';
|
||||
import QueryTabItem from './QueryTabItem';
|
||||
import RenamePanelModal from './RenamePanelModal';
|
||||
import SimpleDropdown from 'src/shared/components/SimpleDropdown';
|
||||
|
||||
const Panel = React.createClass({
|
||||
propTypes: {
|
||||
panel: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
}).isRequired,
|
||||
queries: PropTypes.arrayOf(PropTypes.shape({})).isRequired,
|
||||
timeRange: PropTypes.shape({
|
||||
upper: PropTypes.string,
|
||||
lower: PropTypes.string,
|
||||
}).isRequired,
|
||||
isExpanded: PropTypes.bool.isRequired,
|
||||
onTogglePanel: PropTypes.func.isRequired,
|
||||
actions: PropTypes.shape({
|
||||
chooseNamespace: PropTypes.func.isRequired,
|
||||
chooseMeasurement: PropTypes.func.isRequired,
|
||||
chooseTag: PropTypes.func.isRequired,
|
||||
groupByTag: PropTypes.func.isRequired,
|
||||
addQuery: PropTypes.func.isRequired,
|
||||
deleteQuery: PropTypes.func.isRequired,
|
||||
toggleField: PropTypes.func.isRequired,
|
||||
groupByTime: PropTypes.func.isRequired,
|
||||
toggleTagAcceptance: PropTypes.func.isRequired,
|
||||
applyFuncsToField: PropTypes.func.isRequired,
|
||||
deletePanel: PropTypes.func.isRequired,
|
||||
renamePanel: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
setActiveQuery: PropTypes.func.isRequired,
|
||||
activeQueryID: PropTypes.string,
|
||||
},
|
||||
|
||||
handleSetActiveQuery(query) {
|
||||
this.props.setActiveQuery(query.id);
|
||||
},
|
||||
|
||||
handleAddQuery() {
|
||||
this.props.actions.addQuery();
|
||||
},
|
||||
|
||||
handleAddRawQuery() {
|
||||
this.props.actions.addQuery({rawText: `SELECT "fields" from "db"."rp"."measurement"`});
|
||||
},
|
||||
|
||||
handleDeleteQuery(query) {
|
||||
this.props.actions.deleteQuery(query.id);
|
||||
},
|
||||
|
||||
handleSelectPanel() {
|
||||
this.props.onTogglePanel(this.props.panel);
|
||||
},
|
||||
|
||||
handleDeletePanel(e) {
|
||||
e.stopPropagation();
|
||||
this.props.actions.deletePanel(this.props.panel.id);
|
||||
},
|
||||
|
||||
getActiveQuery() {
|
||||
const {queries, activeQueryID} = this.props;
|
||||
const activeQuery = queries.find((query) => query.id === activeQueryID);
|
||||
const defaultQuery = queries[0];
|
||||
|
||||
return activeQuery || defaultQuery;
|
||||
},
|
||||
|
||||
openRenamePanelModal(e) {
|
||||
e.stopPropagation();
|
||||
$(`#renamePanelModal-${this.props.panel.id}`).modal('show'); // eslint-disable-line no-undef
|
||||
},
|
||||
|
||||
handleRename(newName) {
|
||||
this.props.actions.renamePanel(this.props.panel.id, newName);
|
||||
},
|
||||
|
||||
|
||||
render() {
|
||||
const {panel, isExpanded} = this.props;
|
||||
|
||||
return (
|
||||
<div className={classNames('panel', {active: isExpanded})}>
|
||||
<div className="panel--header" onClick={this.handleSelectPanel}>
|
||||
<div className="panel--name">
|
||||
<span className="icon caret-right"></span>
|
||||
{panel.name || "Graph"}
|
||||
</div>
|
||||
<div className="panel--actions">
|
||||
{/* <div title="Export Queries to Dashboard" className="panel--action"><span className="icon export"></span></div> */}
|
||||
<div title="Rename Graph" className="panel--action" onClick={this.openRenamePanelModal}><span className="icon pencil"></span></div>
|
||||
<div title="Delete Graph" className="panel--action" onClick={this.handleDeletePanel}><span className="icon trash"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
{this.renderQueryTabList()}
|
||||
{this.renderQueryEditor()}
|
||||
<RenamePanelModal panel={panel} onConfirm={this.handleRename} />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
renderQueryEditor() {
|
||||
if (!this.props.isExpanded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const {timeRange, actions} = this.props;
|
||||
const query = this.getActiveQuery();
|
||||
|
||||
if (!query) {
|
||||
return (
|
||||
<div className="qeditor--empty">
|
||||
<h5>This Graph has no Queries</h5>
|
||||
<br/>
|
||||
<div className="btn btn-primary" role="button" onClick={this.handleAddQuery}>Add a Query</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<QueryEditor
|
||||
timeRange={timeRange}
|
||||
query={this.getActiveQuery()}
|
||||
actions={actions}
|
||||
onAddQuery={this.handleAddQuery}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
||||
renderQueryTabList() {
|
||||
const {isExpanded, queries} = this.props;
|
||||
if (!isExpanded) {
|
||||
return null;
|
||||
}
|
||||
return (
|
||||
<div className="panel--tabs">
|
||||
{queries.map((q) => {
|
||||
let queryTabText;
|
||||
if (q.rawText) {
|
||||
queryTabText = 'InfluxQL';
|
||||
} else {
|
||||
queryTabText = (q.measurement && q.fields.length !== 0) ? `${q.measurement}.${q.fields[0].field}` : 'Query';
|
||||
}
|
||||
return (
|
||||
<QueryTabItem
|
||||
isActive={this.getActiveQuery().id === q.id}
|
||||
key={q.id}
|
||||
query={q}
|
||||
onSelect={this.handleSetActiveQuery}
|
||||
onDelete={this.handleDeleteQuery}
|
||||
queryTabText={queryTabText}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
{this.renderAddQuery()}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
onChoose(item) {
|
||||
switch (item.text) {
|
||||
case 'Query Builder':
|
||||
this.handleAddQuery();
|
||||
break;
|
||||
case 'InfluxQL':
|
||||
this.handleAddRawQuery();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
renderAddQuery() {
|
||||
return (
|
||||
<SimpleDropdown onChoose={this.onChoose} items={[{text: 'Query Builder'}, {text: 'InfluxQL'}]} className="panel--tab-new">
|
||||
<span className="icon plus"></span>
|
||||
</SimpleDropdown>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default Panel;
|
|
@ -1,63 +0,0 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import {bindActionCreators} from 'redux';
|
||||
import PanelList from './PanelList';
|
||||
import * as viewActions from '../actions/view';
|
||||
|
||||
const {string, func} = PropTypes;
|
||||
const PanelBuilder = React.createClass({
|
||||
propTypes: {
|
||||
width: string,
|
||||
actions: PropTypes.shape({
|
||||
activatePanel: func.isRequired,
|
||||
createPanel: func.isRequired,
|
||||
deleteQuery: func.isRequired,
|
||||
addQuery: func.isRequired,
|
||||
editRawText: func.isRequired,
|
||||
chooseNamespace: func.isRequired,
|
||||
chooseMeasurement: func.isRequired,
|
||||
toggleField: func.isRequired,
|
||||
groupByTime: func.isRequired,
|
||||
applyFuncsToField: func.isRequired,
|
||||
chooseTag: func.isRequired,
|
||||
groupByTag: func.isRequired,
|
||||
toggleTagAcceptance: func.isRequired,
|
||||
deletePanel: func.isRequired,
|
||||
}).isRequired,
|
||||
setActiveQuery: func.isRequired,
|
||||
activePanelID: string,
|
||||
activeQueryID: string,
|
||||
},
|
||||
|
||||
handleCreateExplorer() {
|
||||
this.props.actions.createPanel();
|
||||
},
|
||||
|
||||
render() {
|
||||
const {width, actions, setActiveQuery, activePanelID, activeQueryID} = this.props;
|
||||
|
||||
return (
|
||||
<div className="panel-builder" style={{width}}>
|
||||
<div className="btn btn-block btn-primary" onClick={this.handleCreateExplorer}><span className="icon graphline"></span> Create Graph</div>
|
||||
<PanelList
|
||||
actions={actions}
|
||||
setActiveQuery={setActiveQuery}
|
||||
activePanelID={activePanelID}
|
||||
activeQueryID={activeQueryID}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
function mapStateToProps() {
|
||||
return {};
|
||||
}
|
||||
|
||||
function mapDispatchToProps(dispatch) {
|
||||
return {
|
||||
actions: bindActionCreators(viewActions, dispatch),
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(PanelBuilder);
|
|
@ -1,76 +0,0 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import _ from 'lodash';
|
||||
|
||||
import Panel from './Panel';
|
||||
|
||||
const {func, string, shape} = PropTypes;
|
||||
const PanelList = React.createClass({
|
||||
propTypes: {
|
||||
timeRange: shape({
|
||||
upper: string,
|
||||
lower: string,
|
||||
}).isRequired,
|
||||
panels: shape({}).isRequired,
|
||||
queryConfigs: PropTypes.shape({}),
|
||||
actions: shape({
|
||||
activatePanel: func.isRequired,
|
||||
deleteQuery: func.isRequired,
|
||||
addQuery: func.isRequired,
|
||||
}).isRequired,
|
||||
setActiveQuery: func.isRequired,
|
||||
activePanelID: string,
|
||||
activeQueryID: string,
|
||||
},
|
||||
|
||||
handleTogglePanel(panel) {
|
||||
const panelID = panel.id === this.props.activePanelID ? null : panel.id;
|
||||
this.props.actions.activatePanel(panelID);
|
||||
|
||||
// Reset the activeQueryID when toggling Exporations
|
||||
this.props.setActiveQuery(null);
|
||||
},
|
||||
|
||||
render() {
|
||||
const {actions, panels, timeRange, queryConfigs, setActiveQuery, activeQueryID, activePanelID} = this.props;
|
||||
|
||||
return (
|
||||
<div>
|
||||
{Object.keys(panels).map((panelID) => {
|
||||
const panel = panels[panelID];
|
||||
const queries = panel.queryIds.map((configId) => queryConfigs[configId]);
|
||||
const deleteQueryFromPanel = _.partial(actions.deleteQuery, panelID);
|
||||
const addQueryToPanel = _.partial(actions.addQuery, panelID);
|
||||
const allActions = Object.assign({}, actions, {
|
||||
addQuery: addQueryToPanel,
|
||||
deleteQuery: deleteQueryFromPanel,
|
||||
});
|
||||
|
||||
return (
|
||||
<Panel
|
||||
key={panelID}
|
||||
panel={panel}
|
||||
queries={queries}
|
||||
timeRange={timeRange}
|
||||
onTogglePanel={this.handleTogglePanel}
|
||||
setActiveQuery={setActiveQuery}
|
||||
isExpanded={panelID === activePanelID}
|
||||
actions={allActions}
|
||||
activeQueryID={activeQueryID}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
timeRange: state.timeRange,
|
||||
panels: state.panels,
|
||||
queryConfigs: state.queryConfigs,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(PanelList);
|
|
@ -26,8 +26,6 @@ const QueryBuilder = React.createClass({
|
|||
groupByTime: PropTypes.func.isRequired,
|
||||
toggleTagAcceptance: PropTypes.func.isRequired,
|
||||
applyFuncsToField: PropTypes.func.isRequired,
|
||||
deletePanel: PropTypes.func.isRequired,
|
||||
renamePanel: PropTypes.func.isRequired,
|
||||
}).isRequired,
|
||||
setActiveQuery: PropTypes.func.isRequired,
|
||||
activeQueryID: PropTypes.string,
|
||||
|
|
|
@ -1,67 +0,0 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
|
||||
const RenamePanelModal = React.createClass({
|
||||
propTypes: {
|
||||
onConfirm: PropTypes.func.isRequired,
|
||||
panel: PropTypes.shape({
|
||||
id: PropTypes.string.isRequired,
|
||||
}),
|
||||
},
|
||||
|
||||
getInitialState() {
|
||||
return {error: null};
|
||||
},
|
||||
|
||||
componentDidMount() {
|
||||
this.refs.name.focus();
|
||||
},
|
||||
|
||||
render() {
|
||||
const {panel} = this.props;
|
||||
|
||||
return (
|
||||
<div className="modal fade in" id={`renamePanelModal-${panel.id}`} tabIndex="-1" role="dialog">
|
||||
<div className="modal-dialog">
|
||||
<div className="modal-content">
|
||||
<div className="modal-header">
|
||||
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<h4 className="modal-title">Rename Panel</h4>
|
||||
</div>
|
||||
<div className="modal-body">
|
||||
{this.state.error ?
|
||||
<div className="alert alert-danger" role="alert">{this.state.error}</div>
|
||||
: null}
|
||||
<div className="form-grid padding-top">
|
||||
<div className="form-group col-md-8 col-md-offset-2">
|
||||
<input ref="name" name="renameExplorer" type="text" placeholder={panel.name} className="form-control input-lg" id="renameExplorer" required={true} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className="modal-footer">
|
||||
<button className="btn btn-info" data-dismiss="modal">Cancel</button>
|
||||
<button onClick={this.handleConfirm} className="btn btn-success">Rename</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
handleConfirm() {
|
||||
const name = this.refs.name.value;
|
||||
|
||||
if (name === '') {
|
||||
this.setState({error: "Name can't be blank"});
|
||||
return;
|
||||
}
|
||||
|
||||
$(`#renamePanelModal-${this.props.panel.id}`).modal('hide'); // eslint-disable-line no-undef
|
||||
this.refs.name.value = '';
|
||||
this.setState({error: null});
|
||||
this.props.onConfirm(name);
|
||||
},
|
||||
});
|
||||
|
||||
export default RenamePanelModal;
|
|
@ -52,7 +52,7 @@ const Visualization = React.createClass({
|
|||
const isInDataExplorer = true;
|
||||
|
||||
return (
|
||||
<div ref={(p) => this.panel = p} className={classNames("graph", {active: true})}>
|
||||
<div className={classNames("graph", {active: true})}>
|
||||
<div className="graph-heading">
|
||||
<div className="graph-title">
|
||||
{name || "Graph"}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
import React, {PropTypes} from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import Visualization from './Visualization';
|
||||
|
||||
const {shape, string} = PropTypes;
|
||||
|
||||
const Visualizations = React.createClass({
|
||||
propTypes: {
|
||||
timeRange: shape({
|
||||
upper: string,
|
||||
lower: string,
|
||||
}).isRequired,
|
||||
panels: shape({}).isRequired,
|
||||
queryConfigs: shape({}).isRequired,
|
||||
width: string,
|
||||
activePanelID: string,
|
||||
activeQueryID: string,
|
||||
},
|
||||
|
||||
render() {
|
||||
const {panels, queryConfigs, timeRange, width, activePanelID} = this.props;
|
||||
|
||||
const visualizations = Object.keys(panels).map((panelID) => {
|
||||
const panel = panels[panelID];
|
||||
const queries = panel.queryIds.map((id) => queryConfigs[id]);
|
||||
const isActive = panelID === activePanelID;
|
||||
|
||||
return <Visualization activeQueryIndex={this.getActiveQueryIndex(panelID)} name={panel.name} key={panelID} queryConfigs={queries} timeRange={timeRange} isActive={isActive} />;
|
||||
});
|
||||
|
||||
return (
|
||||
<div className="panels" style={{width}}>
|
||||
{visualizations}
|
||||
</div>
|
||||
);
|
||||
},
|
||||
|
||||
getActiveQueryIndex(panelID) {
|
||||
const {activeQueryID, activePanelID, panels} = this.props;
|
||||
const isPanelActive = panelID === activePanelID;
|
||||
|
||||
if (!isPanelActive) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (activeQueryID === null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return panels[panelID].queryIds.indexOf(activeQueryID);
|
||||
},
|
||||
});
|
||||
|
||||
function mapStateToProps(state) {
|
||||
return {
|
||||
panels: state.panels,
|
||||
queryConfigs: state.queryConfigs,
|
||||
};
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps)(Visualizations);
|
|
@ -84,12 +84,11 @@ const DataExplorer = React.createClass({
|
|||
});
|
||||
|
||||
function mapStateToProps(state) {
|
||||
const {timeRange, queryConfigs, dataExplorerUI} = state;
|
||||
const {timeRange, queryConfigs} = state;
|
||||
|
||||
return {
|
||||
timeRange,
|
||||
queryConfigs,
|
||||
activePanel: dataExplorerUI.activePanel,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -1,11 +0,0 @@
|
|||
export default function dataExplorerUI(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case 'ACTIVATE_PANEL':
|
||||
case 'CREATE_PANEL': {
|
||||
const {panelID} = action.payload;
|
||||
return {...state, activePanel: panelID};
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
|
@ -1,11 +1,7 @@
|
|||
import queryConfigs from './queryConfigs';
|
||||
import panels from './panels';
|
||||
import timeRange from './timeRange';
|
||||
import dataExplorerUI from './dataExplorerUI';
|
||||
|
||||
export {
|
||||
queryConfigs,
|
||||
panels,
|
||||
timeRange,
|
||||
dataExplorerUI,
|
||||
};
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
import update from 'react-addons-update';
|
||||
|
||||
export default function panels(state = {}, action) {
|
||||
switch (action.type) {
|
||||
case 'CREATE_PANEL': {
|
||||
const {panelID, queryID} = action.payload;
|
||||
return {
|
||||
...state,
|
||||
[panelID]: {id: panelID, queryIds: [queryID]},
|
||||
};
|
||||
}
|
||||
|
||||
case 'RENAME_PANEL': {
|
||||
const {panelId, name} = action.payload;
|
||||
return update(state, {
|
||||
[panelId]: {
|
||||
name: {$set: name},
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
case 'DELETE_PANEL': {
|
||||
const {panelId} = action.payload;
|
||||
return update(state, {$apply: (p) => {
|
||||
const panelsCopy = Object.assign({}, p);
|
||||
delete panelsCopy[panelId];
|
||||
return panelsCopy;
|
||||
}});
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
|
@ -46,7 +46,6 @@ export default function queryConfigs(state = {}, action) {
|
|||
return nextState;
|
||||
}
|
||||
|
||||
case 'CREATE_PANEL':
|
||||
case 'ADD_KAPACITOR_QUERY':
|
||||
case 'ADD_QUERY': {
|
||||
const {queryID, options} = action.payload;
|
||||
|
|
|
@ -19,13 +19,11 @@ export const loadLocalStorage = () => {
|
|||
}
|
||||
};
|
||||
|
||||
export const saveToLocalStorage = ({panels, queryConfigs, timeRange, dataExplorerUI}) => {
|
||||
export const saveToLocalStorage = ({queryConfigs, timeRange}) => {
|
||||
try {
|
||||
window.localStorage.setItem('state', JSON.stringify({
|
||||
panels,
|
||||
queryConfigs,
|
||||
timeRange,
|
||||
dataExplorerUI,
|
||||
}));
|
||||
} catch (err) {
|
||||
console.error('Unable to save data explorer: ', JSON.parse(err)); // eslint-disable-line no-console
|
||||
|
|
|
@ -29,7 +29,6 @@
|
|||
// DE Specific components
|
||||
@import 'data-explorer/query-builder';
|
||||
@import 'data-explorer/page-header';
|
||||
@import 'data-explorer/panel-builder';
|
||||
@import 'data-explorer/query-editor';
|
||||
@import 'data-explorer/raw-text';
|
||||
@import 'data-explorer/tag-list';
|
||||
|
|
|
@ -1,15 +0,0 @@
|
|||
.panel-builder {
|
||||
width: 399px;
|
||||
overflow-x: hidden;
|
||||
background: $g1-raven;
|
||||
padding: $explorer-page-padding;
|
||||
@include gradient-v($g2-kevlar,$g0-obsidian);
|
||||
|
||||
&::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
> .btn {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue