Implement GH-1074: Add "coming soon" extensions to the library (#1132)
* Add coming soon extensions to the library This implements #1074 * don’t call `onSelect` when disabled thanks @paulkaplan! * add speech image to coming soon extension
This commit is contained in:
1 parent
1c44dcd969
commit
4743702d66
10 files changed
+95
-7
No files matched your search
@@ -27,6 +27,15 @@
|
||||
border-color: #1dacf4;
|
||||
}
|
||||
|
||||
.disabled {
|
||||
opacity: .5;
|
||||
cursor: auto;
|
||||
}
|
||||
|
||||
.disabled:hover {
|
||||
border-color: #e9eef2;
|
||||
}
|
||||
|
||||
.library-item-image-container-wrapper {
|
||||
height: 100px;
|
||||
width: 100%;
|
||||
@@ -67,6 +76,10 @@
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.featured-image-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.featured-image {
|
||||
width: 100%;
|
||||
}
|
||||
@@ -82,3 +95,15 @@
|
||||
font-weight: normal;
|
||||
line-height: 2;
|
||||
}
|
||||
|
||||
.coming-soon-text {
|
||||
position: absolute;
|
||||
transform: translate(calc(2 * $space), calc(2 * $space));
|
||||
background-color: $data-primary;
|
||||
border-radius: 1rem;
|
||||
box-shadow: 0 0 .5rem hsla(0, 0%, 0%, .25);
|
||||
padding: .5rem 1rem;
|
||||
font-size: .875rem;
|
||||
font-weight: bold;
|
||||
color: #FFF;
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import bindAll from 'lodash.bindall';
|
||||
import {FormattedMessage} from 'react-intl';
|
||||
import PropTypes from 'prop-types';
|
||||
import React from 'react';
|
||||
|
||||
@@ -25,7 +26,9 @@ class LibraryItem extends React.PureComponent {
|
||||
this.props.onFocus(this.props.id);
|
||||
}
|
||||
handleClick (e) {
|
||||
this.props.onSelect(this.props.id);
|
||||
if (!this.props.disabled) {
|
||||
this.props.onSelect(this.props.id);
|
||||
}
|
||||
e.preventDefault();
|
||||
}
|
||||
handleKeyPress (e) {
|
||||
@@ -43,10 +46,25 @@ class LibraryItem extends React.PureComponent {
|
||||
render () {
|
||||
return this.props.featured ? (
|
||||
<div
|
||||
className={classNames(styles.libraryItem, styles.featuredItem)}
|
||||
className={classNames(
|
||||
styles.libraryItem,
|
||||
styles.featuredItem,
|
||||
{
|
||||
[styles.disabled]: this.props.disabled
|
||||
}
|
||||
)}
|
||||
onClick={this.handleClick}
|
||||
>
|
||||
<div>
|
||||
<div className={styles.featuredImageContainer}>
|
||||
{this.props.disabled ? (
|
||||
<div className={styles.comingSoonText}>
|
||||
<FormattedMessage
|
||||
defaultMessage="Coming Soon"
|
||||
description="Label for extensions that are not yet implemented"
|
||||
id="gui.extensionLibrary.comingSoon"
|
||||
/>
|
||||
</div>
|
||||
) : null}
|
||||
<img
|
||||
className={styles.featuredImage}
|
||||
src={this.props.iconURL}
|
||||
@@ -89,6 +107,7 @@ class LibraryItem extends React.PureComponent {
|
||||
|
||||
LibraryItem.propTypes = {
|
||||
description: PropTypes.string,
|
||||
disabled: PropTypes.bool,
|
||||
featured: PropTypes.bool,
|
||||
iconURL: PropTypes.string.isRequired,
|
||||
id: PropTypes.number.isRequired,
|
||||
@@ -100,4 +119,8 @@ LibraryItem.propTypes = {
|
||||
onSelect: PropTypes.func.isRequired
|
||||
};
|
||||
|
||||
LibraryItem.defaultProps = {
|
||||
disabled: false
|
||||
};
|
||||
|
||||
export default LibraryItem;
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
.library-scroll-grid {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
justify-content: flex-start;
|
||||
align-content: flex-start;
|
||||
background: $ui-pane-gray;
|
||||
flex-grow: 1;
|
||||
|
||||
@@ -68,6 +68,7 @@ class LibraryComponent extends React.Component {
|
||||
return (
|
||||
<LibraryItem
|
||||
description={dataItem.description}
|
||||
disabled={dataItem.disabled}
|
||||
featured={dataItem.featured}
|
||||
iconURL={scratchURL}
|
||||
id={index}
|
||||
|
||||
@@ -16,9 +16,12 @@ class ExtensionLibrary extends React.PureComponent {
|
||||
]);
|
||||
}
|
||||
handleItemSelect (item) {
|
||||
// eslint-disable-next-line no-alert
|
||||
const url = item.extensionURL || prompt('Enter the URL of the extension');
|
||||
if (url) {
|
||||
let url = item.extensionURL;
|
||||
if (!item.disabled && !item.extensionURL) {
|
||||
// eslint-disable-next-line no-alert
|
||||
url = prompt('Enter the URL of the extension');
|
||||
}
|
||||
if (url && !item.disabled) {
|
||||
if (this.props.vm.extensionManager.isExtensionLoaded(url)) {
|
||||
this.props.onCategorySelected(item.name);
|
||||
} else {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 42 KiB |
@@ -1,5 +1,9 @@
|
||||
import boostImage from './boost.png';
|
||||
import musicImage from './music.png';
|
||||
import penImage from './pen.png';
|
||||
import speechImage from './speech.png';
|
||||
import videoImage from './video-sensing.png';
|
||||
import wedoImage from './wedo.png';
|
||||
|
||||
export default [
|
||||
{
|
||||
@@ -15,5 +19,37 @@ export default [
|
||||
iconURL: penImage,
|
||||
description: 'Draw with your sprites.',
|
||||
featured: true
|
||||
},
|
||||
{
|
||||
name: 'LEGO WeDo 2.0',
|
||||
extensionURL: '',
|
||||
iconURL: wedoImage,
|
||||
description: 'Build with motors and sensors.',
|
||||
featured: true,
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
name: 'Speech',
|
||||
extensionURL: '',
|
||||
iconURL: speechImage,
|
||||
description: 'Talk to your projects.',
|
||||
featured: true,
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
name: 'Video Sensing',
|
||||
extensionURL: '',
|
||||
iconURL: videoImage,
|
||||
description: 'Detect motion with the camera.',
|
||||
featured: true,
|
||||
disabled: true
|
||||
},
|
||||
{
|
||||
name: 'LEGO Boost',
|
||||
extensionURL: '',
|
||||
iconURL: boostImage,
|
||||
description: 'Build robots and more.',
|
||||
featured: true,
|
||||
disabled: true
|
||||
}
|
||||
];
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 30 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 41 KiB |
Reference in new issue
Block a user