From e7fa7c8bf09616eddc4e8678f0926affb1ecf655 Mon Sep 17 00:00:00 2001 From: Caley Brock Date: Wed, 9 Aug 2017 14:35:11 -0700 Subject: [PATCH 1/5] Create new project action component --- .../templates/projects/ProjectActionBox.jsx | 68 +++++++++++++++++++ .../projects/ProjectActionBox.story.jsx | 24 +++++++ 2 files changed, 92 insertions(+) create mode 100644 apps/src/templates/projects/ProjectActionBox.jsx create mode 100644 apps/src/templates/projects/ProjectActionBox.story.jsx diff --git a/apps/src/templates/projects/ProjectActionBox.jsx b/apps/src/templates/projects/ProjectActionBox.jsx new file mode 100644 index 0000000000000..a689f16309957 --- /dev/null +++ b/apps/src/templates/projects/ProjectActionBox.jsx @@ -0,0 +1,68 @@ +import React, {Component, PropTypes} from 'react'; +import i18n from '@cdo/locale'; +import color from "../../util/color"; +import FontAwesome from '../FontAwesome'; + +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' + } +}; + +export default class ProjectActionBox extends Component { + static propTypes = { + projectData: PropTypes.object + }; + + getAvailableActions = function () { + let actions = [i18n.rename(), i18n.remix()]; + this.props.projectData.isPublished ? + actions.push(i18n.removeFromPublicGallery()) : actions.push(i18n.publishToPublicGallery()); + return actions; + }; + + render() { + return ( +
+ {(this.getAvailableActions()).map((action, index) => ( +
+ {action} +
+ ))} +
+ + {i18n.deleteProject()} +
+
+ ); + } +} diff --git a/apps/src/templates/projects/ProjectActionBox.story.jsx b/apps/src/templates/projects/ProjectActionBox.story.jsx new file mode 100644 index 0000000000000..ed2a55585c61b --- /dev/null +++ b/apps/src/templates/projects/ProjectActionBox.story.jsx @@ -0,0 +1,24 @@ +import React from 'react'; +import ProjectActionBox from './ProjectActionBox'; +import {stubFakePersonalProjectData} from './generateFakePersonalProjects'; + +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: () => ( + + ) + }, + ]); + }; From 3c5ed44878b6457a7cd96d5d42c4f1d053ac41f6 Mon Sep 17 00:00:00 2001 From: Caley Brock Date: Wed, 9 Aug 2017 16:16:20 -0700 Subject: [PATCH 2/5] Use new action box in cards --- .../templates/projects/ProjectActionBox.jsx | 12 ++-- .../projects/ProjectActionBox.story.jsx | 9 ++- apps/src/templates/projects/ProjectCard.jsx | 60 +++---------------- 3 files changed, 21 insertions(+), 60 deletions(-) diff --git a/apps/src/templates/projects/ProjectActionBox.jsx b/apps/src/templates/projects/ProjectActionBox.jsx index a689f16309957..7ea6375bd4089 100644 --- a/apps/src/templates/projects/ProjectActionBox.jsx +++ b/apps/src/templates/projects/ProjectActionBox.jsx @@ -2,6 +2,7 @@ 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: { @@ -38,21 +39,22 @@ const styles = { } }; -export default class ProjectActionBox extends Component { +class ProjectActionBox extends Component { static propTypes = { - projectData: PropTypes.object + isPublished: PropTypes.bool, + style: PropTypes.object }; getAvailableActions = function () { let actions = [i18n.rename(), i18n.remix()]; - this.props.projectData.isPublished ? + this.props.isPublished ? actions.push(i18n.removeFromPublicGallery()) : actions.push(i18n.publishToPublicGallery()); return actions; }; render() { return ( -
+
{(this.getAvailableActions()).map((action, index) => (
{action} @@ -66,3 +68,5 @@ export default class ProjectActionBox extends Component { ); } } + +export default Radium(ProjectActionBox); diff --git a/apps/src/templates/projects/ProjectActionBox.story.jsx b/apps/src/templates/projects/ProjectActionBox.story.jsx index ed2a55585c61b..79fa046fe3880 100644 --- a/apps/src/templates/projects/ProjectActionBox.story.jsx +++ b/apps/src/templates/projects/ProjectActionBox.story.jsx @@ -1,6 +1,5 @@ import React from 'react'; import ProjectActionBox from './ProjectActionBox'; -import {stubFakePersonalProjectData} from './generateFakePersonalProjects'; export default storybook => { storybook @@ -10,14 +9,18 @@ export default storybook => { 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..f03d65c627065 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,28 +76,6 @@ 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 }, @@ -177,36 +156,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 +218,12 @@ const ProjectCard = React.createClass({ }
- {this.renderActionBox(this.checkIfPublished())} + {this.state.actionsOpen && + + }
); From b07dd22e7314b06942c867e68fb246d11f38a915 Mon Sep 17 00:00:00 2001 From: Caley Brock Date: Thu, 10 Aug 2017 11:13:22 -0700 Subject: [PATCH 3/5] Add quick actions box to table --- .../projects/PersonalProjectsTable.jsx | 15 ++-- .../templates/projects/QuickActionsCell.jsx | 80 +++++++++++++++++++ 2 files changed, 86 insertions(+), 9 deletions(-) create mode 100644 apps/src/templates/projects/QuickActionsCell.jsx 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/QuickActionsCell.jsx b/apps/src/templates/projects/QuickActionsCell.jsx new file mode 100644 index 0000000000000..adef4069e331b --- /dev/null +++ b/apps/src/templates/projects/QuickActionsCell.jsx @@ -0,0 +1,80 @@ +import React, {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' + } +}; + +//to do - style it to always be in the center +const QuickActionsCell = React.createClass({ + propTypes: { + projectData: PropTypes.object + }, + + getInitialState() { + return {actionsOpen: false}; + }, + + toggleActionBox(event) { + if (!this.state.actionsOpen) { + this.minimizeOnClickAnywhere(); + } + this.setState({actionsOpen: !this.state.actionsOpen}); + }, + + minimizeOnClickAnywhere: function (event) { + // The first time we click anywhere, hide any open children + $(document.body).one('click', function (event) { + if (event.target === this.refs.actionBox) { + return; + } + this.setState({ + actionsOpen: false + }); + }.bind(this)); + }, + + render() { + const selectedStyle = this.state.actionsOpen ? styles.selected : styles.nonSelected; + return ( +
+
{ this.icon = icon; }} + > + +
+ {this.state.actionsOpen && + { this.actionBox = actionBox; }} + /> + } +
+ ); + } +}); + +export default QuickActionsCell; From f94ab59cc0ae6f047c7b050bed88aa88b129a4d6 Mon Sep 17 00:00:00 2001 From: Caley Brock Date: Thu, 10 Aug 2017 13:08:54 -0700 Subject: [PATCH 4/5] Convert to ES6 component --- .../templates/projects/QuickActionsCell.jsx | 29 ++++++++----------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/apps/src/templates/projects/QuickActionsCell.jsx b/apps/src/templates/projects/QuickActionsCell.jsx index adef4069e331b..93a73ca5b9ebe 100644 --- a/apps/src/templates/projects/QuickActionsCell.jsx +++ b/apps/src/templates/projects/QuickActionsCell.jsx @@ -1,4 +1,4 @@ -import React, {PropTypes} from 'react'; +import React, {Component, PropTypes} from 'react'; import FontAwesome from '@cdo/apps/templates/FontAwesome'; import color from "../../util/color"; import ProjectActionBox from './ProjectActionBox'; @@ -26,34 +26,28 @@ const styles = { } }; -//to do - style it to always be in the center -const QuickActionsCell = React.createClass({ - propTypes: { +class QuickActionsCell extends Component { + static propTypes = { projectData: PropTypes.object - }, + }; - getInitialState() { - return {actionsOpen: false}; - }, + state = {actionsOpen: false}; - toggleActionBox(event) { + toggleActionBox = (event) => { if (!this.state.actionsOpen) { this.minimizeOnClickAnywhere(); } this.setState({actionsOpen: !this.state.actionsOpen}); - }, + }; - minimizeOnClickAnywhere: function (event) { + minimizeOnClickAnywhere = (event) => { // The first time we click anywhere, hide any open children $(document.body).one('click', function (event) { - if (event.target === this.refs.actionBox) { - return; - } this.setState({ actionsOpen: false }); }.bind(this)); - }, + }; render() { const selectedStyle = this.state.actionsOpen ? styles.selected : styles.nonSelected; @@ -62,8 +56,9 @@ const QuickActionsCell = React.createClass({
{ this.icon = icon; }} + onClick={this.toggleActionBox} > - +
{this.state.actionsOpen && ); } -}); +} export default QuickActionsCell; From c4f0815e0f1ab60fec0538d620a7a3e2a7889133 Mon Sep 17 00:00:00 2001 From: Caley Brock Date: Fri, 11 Aug 2017 14:31:50 -0700 Subject: [PATCH 5/5] Code review feedback --- apps/src/templates/projects/ProjectActionBox.jsx | 9 +++++---- apps/src/templates/projects/ProjectCard.jsx | 7 ++++++- apps/src/templates/projects/QuickActionsCell.jsx | 8 ++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/apps/src/templates/projects/ProjectActionBox.jsx b/apps/src/templates/projects/ProjectActionBox.jsx index 7ea6375bd4089..750ee8d493dc4 100644 --- a/apps/src/templates/projects/ProjectActionBox.jsx +++ b/apps/src/templates/projects/ProjectActionBox.jsx @@ -46,10 +46,11 @@ class ProjectActionBox extends Component { }; getAvailableActions = function () { - let actions = [i18n.rename(), i18n.remix()]; - this.props.isPublished ? - actions.push(i18n.removeFromPublicGallery()) : actions.push(i18n.publishToPublicGallery()); - return actions; + return [ + i18n.rename(), + i18n.remix(), + this.props.isPublished ? i18n.removeFromPublicGallery() : i18n.publishToPublicGallery() + ]; }; render() { diff --git a/apps/src/templates/projects/ProjectCard.jsx b/apps/src/templates/projects/ProjectCard.jsx index f03d65c627065..4628728f43119 100644 --- a/apps/src/templates/projects/ProjectCard.jsx +++ b/apps/src/templates/projects/ProjectCard.jsx @@ -81,6 +81,11 @@ const styles = { }, bold: { fontFamily: '"Gotham 5r", sans-serif' + }, + actionBox: { + position: 'absolute', + marginLeft: 10, + marginTop: -10 } }; @@ -221,7 +226,7 @@ const ProjectCard = React.createClass({ {this.state.actionsOpen && } diff --git a/apps/src/templates/projects/QuickActionsCell.jsx b/apps/src/templates/projects/QuickActionsCell.jsx index 93a73ca5b9ebe..d9edf1ded10a3 100644 --- a/apps/src/templates/projects/QuickActionsCell.jsx +++ b/apps/src/templates/projects/QuickActionsCell.jsx @@ -42,11 +42,11 @@ class QuickActionsCell extends Component { minimizeOnClickAnywhere = (event) => { // The first time we click anywhere, hide any open children - $(document.body).one('click', function (event) { + $(document.body).one('click', (event) => { this.setState({ actionsOpen: false }); - }.bind(this)); + }); }; render() { @@ -55,7 +55,7 @@ class QuickActionsCell extends Component {
{ this.icon = icon; }} + ref={icon => this.icon = icon} onClick={this.toggleActionBox} > @@ -64,7 +64,7 @@ class QuickActionsCell extends Component { { this.actionBox = actionBox; }} + ref={actionBox => this.actionBox = actionBox} /> }