atom-lupa
Version:
Navigation bar and breadcrumbs
186 lines (165 loc) • 6.12 kB
JavaScript
"use babel";
import React from 'react';
import ReactDOM from 'react-dom';
import {Structure} from './Structure';
const Path = require('path');
import {StatusBar} from './StatusBar';
const d = document;
const get = require('lodash/get');
const _ = {get};
const NavigationActions = require('../action-creators/NavigationActions');
// TODO move resize logic to separate component/module
const pos = (e, prev) => {
const curr = [e.clientX, e.clientY];
if (!prev) return curr;
return [curr[0] - prev[0], curr[1] - prev[1]];
}
const resizeHandleStyle = {
position: 'absolute',
width: '8px',
right:'-5px',
top: 0,
bottom: 0,
cursor: 'col-resize'
};
//---
function getEntityFromElement(entities, el) {
const name = el.getAttribute('data-lupa-entity-name');
const type = el.getAttribute('data-lupa-entity-type');
const id = el.getAttribute('data-lupa-entity-id');
const loc = {start:{}, end:{}};
loc.start.line = ~~el.getAttribute('data-line');
loc.start.column = ~~el.getAttribute('data-column');
return entities.find(ent => {
return ent.id == id;
return (
ent.name == name &&
ent.type == type &&
_.get(ent, 'loc.start.line') == loc.start.line &&
_.get(ent, 'loc.start.column') == loc.start.column
);
})
}
export class Lupa extends React.Component {
constructor(props) {
super(props);
this.state = {
file: {
metadata: []
},
w: 220,
redButton: 0
}
this.handleDrag = this.handleDrag.bind(this);
}
componentDidMount() {
// TODO move this from here
const dispatch = this.props.dispatch;
this.navigationActions = NavigationActions(dispatch, this.props.editorWrapper);
const navigationActions = this.navigationActions;
this.previewEvents = {
onMouseLeave: () => navigationActions.RemovePreview(true),
onMouseOut: () => navigationActions.RemovePreview(),
onMouseOver: (entity) => navigationActions.SetPreview(entity),
onClick: (e) => navigationActions.GoTo(e, false, {select: e.altKey})
};
window.lupaNavigationActions = navigationActions;
setInterval(() => {
const pos = this.props.activePosition;
const metadata = this.props.metadata;
if (pos) {
const entitiesAtPos = metadata.filter((item) => (
item.loc &&
item.loc.start.line <= (pos.row + 1) &&
item.loc.end.line >= (pos.row + 1)
));
const entities = entitiesAtPos;
const el = <StatusBar {...this.previewEvents}
entities={entities}/>;
ReactDOM.render(el, this.props.breadcrumbsElement);
}
}, 300)
}
componentWillReceiveProps(nextProps) {
}
// TODO move resize logic to separate module/component
handleMouseDown(e) {
this.start = pos(e);
this.w0 = this.state.w;
d.addEventListener('mousemove', this.handleDrag)
d.addEventListener('mouseup', this.handleMouseUp.bind(this))
}
handleMouseUp(e) {
d.removeEventListener('mousemove', this.handleDrag)
}
handleDrag(e) {
const delta = pos(e, this.start);
this.setState({w: Math.max(delta[0] + this.w0, 10) })
}
//----
getStructureEvents(dispatch, metadata) {
const navigationActions = this.navigationActions;
return Object.assign({
onFocus(e) {
const el = e.target;//.closest('.lupa-entity');
if (el.classList.contains('lupa-entity')) {
navigationActions.SetPreview(el);
const entity = getEntityFromElement(metadata, el);
dispatch({
type: 'setActiveEntity',
entity: entity
})
}
},
onBlur(e) {
navigationActions.RemovePreview(true);
},
}, this.previewEvents);
}
render() {
// TODO move resize logic to separate module/component
return <div style={{position: 'relative', width: this.state.w}}>
<div
onMouseDown={this.handleMouseDown.bind(this)}
style={resizeHandleStyle}>
</div>
<button
style={{background: '#b00',
maxHeight: !this.props.indexed? '1000px': '0',
boxShadow: !this.props.indexed? '0 0 3px yellow' : 'none',
transition: '0.7s all',
width: '60%',
margin: '10px',
border: 'none',
overflow: 'hidden',
lineHeight: 1,
padding: !this.props.indexed? '12px 6px': 0,
textTransform: 'none',
textAlign: 'center',
color: 'yellow', borderRadius: 10}}
onClick={()=> {
if (!this.props.indexed) {
this.props.dispatch({
type: 'indexProject'
})
}
//if (this.props.indexed)
this.setState({redButton: this.state.redButton + 1});
}}
className="btn cta lupa-index-project">
{this.props.indexed == 1? <span>🚀 indexing... 🚀{/*Please do not press<br/> this button again.*/}</span> : 'Index project'}
</button>
<Structure
metadata={this.props.metadata}
allMetadata={this.props.allMetadata}
showInfo={this.state.redButton < 2}
{...this.getStructureEvents(this.props.dispatch, this.props.metadata)}
/>
</div>
}
}
Lupa.propTypes = {
editorWrapper: React.PropTypes.shape({
RememberPosition: React.PropTypes.func.isRequired
}).isRequired
}