diff --git a/src/views/preview/l10n.json b/src/views/preview/l10n.json
index 7f0e429e1..eb29ba620 100644
--- a/src/views/preview/l10n.json
+++ b/src/views/preview/l10n.json
@@ -21,5 +21,8 @@
"project.instructionsLabel": "Instructions",
"project.notesAndCreditsLabel": "Notes and Credits",
"project.credit": "Thanks to {userLink} for the original project {projectLink}.",
- "project.deletedBanner": "Note: This project is in the trash folder"
+ "project.deletedBanner": "Note: This project is in the trash folder",
+ "project.moderationInfoLabel": "Moderation Info",
+ "project.numScripts": "{number} scripts",
+ "project.numSprites": "{number} sprites"
}
diff --git a/src/views/preview/mod-info.jsx b/src/views/preview/mod-info.jsx
new file mode 100644
index 000000000..2d0d4bbb1
--- /dev/null
+++ b/src/views/preview/mod-info.jsx
@@ -0,0 +1,58 @@
+const PropTypes = require('prop-types');
+const React = require('react');
+const FormattedDate = require('react-intl').FormattedDate;
+const FormattedMessage = require('react-intl').FormattedMessage;
+const FormattedTime = require('react-intl').FormattedTime;
+
+const FlexRow = require('../../components/flex-row/flex-row.jsx');
+
+require('./mod-info.scss');
+
+const ModInfo = props => (
+
+
+ {/* eslint-disable react/jsx-sort-props */}
+ {props.revisedDate &&
+
+
+ {' - '}
+
+
+ }
+ {/* eslint-enable react/jsx-sort-props */}
+
+
+
+
+
+
+
+);
+
+ModInfo.propTypes = {
+ revisedDate: PropTypes.string,
+ scripts: PropTypes.number,
+ sprites: PropTypes.number
+};
+
+module.exports = ModInfo;
diff --git a/src/views/preview/mod-info.scss b/src/views/preview/mod-info.scss
new file mode 100644
index 000000000..e96a1a2c6
--- /dev/null
+++ b/src/views/preview/mod-info.scss
@@ -0,0 +1,64 @@
+@import "../../frameless";
+
+.mod-info {
+ line-height: 2rem;
+ justify-content: flex-start;
+
+ @media #{$medium-and-smaller} {
+ margin: 0;
+ width: 100%;
+ justify-content: center;
+ flex-direction: row;
+ }
+
+ & > div {
+ @media #{$medium-and-smaller} {
+ padding: 0 1rem;
+ }
+ }
+}
+
+.mod-date,
+.mod-sprites,
+.mod-scripts {
+
+ display: inline;
+ padding-right: 2rem;
+ font-size: .875rem;
+
+ &:before {
+ display: inline-block;
+ margin-right: .5rem;
+ background-repeat: no-repeat;
+ background-position: center center;
+ background-size: contain;
+ width: 1.5rem;
+ height: 1.5rem;
+ vertical-align: -.35rem;
+ content: "";
+ }
+}
+
+.mod-date {
+
+ &:before {
+ opacity: .5;
+ background-image: url("/svgs/project/last-revised.svg");
+ }
+}
+
+.mod-sprites {
+
+ &:before {
+ opacity: .5;
+ background-image: url("/svgs/project/sprite-count.svg");
+ }
+}
+
+.mod-scripts {
+
+ &:before {
+ opacity: .5;
+ background-image: url("/svgs/project/block-count.svg");
+ }
+}
diff --git a/src/views/preview/presentation.jsx b/src/views/preview/presentation.jsx
index 907f5f2d9..6f20b36d4 100644
--- a/src/views/preview/presentation.jsx
+++ b/src/views/preview/presentation.jsx
@@ -16,6 +16,7 @@ const FlexRow = require('../../components/flex-row/flex-row.jsx');
const Button = require('../../components/forms/button.jsx');
const Avatar = require('../../components/avatar/avatar.jsx');
const Banner = require('./banner.jsx');
+const ModInfo = require('./mod-info.jsx');
const RemixCredit = require('./remix-credit.jsx');
const RemixList = require('./remix-list.jsx');
const Stats = require('./stats.jsx');
@@ -65,6 +66,7 @@ const PreviewPresentation = ({
isShared,
loveCount,
loved,
+ modInfo,
moreCommentsToLoad,
onAddComment,
onAddToStudioClicked,
@@ -96,11 +98,13 @@ const PreviewPresentation = ({
remixes,
replies,
reportOpen,
+ showModInfo,
singleCommentId,
userOwnsProject,
visibilityInfo
}) => {
const shareDate = ((projectInfo.history && projectInfo.history.shared)) ? projectInfo.history.shared : '';
+ const revisedDate = ((projectInfo.history && projectInfo.history.modified)) ? projectInfo.history.modified : '';
// Allow embedding html in banner messages coming from the server
const embedCensorMessage = message => (
@@ -376,6 +380,21 @@ const PreviewPresentation = ({
/>
+ {showModInfo &&
+
+
+
+
+
+
+
+ }
+
+
@@ -512,6 +531,10 @@ PreviewPresentation.propTypes = {
isShared: PropTypes.bool,
loveCount: PropTypes.number,
loved: PropTypes.bool,
+ modInfo: PropTypes.shape({
+ scripts: PropTypes.number,
+ sprites: PropTypes.number
+ }),
moreCommentsToLoad: PropTypes.bool,
onAddComment: PropTypes.func,
onAddToStudioClicked: PropTypes.func,
@@ -543,6 +566,7 @@ PreviewPresentation.propTypes = {
remixes: PropTypes.arrayOf(PropTypes.object),
replies: PropTypes.objectOf(PropTypes.array),
reportOpen: PropTypes.bool,
+ showModInfo: PropTypes.bool,
singleCommentId: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]),
userOwnsProject: PropTypes.bool,
visibilityInfo: PropTypes.shape({
diff --git a/src/views/preview/project-view.jsx b/src/views/preview/project-view.jsx
index cc70c42fc..b5df885de 100644
--- a/src/views/preview/project-view.jsx
+++ b/src/views/preview/project-view.jsx
@@ -82,6 +82,10 @@ class Preview extends React.Component {
extensions: [],
favoriteCount: 0,
loveCount: 0,
+ modInfo: {
+ scripts: 0,
+ sprites: 0
+ },
projectId: parts[1] === 'editor' ? '0' : parts[1],
reportOpen: false,
singleCommentId: singleCommentId
@@ -96,7 +100,7 @@ class Preview extends React.Component {
this.props.sessionStatus === sessionActions.Status.FETCHED) ||
(this.state.projectId !== prevState.projectId))) {
this.fetchCommunityData();
- this.getExtensions(this.state.projectId);
+ this.getProjectData(this.state.projectId);
}
if (this.state.projectId === '0' && this.state.projectId !== prevState.projectId) {
this.props.resetProject();
@@ -175,7 +179,7 @@ class Preview extends React.Component {
}
}
}
- getExtensions (projectId) {
+ getProjectData (projectId) {
if (projectId > 0) {
storage
.load(storage.AssetType.Project, projectId, storage.DataFormat.JSON)
@@ -205,14 +209,29 @@ class Preview extends React.Component {
}
});
}
+ const sprites = projectData[0].targets.length - 1; // don't count stage
+ const scripts = projectData[0].targets
+ .map(target =>
+ Object.values(target.blocks)
+ .filter(block => block.topLevel).length
+ )
+ .reduce((accumulator, currentVal) => accumulator + currentVal, 0);
this.setState({
- extensions: Array.from(extensionSet)
+ extensions: Array.from(extensionSet),
+ modInfo: {
+ scripts: scripts,
+ sprites: sprites
+ }
});
});
});
} else { // projectId is default or invalid; empty the extensions array
this.setState({
- extensions: []
+ extensions: [],
+ modInfo: {
+ scripts: 0,
+ sprites: 0
+ }
});
}
}
@@ -454,6 +473,7 @@ class Preview extends React.Component {
isShared={this.props.isShared}
loveCount={this.state.loveCount}
loved={this.props.loved}
+ modInfo={this.state.modInfo}
moreCommentsToLoad={this.props.moreCommentsToLoad}
originalInfo={this.props.original}
parentInfo={this.props.parent}
@@ -464,6 +484,7 @@ class Preview extends React.Component {
remixes={this.props.remixes}
replies={this.props.replies}
reportOpen={this.state.reportOpen}
+ showModInfo={this.props.isAdmin}
singleCommentId={this.state.singleCommentId}
userOwnsProject={this.props.userOwnsProject}
visibilityInfo={this.props.visibilityInfo}
diff --git a/static/svgs/project/block-count.svg b/static/svgs/project/block-count.svg
new file mode 100644
index 000000000..8d1ca6bfd
--- /dev/null
+++ b/static/svgs/project/block-count.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/static/svgs/project/last-revised.svg b/static/svgs/project/last-revised.svg
new file mode 100644
index 000000000..e760cf814
--- /dev/null
+++ b/static/svgs/project/last-revised.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file
diff --git a/static/svgs/project/sprite-count.svg b/static/svgs/project/sprite-count.svg
new file mode 100644
index 000000000..989b06509
--- /dev/null
+++ b/static/svgs/project/sprite-count.svg
@@ -0,0 +1,18 @@
+
+
\ No newline at end of file