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;