Skip to content

Commit

Permalink
Merge pull request #50 from kuutamol/master
Browse files Browse the repository at this point in the history
Help layer
  • Loading branch information
tanelih committed Jun 4, 2015
2 parents 66e1ea6 + 263f6a8 commit 156c388
Show file tree
Hide file tree
Showing 16 changed files with 666 additions and 36 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"react-tween-state": "0.0.4",
"socket.io-client": "1.3.3",
"superagent": "1.1.0",
"utf8": "2.1.0"
"utf8": "2.1.0",
"nuka-carousel": "0.0.12"
},
"devDependencies": {
"babel-eslint": "2.0.2",
Expand Down
2 changes: 1 addition & 1 deletion src/scripts/components/board-preview.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ export default React.createClass({

showDialog(dialog) {
if(!this.props.board.id.startsWith('dirty_')) {
this.setState({[`show${dialog}`]: !this.state[`show${dialog}`]});
this.setState({ [`show${dialog}`]: !this.state[`show${dialog}`] });
}
},

Expand Down
25 changes: 12 additions & 13 deletions src/scripts/components/dialog/edit-board.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,9 @@ export default React.createClass({
id: this.props.board.id,
name: this.state.name,
background: this.state.background,
customBackground: this.state.customBackground,
customBackground: this.state.customBackground
}


if (!isNaN(size.width) && !isNaN(size.height)) {
if (size.width < 1 || size.height < 1) {
size.width = this.props.board.size.width;
Expand Down Expand Up @@ -121,11 +120,11 @@ export default React.createClass({
<section className="dialog-size">
<label htmlFor="board-width">Width</label>
<input name="board-width"
placeholder="Board Width"
valueLink={widthValueLink}
type="number"
max="99"
min="1" />
placeholder="Board Width"
valueLink={widthValueLink}
type="number"
max="99"
min="1" />
</section>

<section className="times-wrapper">
Expand All @@ -135,13 +134,13 @@ export default React.createClass({
<section className="dialog-size">
<label htmlFor="board-height">Height</label>
<input name="board-height"
placeholder="Board Height"
valueLink={heightValueLink}
type="number"
max="99"
min="1" />
placeholder="Board Height"
valueLink={heightValueLink}
type="number"
max="99"
min="1" />
</section>
</section>
</section>

</section>
<section className="dialog-footer">
Expand Down
22 changes: 17 additions & 5 deletions src/scripts/components/dialog/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@ import Hammer from 'hammerjs';
*/
export default React.createClass({
mixins: [ React.addons.PureRenderMixin ],

//Since this component is used for the infolayer, infoView is true while it
//is active and dictates whether a form gets rendered within the dialog
//or not.
propTypes: {
infoView: React.PropTypes.bool,
className: React.PropTypes.string,
onDismiss: React.PropTypes.func
},

getDefaultProps() {
return {
className: '',
infoView: false,
onDismiss: () => {}
}
},
Expand Down Expand Up @@ -58,12 +62,20 @@ export default React.createClass({
},

renderDialog() {
let form = !this.props.infoView ?
<form className={`dialog ${this.props.className}`}
onSubmit={this.onSubmit}>
{this.props.children}
</form> :
<div className={`${this.props.className}`}
onSubmit={this.onSubmit}>
{this.props.children}
</div>
;

return (
<div className="dialog-overlay">
<form className={`dialog ${this.props.className}`}
onSubmit={this.onSubmit}>
{this.props.children}
</form>
{form}
</div>
);
}
Expand Down
51 changes: 51 additions & 0 deletions src/scripts/components/dialog/text-box.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import React from 'react';

/**
*
*/
// This is the textbox used in the infolayer.
const SingleBox = React.createClass({
propTypes: {
content: React.PropTypes.string,
className: React.PropTypes.string
},

getDefaultProps() {
return {
content: 'Content',
className: ''
}
},

render() {
return (
<div className={`pos ${this.props.className}`}>
<p>{this.props.content}</p>
</div>
);
}
});

// The objects other than textboxes to be shown in the infolayer and
// the instances of SingleBoxes are passed here as props and mapped
export default React.createClass({
propTypes: {
items: React.PropTypes.array,
objects: React.PropTypes.array
},

getDefaultProps() {
return { items: [ ], objects: [ ] }
},

render() {
return (
<div className="infospace">
{this.props.objects}
{this.props.items.map((item, index) => {
return <SingleBox key={index} {...item} />;
})}
</div>
);
}
});
111 changes: 111 additions & 0 deletions src/scripts/components/dialog/view-info.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
import React from 'react/addons';
import Carousel from 'nuka-carousel';
import Dialog from '../../components/dialog';
import TextBoxes from './text-box';
import Dropdown from '../dropdown';

/**
*
*/

export default React.createClass({
mixins: [ Carousel.ControllerMixin ],
getInitialState(){
return { currentSlide: null }
},

componentDidMount() {
this.el = document.getElementById('application');
this.el.className = 'info-view-active';
this.avatar = document.getElementById('avatar');
},

componentWillUnmount() {
this.el.className = '';
},

componentDidUpdate(){
this.el.className =
`info-view-active slide-${this.state.carousels.carousel.state.currentSlide}`;
},

render() {
let dropitems = [
{ icon: 'user', content: 'Profile' },
{ icon: 'language', content: 'Localization' },
{ icon: 'bullhorn', content: 'Feedback' },
{ icon: 'sign-out', content: 'Logout' }
];

/*
Second layer arrays represent the slides. First one of the
third layer arrays contain anything other than textbox-components
while the second ones contain the textboxes' props.
*/
let objects = [
[
[ <Dropdown className='infodrop' show={true} items={dropitems} /> ],
[
{ content: 'Return to workspace', className: 'pos-back' },
{ content: 'Edit board', className:'pos-edit' },
{ content: 'Share board', className:'pos-share' },
{ content: 'Export board', className:'pos-export' },
{ content: 'Make tickets snap to grid', className:'pos-magnet' },
{ content: 'Toggle board overview and navigate', className:'pos-minimap' },
{ content: 'Edit your profile', className:'pos-profile' },
{ content: 'Change operating language', className:'pos-localization' },
{ content: 'Send feedback to developers', className:'pos-feedback' },
{ content: 'Logout', className:'pos-logout' }
]
],
[
[ <img draggable="false" className="imgTicket" src="/dist/assets/img/ticket.png"/>,
<img draggable="false" className="imgEditTicket" src="/dist/assets/img/edit-ticket.png"/> ],
[
{ content: 'Double tap board to create a ticket.', className: 'pos-click' },
{ content: 'Double tap a ticket to edit it.', className:'pos-ticket' },
{ content: 'Select a color for your ticket.', className:'pos-color' },
{ content: 'Edit the contents of a ticket.', className:'pos-content' }
]
],
[
[ <img draggable="false" className="imgInfo" src="/dist/assets/img/edit-board.png"/> ],
[
{ content: 'Create or edit the name of this board.', className: 'pos-boardname' },
{ content: 'Board preview.', className:'pos-boardpreview' },
{ content: 'Edit the background appearance of this board.', className:'pos-boardbg' },
{ content: 'Change the size of this board.', className:'pos-boardmeasures' }
]
],
[
[ <img draggable="false" className="imgInfo" src="/dist/assets/img/share-board.png"/> ],
[
{ content: 'Hit Share to get the URL of this board for sharing.', className: 'pos-format' }
]
],
[
[ <img draggable="false" className="imgInfo" src="/dist/assets/img/export-board.png"/> ],
[
{ content: 'Select an export format and hit Export to download the file.', className: 'pos-format' }
]
]
];

return (
<Dialog className="info" infoView={true}
onDismiss={this.props.onDismiss}>
<Carousel ref="carousel" className="infocarousel"
data={this.setCarouselData.bind(this, 'carousel')}>

{objects.map((item) => {
return (
<div>
<TextBoxes items={item[1]} objects={item[0]}/>
</div>
);
})}
</Carousel>
</Dialog>
);
}
});
5 changes: 3 additions & 2 deletions src/scripts/components/dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ const DropdownItem = React.createClass({
export default React.createClass({
propTypes: {
show: React.PropTypes.bool.isRequired,
items: React.PropTypes.array
items: React.PropTypes.array,
className: React.PropTypes.string
},

getDefaultProps() {
Expand All @@ -53,7 +54,7 @@ export default React.createClass({

render() {
return !this.props.show ? null : (
<ul className="dropdown">
<ul className={`dropdown ${this.props.className}`}>
{this.props.items.map((item, index) => {
return <DropdownItem key={index} {...item} />;
})}
Expand Down
49 changes: 44 additions & 5 deletions src/scripts/components/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,20 @@ import BroadcastAction from '../actions/broadcast';

import Dropdown from '../components/dropdown';
import UserVoice from '../components/user-voice';
import InfoView from './dialog/view-info';

/**
*
*/
export default React.createClass({
propTypes: {
title: React.PropTypes.string.isRequired
title: React.PropTypes.string.isRequired,
showHelp: React.PropTypes.bool
},

getInitialState() {
return { dropdown: false, feedback: false }
},
return { dropdown: false, feedback: false, infoActive: false }
},

showWorkspace() {
return page.show('/boards');
Expand All @@ -27,8 +29,42 @@ export default React.createClass({
toggleDropdown() {
this.setState({ dropdown: !this.state.dropdown });
},
toggleInfoView() {
this.setState({ infoActive: !this.state.infoActive });
},

render: function() {
let infoDialog = null;
let activeClick = null;
let infoIcon = null;

if(!this.state.infoActive) {
infoIcon = 'info';
infoDialog = null;
activeClick = this.toggleDropdown;
} else {
infoIcon = 'times';
infoDialog = <InfoView onDismiss = { this.toggleInfoView} />;
activeClick = () => {};
}

let infoButtonClass =
React.addons.classSet({
infobutton: true,
active: this.state.infoActive
});
let userButtonClass =
React.addons.classSet({
avatar: true,
active: this.state.dropdown
});

let showInfo = !this.props.showHelp ? null : (
<div onClick={this.toggleInfoView} className={infoButtonClass}>
<span className={`fa fa-fw fa-${infoIcon}`}></span>
</div>
);

let items = [
{ icon: 'user', content: 'Profile', disabled: true },
{ icon: 'language', content: 'Localization', disabled: true },
Expand All @@ -54,15 +90,18 @@ export default React.createClass({
}
];
return (
<nav className="nav">
<nav id="nav" className="nav">
<img className="logo" src="/dist/assets/img/logo.svg"
onClick={this.showWorkspace} />
<h1 className="title">{this.props.title}</h1>
<div className="avatar" onClick={this.toggleDropdown}>
{showInfo}
<div id="avatar" onClick={activeClick} className={userButtonClass}>
<span className="fa fa-fw fa-user"></span>
</div>
<Dropdown show={this.state.dropdown} items={items} />
{infoDialog}
</nav>

);
}
});
Loading

0 comments on commit 156c388

Please sign in to comment.