Skip to content

Commit

Permalink
Merge pull request #3 from williaster/resizable-grid
Browse files Browse the repository at this point in the history
add resizable grid and dragdroppables
  • Loading branch information
williaster authored Feb 21, 2018
2 parents 8a56d8f + 8b5e08f commit e92d386
Show file tree
Hide file tree
Showing 75 changed files with 3,969 additions and 329 deletions.
Binary file modified superset/assets/images/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed superset/assets/images/superset-logo@2x.png
Binary file not shown.
36 changes: 34 additions & 2 deletions superset/assets/javascripts/components/EditableTitle.jsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import TooltipWrapper from './TooltipWrapper';
import { t } from '../locales';

Expand Down Expand Up @@ -27,8 +28,10 @@ class EditableTitle extends React.PureComponent {
this.handleClick = this.handleClick.bind(this);
this.handleBlur = this.handleBlur.bind(this);
this.handleChange = this.handleChange.bind(this);
this.handleKeyDown = this.handleKeyDown.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
}

componentWillReceiveProps(nextProps) {
if (nextProps.title !== this.state.title) {
this.setState({
Expand All @@ -37,15 +40,17 @@ class EditableTitle extends React.PureComponent {
});
}
}

handleClick() {
if (!this.props.canEdit) {
if (!this.props.canEdit || this.state.isEditing) {
return;
}

this.setState({
isEditing: true,
});
}

handleBlur() {
if (!this.props.canEdit) {
return;
Expand All @@ -67,9 +72,31 @@ class EditableTitle extends React.PureComponent {
this.setState({
lastTitle: this.state.title,
});
}

if (this.props.title !== this.state.title) {
this.props.onSaveTitle(this.state.title);
}
}

handleKeyDown(ev) {
// this entire method exists to support using EditableTitle as the title of a
// react-bootstrap Tab, as a workaround for this line in react-bootstrap https://goo.gl/ZVLmv4
//
// tl;dr when a Tab EditableTitle is being edited, typically the Tab it's within has been
// clicked and is focused/active. for accessibility, when focused the Tab <a /> intercepts
// the ' ' key (among others, including all arrows) and onChange() doesn't fire. somehow
// keydown is still called so we can detect this and manually add a ' ' to the current title
if (ev.key === ' ') {
let title = ev.target.value;
const titleLength = (title || '').length;
if (title && title[titleLength - 1] !== ' ') {
title = `${title} `;
this.setState(() => ({ title }));
}
}
}

handleChange(ev) {
if (!this.props.canEdit) {
return;
Expand All @@ -79,19 +106,22 @@ class EditableTitle extends React.PureComponent {
title: ev.target.value,
});
}

handleKeyPress(ev) {
if (ev.key === 'Enter') {
ev.preventDefault();

this.handleBlur();
}
}

render() {
let input = (
<input
required
type={this.state.isEditing ? 'text' : 'button'}
value={this.state.title}
onKeyDown={this.handleKeyDown}
onChange={this.handleChange}
onBlur={this.handleBlur}
onClick={this.handleClick}
Expand All @@ -110,7 +140,9 @@ class EditableTitle extends React.PureComponent {
);
}
return (
<span className="editable-title">{input}</span>
<span className={cx('editable-title', this.props.canEdit && 'editable-title--editable')}>
{input}
</span>
);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,16 @@ import Dashboard from '../v2/components/Dashboard';

function mapStateToProps({ charts, dashboard }) {
return {
initMessages: dashboard.common.flash_messages,
timeout: dashboard.common.conf.SUPERSET_WEBSERVER_TIMEOUT,
dashboard: dashboard.dashboard,
slices: charts,
datasources: dashboard.datasources,
filters: dashboard.filters,
refresh: !!dashboard.refresh,
userId: dashboard.userId,
isStarred: !!dashboard.isStarred,
editMode: dashboard.editMode,
// initMessages: dashboard.common.flash_messages,
// timeout: dashboard.common.conf.SUPERSET_WEBSERVER_TIMEOUT,
// dashboard: dashboard.dashboard,
// slices: charts,
// datasources: dashboard.datasources,
// filters: dashboard.filters,
// refresh: !!dashboard.refresh,
// userId: dashboard.userId,
// isStarred: !!dashboard.isStarred,
// editMode: dashboard.editMode,
};
}

Expand Down
21 changes: 16 additions & 5 deletions superset/assets/javascripts/dashboard/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,33 @@ import { initEnhancer } from '../reduxUtils';
import { appSetup } from '../common';
import { initJQueryAjax } from '../modules/utils';
import DashboardContainer from './components/DashboardContainer';
import rootReducer, { getInitialState } from './reducers';
// import rootReducer, { getInitialState } from './reducers';

import testLayout from './v2/fixtures/testLayout';
import rootReducer from './v2/reducers/';

appSetup();
initJQueryAjax();

const appContainer = document.getElementById('app');
const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
const initState = Object.assign({}, getInitialState(bootstrapData));
// const bootstrapData = JSON.parse(appContainer.getAttribute('data-bootstrap'));
// const initState = Object.assign({}, getInitialState(bootstrapData));
const initState = {
dashboard: testLayout,
};

const store = createStore(
rootReducer, initState, compose(applyMiddleware(thunk), initEnhancer(false)));
rootReducer,
initState,
compose(
applyMiddleware(thunk),
initEnhancer(false),
),
);

ReactDOM.render(
<Provider store={store}>
<DashboardContainer />
</Provider>,
appContainer,
);

29 changes: 29 additions & 0 deletions superset/assets/javascripts/dashboard/v2/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"rules": {
"prefer-template": 2,
"new-cap": 2,
"no-restricted-syntax": 2,
"guard-for-in": 2,
"prefer-arrow-callback": 2,
"func-names": 2,
"react/jsx-no-bind": 2,
"no-confusing-arrow": 2,
"jsx-a11y/no-static-element-interactions": 2,
"jsx-a11y/anchor-has-content": 2,
"react/require-default-props": 2,
"no-plusplus": 2,
"no-mixed-operators": 2,
"no-continue": 2,
"no-bitwise": 2,
"no-undef": 2,
"no-multi-assign": 2,
"no-restricted-properties": 2,
"no-prototype-builtins": 2,
"jsx-a11y/href-no-hash": 2,
"class-methods-use-this": 2,
"import/no-named-as-default": 2,
"import/prefer-default-export": 2,
"react/no-unescaped-entities": 2,
"react/no-string-refs": 2,
}
}
69 changes: 69 additions & 0 deletions superset/assets/javascripts/dashboard/v2/actions/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
export const UPDATE_COMPONENTS = 'UPDATE_COMPONENTS';
export function updateComponents(nextComponents) {
return {
type: UPDATE_COMPONENTS,
payload: {
nextComponents,
},
};
}

export const DELETE_COMPONENT = 'DELETE_COMPONENT';
export function deleteComponent(id, parentId) {
return {
type: DELETE_COMPONENT,
payload: {
id,
parentId,
},
};
}

export const CREATE_COMPONENT = 'CREATE_COMPONENT';
export function createComponent(dropResult) {
return {
type: CREATE_COMPONENT,
payload: {
dropResult,
},
};
}


// Drag and drop --------------------------------------------------------------
export const MOVE_COMPONENT = 'MOVE_COMPONENT';
export function moveComponent(dropResult) {
return {
type: MOVE_COMPONENT,
payload: {
dropResult,
},
};
}

export const HANDLE_COMPONENT_DROP = 'HANDLE_COMPONENT_DROP';
export function handleComponentDrop(dropResult) {
return (dispatch) => {
if (
dropResult.destination
&& dropResult.source
&& !( // ensure it has moved
dropResult.destination.droppableId === dropResult.source.droppableId
&& dropResult.destination.index === dropResult.source.index
)
) {
return dispatch(moveComponent(dropResult));

// new components don't have a source
} else if (dropResult.destination && !dropResult.source) {
return dispatch(createComponent(dropResult));
}
return null;
};
}

// Resize ---------------------------------------------------------------------

// export function dashboardComponentResizeStart() {}
// export function dashboardComponentResize() {}
// export function dashboardComponentResizeStop() {}
Original file line number Diff line number Diff line change
@@ -1,46 +1,34 @@
import React from 'react';
import PropTypes from 'prop-types';
import { Droppable } from 'react-beautiful-dnd';

import DraggableNewChart from './dnd/DraggableNewChart';
import DraggableNewDivider from './dnd/DraggableNewDivider';
import DraggableNewHeader from './dnd/DraggableNewHeader';
import DraggableNewRow from './dnd/DraggableNewRow';

import { DROPPABLE_NEW_COMPONENT } from '../util/constants';
import NewChart from './gridComponents/new/NewChart';
import NewColumn from './gridComponents/new/NewColumn';
import NewDivider from './gridComponents/new/NewDivider';
import NewHeader from './gridComponents/new/NewHeader';
import NewRow from './gridComponents/new/NewRow';
import NewSpacer from './gridComponents/new/NewSpacer';
import NewTabs from './gridComponents/new/NewTabs';

const propTypes = {
editMode: PropTypes.bool,
};

class BuilderComponentPane extends React.Component {
class BuilderComponentPane extends React.PureComponent {
render() {
return (
<div className="dashboard-builder-sidepane">
<div style={{ fontSize: 16, fontWeight: 700, borderBottom: '1px solid #ccc', padding: 16 }}>
<div className="dashboard-builder-sidepane-header">
Insert components
</div>
<Droppable
droppableId={DROPPABLE_NEW_COMPONENT}
direction="vertical"
isDropDisabled
>
{provided => (
<div
ref={provided.innerRef}
style={{
width: 376,
marginTop: 1,
}}
>
<DraggableNewChart index={0} />
<DraggableNewDivider index={1} />
<DraggableNewHeader index={2} />
<DraggableNewRow index={3} />
{provided.placeholder}
</div>
)}
</Droppable>
<NewChart />
<NewHeader />

<NewDivider />
<NewSpacer />

<NewTabs />
<NewRow />
<NewColumn />
</div>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import PropTypes from 'prop-types';

import DashboardBuilder from './DashboardBuilder';
import StaticDashboard from './StaticDashboard';
import Header from './Header';
import DashboardHeader from './DashboardHeader';

import '../../../../stylesheets/dashboard-v2.css';

Expand All @@ -15,25 +15,30 @@ const propTypes = {
editMode: PropTypes.bool,
};

const defaultProps = {
editMode: true,
};

class Dashboard extends React.Component {
render() {
const { editMode, actions } = this.props;
const { setEditMode, updateDashboardTitle } = actions;
return (
<div className="dashboard-v2">
<Header
editMode={editMode}
<DashboardHeader
editMode={true}
setEditMode={setEditMode}
updateDashboardTitle={updateDashboardTitle}
/>

{editMode ?
{true ?
<DashboardBuilder /> : <StaticDashboard />}
</div>
);
}
}

Dashboard.propTypes = propTypes;
Dashboard.defaultProps = defaultProps;

export default Dashboard;
Loading

0 comments on commit e92d386

Please sign in to comment.