Skip to content

Commit

Permalink
Merge pull request #16994 from code-dot-org/projects-quick-actions
Browse files Browse the repository at this point in the history
Project Table : add quick actions box
  • Loading branch information
caleybrock committed Aug 14, 2017
2 parents 581a285 + c4f0815 commit 844bad7
Show file tree
Hide file tree
Showing 5 changed files with 193 additions and 62 deletions.
15 changes: 6 additions & 9 deletions apps/src/templates/projects/PersonalProjectsTable.jsx
Expand Up @@ -7,6 +7,7 @@ import {Table, sort} from 'reactabular';
import wrappedSortable from '../tables/wrapped_sortable';
import orderBy from 'lodash/orderBy';
import {PROJECT_TYPE_MAP, personalProjectDataPropType} from './projectConstants';
import QuickActionsCell from './QuickActionsCell';

const PROJECT_DEFAULT_IMAGE = '/blockly/media/projects/project_default.png';

Expand Down Expand Up @@ -71,9 +72,6 @@ const styles = {
cellIsPublished: {
textAlign: 'center'
},
cellAction: {
textAlign: 'center'
},
thumbnailWrapper: {
height: THUMBNAIL_SIZE,
display: 'flex',
Expand Down Expand Up @@ -107,8 +105,10 @@ const isPublishedFormatter = function (isPublished) {
return isPublished ? (<FontAwesome icon="circle"/>) : '';
};

const actionsFormatter = function () {
return (<FontAwesome icon="angle-down"/>);
const actionsFormatter = function (actions, {rowData}) {
return (
<QuickActionsCell projectData={rowData} />
);
};

const dateFormatter = function (time) {
Expand Down Expand Up @@ -241,10 +241,7 @@ const PersonalProjectsTable = React.createClass({
},
cell: {
format: actionsFormatter,
props: {style: {
...styles.cell,
...styles.cellAction
}}
props: {style: styles.cell}
}
}
];
Expand Down
73 changes: 73 additions & 0 deletions apps/src/templates/projects/ProjectActionBox.jsx
@@ -0,0 +1,73 @@
import React, {Component, PropTypes} from 'react';
import i18n from '@cdo/locale';
import color from "../../util/color";
import FontAwesome from '../FontAwesome';
import Radium from 'radium';

const styles = {
arrowIcon: {
paddingRight: 8
},
actionBox: {
width: 180,
paddingLeft: 15,
paddingRight: 15,
border: '1px solid ' + color.lighter_gray,
borderRadius: 2,
backgroundColor: color.white,
boxShadow: "2px 2px 2px " + color.light_gray,
marginTop: 5,
},
actionText: {
fontSize: 14,
fontFamily: '"Gotham", sans-serif',
color: color.charcoal,
padding: '12px 0px 2px 0px',
},
delete: {
color: color.red,
borderTop: '1px solid ' + color.lighter_gray,
marginTop: 8,
padding: '10px 0px 10px 0px',
fontSize: 14,
},
xIcon: {
paddingRight: 5
},
bold: {
fontFamily: '"Gotham 5r", sans-serif'
}
};

class ProjectActionBox extends Component {
static propTypes = {
isPublished: PropTypes.bool,
style: PropTypes.object
};

getAvailableActions = function () {
return [
i18n.rename(),
i18n.remix(),
this.props.isPublished ? i18n.removeFromPublicGallery() : i18n.publishToPublicGallery()
];
};

render() {
return (
<div style={[styles.actionBox, this.props.style]}>
{(this.getAvailableActions()).map((action, index) => (
<div key={index} style={styles.actionText}>
{action}
</div>
))}
<div style={styles.delete}>
<FontAwesome icon=" fa-times-circle" style={styles.xIcon}/>
{i18n.deleteProject()}
</div>
</div>
);
}
}

export default Radium(ProjectActionBox);
27 changes: 27 additions & 0 deletions apps/src/templates/projects/ProjectActionBox.story.jsx
@@ -0,0 +1,27 @@
import React from 'react';
import ProjectActionBox from './ProjectActionBox';

export default storybook => {
storybook
.storiesOf('ProjectActionBox', module)
.addStoryTable([
{
name: 'Already published project',
description: 'Personal gallery',
story: () => (
<ProjectActionBox
isPublished={true}
/>
)
},
{
name: 'Not yet published project',
description: 'Personal gallery',
story: () => (
<ProjectActionBox
isPublished={false}
/>
)
},
]);
};
65 changes: 12 additions & 53 deletions apps/src/templates/projects/ProjectCard.jsx
Expand Up @@ -3,6 +3,7 @@ import color from "../../util/color";
import FontAwesome from '../FontAwesome';
import i18n from "@cdo/locale";
import $ from 'jquery';
import ProjectActionBox from './ProjectActionBox';

const PROJECT_DEFAULT_IMAGE = '/blockly/media/projects/project_default.png';

Expand Down Expand Up @@ -75,33 +76,16 @@ const styles = {
minWidth: '100%',
minHeight: '100%'
},
actionBox: {
width: 160,
paddingLeft: 15,
paddingRight: 15,
border: '1px solid #bbbbbb',
borderRadius: 2,
backgroundColor: color.white,
boxShadow: "3px 3px 3px gray",
marginTop: 5,
position: "absolute"
},
actionText: {
fontSize: 11,
fontFamily: '"Gotham", sans-serif',
color: color.gray
},
delete: {
color: color.red,
borderTop: '1px solid lightGray',
paddingTop: 10,
fontSize: 11
},
xIcon: {
paddingRight: 5
},
bold: {
fontFamily: '"Gotham 5r", sans-serif'
},
actionBox: {
position: 'absolute',
marginLeft: 10,
marginTop: -10
}
};

Expand Down Expand Up @@ -177,36 +161,6 @@ const ProjectCard = React.createClass({
this.setState({actionsOpen: !this.state.actionsOpen});
},

checkIfPublished() {
let actions = [i18n.rename(), i18n.remix(), i18n.share()];

this.props.projectData.publishedToClass ?
actions.push(i18n.removeFromClassGallery()) :
actions.push(i18n.publishToClassGallery());

this.props.projectData.publishedToPublic ?
actions.push(i18n.removeFromPublicGallery()) : actions.push(i18n.publishToPublicGallery());
return actions;
},

renderActionBox(actions) {
if (this.state.actionsOpen) {
return (
<div style={styles.actionBox}>
{actions.map((action, index) => (
<h5 key={index} style={styles.actionText}>
{action}
</h5>
))}
<h5 style={styles.delete}>
<FontAwesome icon=" fa-times-circle" style={styles.xIcon}/>
{i18n.deleteProject()}
</h5>
</div>
);
}
},

renderProjectName(url, name) {
return (
<a style={styles.titleLink} href={url}>
Expand Down Expand Up @@ -269,7 +223,12 @@ const ProjectCard = React.createClass({
}
</div>

{this.renderActionBox(this.checkIfPublished())}
{this.state.actionsOpen &&
<ProjectActionBox
isPublished={this.props.projectData.publishedToPublic}
style={styles.actionBox}
/>
}

</div>
);
Expand Down
75 changes: 75 additions & 0 deletions apps/src/templates/projects/QuickActionsCell.jsx
@@ -0,0 +1,75 @@
import React, {Component, PropTypes} from 'react';
import FontAwesome from '@cdo/apps/templates/FontAwesome';
import color from "../../util/color";
import ProjectActionBox from './ProjectActionBox';
import $ from 'jquery';

const styles = {
selected: {
backgroundColor: color.lighter_gray,
borderRadius: 3,
padding: 5,
width: 9
},
nonSelected: {
padding: 5,
width: 9
},
actionBox: {
position: 'absolute',
marginTop: 32,
marginLeft: 96
},
cellContainer: {
display: 'flex',
justifyContent: 'center'
}
};

class QuickActionsCell extends Component {
static propTypes = {
projectData: PropTypes.object
};

state = {actionsOpen: false};

toggleActionBox = (event) => {
if (!this.state.actionsOpen) {
this.minimizeOnClickAnywhere();
}
this.setState({actionsOpen: !this.state.actionsOpen});
};

minimizeOnClickAnywhere = (event) => {
// The first time we click anywhere, hide any open children
$(document.body).one('click', (event) => {
this.setState({
actionsOpen: false
});
});
};

render() {
const selectedStyle = this.state.actionsOpen ? styles.selected : styles.nonSelected;
return (
<div style={styles.cellContainer}>
<div
style={selectedStyle}
ref={icon => this.icon = icon}
onClick={this.toggleActionBox}
>
<FontAwesome icon="angle-down" />
</div>
{this.state.actionsOpen &&
<ProjectActionBox
isPublished={this.props.projectData.isPublished}
style={styles.actionBox}
ref={actionBox => this.actionBox = actionBox}
/>
}
</div>
);
}
}

export default QuickActionsCell;

0 comments on commit 844bad7

Please sign in to comment.