diff --git a/apps/src/templates/projects/PersonalProjectsTable.jsx b/apps/src/templates/projects/PersonalProjectsTable.jsx index 109cd1f0c221a..3d344354dd28f 100644 --- a/apps/src/templates/projects/PersonalProjectsTable.jsx +++ b/apps/src/templates/projects/PersonalProjectsTable.jsx @@ -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'; @@ -71,9 +72,6 @@ const styles = { cellIsPublished: { textAlign: 'center' }, - cellAction: { - textAlign: 'center' - }, thumbnailWrapper: { height: THUMBNAIL_SIZE, display: 'flex', @@ -107,8 +105,10 @@ const isPublishedFormatter = function (isPublished) { return isPublished ? () : ''; }; -const actionsFormatter = function () { - return (); +const actionsFormatter = function (actions, {rowData}) { + return ( + + ); }; const dateFormatter = function (time) { @@ -241,10 +241,7 @@ const PersonalProjectsTable = React.createClass({ }, cell: { format: actionsFormatter, - props: {style: { - ...styles.cell, - ...styles.cellAction - }} + props: {style: styles.cell} } } ]; diff --git a/apps/src/templates/projects/ProjectActionBox.jsx b/apps/src/templates/projects/ProjectActionBox.jsx new file mode 100644 index 0000000000000..750ee8d493dc4 --- /dev/null +++ b/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 ( +
+ {(this.getAvailableActions()).map((action, index) => ( +
+ {action} +
+ ))} +
+ + {i18n.deleteProject()} +
+
+ ); + } +} + +export default Radium(ProjectActionBox); diff --git a/apps/src/templates/projects/ProjectActionBox.story.jsx b/apps/src/templates/projects/ProjectActionBox.story.jsx new file mode 100644 index 0000000000000..79fa046fe3880 --- /dev/null +++ b/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: () => ( + + ) + }, + { + name: 'Not yet published project', + description: 'Personal gallery', + story: () => ( + + ) + }, + ]); + }; diff --git a/apps/src/templates/projects/ProjectCard.jsx b/apps/src/templates/projects/ProjectCard.jsx index ce17c0cb412bc..4628728f43119 100644 --- a/apps/src/templates/projects/ProjectCard.jsx +++ b/apps/src/templates/projects/ProjectCard.jsx @@ -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'; @@ -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 } }; @@ -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 ( -
- {actions.map((action, index) => ( -
- {action} -
- ))} -
- - {i18n.deleteProject()} -
-
- ); - } - }, - renderProjectName(url, name) { return ( @@ -269,7 +223,12 @@ const ProjectCard = React.createClass({ } - {this.renderActionBox(this.checkIfPublished())} + {this.state.actionsOpen && + + } ); diff --git a/apps/src/templates/projects/QuickActionsCell.jsx b/apps/src/templates/projects/QuickActionsCell.jsx new file mode 100644 index 0000000000000..d9edf1ded10a3 --- /dev/null +++ b/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 ( +
+
this.icon = icon} + onClick={this.toggleActionBox} + > + +
+ {this.state.actionsOpen && + this.actionBox = actionBox} + /> + } +
+ ); + } +} + +export default QuickActionsCell;