fixed height of studio buttons scrolling container to fill all modal

This commit is contained in:
Linda 2018-10-02 13:49:56 -04:00
commit 7c8fdbfcc3
15 changed files with 184 additions and 97 deletions

View file

@ -100,7 +100,7 @@
"redux-thunk": "2.0.1", "redux-thunk": "2.0.1",
"sass-lint": "1.5.1", "sass-lint": "1.5.1",
"sass-loader": "6.0.6", "sass-loader": "6.0.6",
"scratch-gui": "latest", "scratch-gui": "develop",
"scratchr2_translations": "git://github.com/LLK/scratchr2_translations.git#master", "scratchr2_translations": "git://github.com/LLK/scratchr2_translations.git#master",
"slick-carousel": "1.6.0", "slick-carousel": "1.6.0",
"source-map-support": "0.3.2", "source-map-support": "0.3.2",

View file

@ -28,6 +28,7 @@ $ui-coral-dark: hsla(350, 100, 60, 1); // #FF3355 More Blocks tertiary
$ui-white: hsla(0, 100%, 100%, 1); //#FFF $ui-white: hsla(0, 100%, 100%, 1); //#FFF
$ui-white-15percent: hsla(0, 100%, 100%, .15); //#FFF $ui-white-15percent: hsla(0, 100%, 100%, .15); //#FFF
$ui-light-primary: hsl(215, 100, 95); $ui-light-primary: hsl(215, 100, 95);
$ui-light-primary-transparent: hsla(215, 100, 95, 0);
$ui-border: hsla(0, 0, 85, 1); //#D9D9D9 $ui-border: hsla(0, 0, 85, 1); //#D9D9D9

View file

@ -20,12 +20,19 @@ $medium-height: "only screen and (min-height : #{$mobile} + 1) and (max-height :
.studio-list-outer-scrollbox { .studio-list-outer-scrollbox {
position: relative; position: relative;
background-color: $ui-blue-10percent; background-color: $ui-blue-10percent;
flex: 1;
max-height: calc(100% - 8rem);
min-height: 15rem;
@media #{$small-height} {
min-height: 0;
}
} }
.studio-list-inner-scrollbox { .studio-list-inner-scrollbox {
margin-right: .5rem; margin-right: .5rem;
padding-right: .5rem; padding-right: .5rem;
height: 16.9375rem; height: 100%;
overflow: scroll; overflow: scroll;
overflow-x: hidden; overflow-x: hidden;

View file

@ -37,13 +37,12 @@ const AddToStudioModalPresentation = ({
return ( return (
<Modal <Modal
standardSizes useStandardSizes
className="mod-addToStudio" className="mod-addToStudio"
contentLabel={contentLabel} contentLabel={contentLabel}
isOpen={isOpen} isOpen={isOpen}
onRequestClose={onRequestClose} onRequestClose={onRequestClose}
> >
<div>
<div className="addToStudio-modal-header modal-header"> <div className="addToStudio-modal-header modal-header">
<div className="addToStudio-content-label content-label"> <div className="addToStudio-content-label content-label">
{contentLabel} {contentLabel}
@ -102,7 +101,6 @@ const AddToStudioModalPresentation = ({
</FlexRow> </FlexRow>
</Form> </Form>
</div> </div>
</div>
</Modal> </Modal>
); );
}; };

View file

@ -28,7 +28,7 @@ class Modal extends React.Component {
appElement={document.getElementById('app')} appElement={document.getElementById('app')}
className={{ className={{
base: classNames('modal-content', this.props.className, { base: classNames('modal-content', this.props.className, {
'modal-sizes': this.props.standardSizes 'modal-sizes': this.props.useStandardSizes
}), }),
afterOpen: classNames('modal-content', this.props.className), afterOpen: classNames('modal-content', this.props.className),
beforeClose: classNames('modal-content', this.props.className) beforeClose: classNames('modal-content', this.props.className)
@ -63,7 +63,7 @@ Modal.propTypes = {
children: PropTypes.node, children: PropTypes.node,
className: PropTypes.string, className: PropTypes.string,
overlayClassName: PropTypes.string, overlayClassName: PropTypes.string,
standardSizes: PropTypes.bool useStandardSizes: PropTypes.bool
}; };
module.exports = Modal; module.exports = Modal;

View file

@ -111,7 +111,7 @@ class ReportModal extends React.Component {
const contentLabel = intl.formatMessage({id: `report.${type}`}); const contentLabel = intl.formatMessage({id: `report.${type}`});
return ( return (
<Modal <Modal
standardSizes useStandardSizes
className="mod-report" className="mod-report"
contentLabel={contentLabel} contentLabel={contentLabel}
isOpen={isOpen} isOpen={isOpen}

View file

@ -444,18 +444,20 @@ class DemographicsStep extends React.Component {
handleChooseGender (name, gender) { handleChooseGender (name, gender) {
this.setState({otherDisabled: gender !== 'other'}); this.setState({otherDisabled: gender !== 'other'});
} }
handleValidSubmit (formData, reset, invalidate) { handleValidSubmit (formData) {
return this.props.onNextStep(formData);
}
isValidBirthdate (year, month) {
const birthdate = new Date( const birthdate = new Date(
formData.user.birth.year, year,
formData.user.birth.month - 1, month - 1,
1 1
); );
if (((Date.now() - birthdate) / (24 * 3600 * 1000 * 365.25)) < this.props.birthOffset) { return (((Date.now() - birthdate) / (24 * 3600 * 1000 * 365.25)) >= this.props.birthOffset);
return invalidate({
'user.birth.year': this.props.intl.formatMessage({id: 'teacherRegistration.validationAge'})
});
} }
return this.props.onNextStep(formData); birthDateValidator (values) {
const isValid = this.isValidBirthdate(values['user.birth.year'], values['user.birth.month']);
return isValid ? true : this.props.intl.formatMessage({id: 'teacherRegistration.validationAge'});
} }
render () { render () {
const countryOptions = getCountryOptions(this.props.intl, DEFAULT_COUNTRY); const countryOptions = getCountryOptions(this.props.intl, DEFAULT_COUNTRY);
@ -485,6 +487,9 @@ class DemographicsStep extends React.Component {
} }
name="user.birth.month" name="user.birth.month"
options={this.getMonthOptions()} options={this.getMonthOptions()}
validations={{
birthDateVal: values => this.birthDateValidator(values)
}}
/> />
<Select <Select
required required

View file

@ -45,6 +45,7 @@
float: left; float: left;
max-width: 164px; max-width: 164px;
overflow: hidden; overflow: hidden;
text-align: left;
.thumbnail-creator a { .thumbnail-creator a {
color: $type-gray; color: $type-gray;

View file

@ -35,14 +35,6 @@ const Jobs = () => (
MIT Media Lab, Cambridge, MA MIT Media Lab, Cambridge, MA
</span> </span>
</li> </li>
<li>
<a href="https://scratch.mit.edu/jobs/moderator">
Community Moderator
</a>
<span>
Remote
</span>
</li>
</ul> </ul>
</div> </div>
</div> </div>

View file

@ -172,7 +172,7 @@
position: absolute; position: absolute;
bottom: 0; bottom: 0;
background: linear-gradient( background: linear-gradient(
transparent, $ui-light-primary-transparent,
$ui-light-primary $ui-light-primary
); );
width: 100%; width: 100%;
@ -211,4 +211,3 @@
margin-right: -50%; margin-right: -50%;
} }
} }

View file

@ -26,6 +26,7 @@
font-size: .875rem; font-size: .875rem;
justify-content: center; justify-content: center;
flex-flow: column; flex-flow: column;
align-items: flex-start;
} }
.extension-status { .extension-status {

View file

@ -2,6 +2,7 @@ const FormattedDate = require('react-intl').FormattedDate;
const injectIntl = require('react-intl').injectIntl; const injectIntl = require('react-intl').injectIntl;
const PropTypes = require('prop-types'); const PropTypes = require('prop-types');
const intlShape = require('react-intl').intlShape; const intlShape = require('react-intl').intlShape;
const MediaQuery = require('react-responsive').default;
const React = require('react'); const React = require('react');
const Formsy = require('formsy-react').default; const Formsy = require('formsy-react').default;
const classNames = require('classnames'); const classNames = require('classnames');
@ -28,6 +29,8 @@ const ExtensionChip = require('./extension-chip.jsx');
const projectShape = require('./projectshape.jsx').projectShape; const projectShape = require('./projectshape.jsx').projectShape;
require('./preview.scss'); require('./preview.scss');
const frameless = require('../../lib/frameless');
// disable enter key submission on formsy input fields; otherwise formsy thinks // disable enter key submission on formsy input fields; otherwise formsy thinks
// we meant to trigger the "See inside" button. Instead, treat these keypresses // we meant to trigger the "See inside" button. Instead, treat these keypresses
// as a blur, which will trigger a save. // as a blur, which will trigger a save.
@ -155,6 +158,21 @@ const PreviewPresentation = ({
<RemixCredit projectInfo={parentInfo} /> <RemixCredit projectInfo={parentInfo} />
<RemixCredit projectInfo={originalInfo} /> <RemixCredit projectInfo={originalInfo} />
{/* eslint-disable max-len */} {/* eslint-disable max-len */}
<MediaQuery maxWidth={frameless.tablet - 1}>
<FlexRow className="preview-row">
<FlexRow className="extension-list">
{extensions && extensions.map(extension => (
<ExtensionChip
extensionL10n={extension.l10nId}
extensionName={extension.name}
hasStatus={extension.hasStatus}
iconURI={extension.icon && `/svgs/project/${extension.icon}`}
key={extension.name || extension.l10nId}
/>
))}
</FlexRow>
</FlexRow>
</MediaQuery>
<FlexRow className="description-block"> <FlexRow className="description-block">
<div className="project-textlabel"> <div className="project-textlabel">
Instructions Instructions
@ -309,6 +327,7 @@ const PreviewPresentation = ({
</FlexRow> </FlexRow>
</FlexRow> </FlexRow>
</FlexRow> </FlexRow>
<MediaQuery minWidth={frameless.tablet}>
<FlexRow className="preview-row"> <FlexRow className="preview-row">
<FlexRow className="extension-list"> <FlexRow className="extension-list">
{extensions && extensions.map(extension => ( {extensions && extensions.map(extension => (
@ -322,6 +341,7 @@ const PreviewPresentation = ({
))} ))}
</FlexRow> </FlexRow>
</FlexRow> </FlexRow>
</MediaQuery>
</div> </div>
<div className="project-lower-container"> <div className="project-lower-container">
<div className="inner"> <div className="inner">

View file

@ -246,6 +246,9 @@ class Preview extends React.Component {
handleSeeInside () { handleSeeInside () {
this.props.setPlayer(false); this.props.setPlayer(false);
} }
handleShare () {
// This is just a placeholder, but enables the button in the editor
}
handleUpdate (jsonData) { handleUpdate (jsonData) {
this.props.updateProject( this.props.updateProject(
this.props.projectInfo.id, this.props.projectInfo.id,
@ -338,6 +341,7 @@ class Preview extends React.Component {
renderLogin={this.renderLogin} renderLogin={this.renderLogin}
onLogOut={this.props.handleLogOut} onLogOut={this.props.handleLogOut}
onOpenRegistration={this.props.handleOpenRegistration} onOpenRegistration={this.props.handleOpenRegistration}
onShare={this.handleShare}
onToggleLoginOpen={this.props.handleToggleLoginOpen} onToggleLoginOpen={this.props.handleToggleLoginOpen}
onUpdateProjectTitle={this.handleUpdateProjectTitle} onUpdateProjectTitle={this.handleUpdateProjectTitle}
/> />

View file

@ -11,7 +11,6 @@ $small: "screen and (max-width : #{$mobile}-1)";
$medium: "screen and (min-width : #{$mobile}) and (max-width : #{$tablet}-1)"; $medium: "screen and (min-width : #{$mobile}) and (max-width : #{$tablet}-1)";
$big: "screen and (min-width : #{$tablet})"; $big: "screen and (min-width : #{$tablet})";
$medium-and-small: "screen and (max-width : #{$tablet}-1)"; $medium-and-small: "screen and (max-width : #{$tablet}-1)";
$little-height: "screen and (max-height : 460px)";
/* override view padding for share banner */ /* override view padding for share banner */
#view { #view {
@ -154,7 +153,23 @@ $little-height: "screen and (max-height : 460px)";
} }
.comments-container { .comments-container {
width: 65%; padding-right: 1.5rem;
min-width: 65%;
max-width: 100%;
flex: 1;
@media #{$medium-and-small} {
padding: 0;
width: 100%;
}
.comment, .comment-top-row, .comment-bottom-row {
flex-direction: row;
}
.comment-bubble {
text-align: left;
}
} }
.remix-button, .remix-button,
@ -201,6 +216,14 @@ $little-height: "screen and (max-height : 460px)";
.guiPlayer { .guiPlayer {
display: inline-block; display: inline-block;
width: $player-width; width: $player-width;
@media #{$small} {
width: 100%;
.stage-wrapper {
max-width: 100%;
}
}
} }
.project-notes { .project-notes {
@ -210,6 +233,12 @@ $little-height: "screen and (max-height : 460px)";
flex: 1; flex: 1;
flex-flow: column; flex-flow: column;
@media #{$medium-and-small} {
margin-top: 1rem;
margin-left: 0;
width: 100%;
}
> .description-block:first-child { > .description-block:first-child {
margin-top: 1rem; margin-top: 1rem;
} }
@ -516,6 +545,12 @@ $little-height: "screen and (max-height : 460px)";
.extension-list { .extension-list {
justify-content: flex-start; justify-content: flex-start;
flex-direction: row;
@media #{$medium-and-small} {
justify-content: center;
}
} }
.remix-list, .remix-list,
@ -537,6 +572,21 @@ $little-height: "screen and (max-height : 460px)";
.thumbnail-column { .thumbnail-column {
display: inline-block; display: inline-block;
width: 100%; width: 100%;
/* TODO: the following can be transferred to
src/components/thumbnailcolumn/thumbnailcolumn.scss
after testing */
@media #{$medium-and-small} {
flex-direction: row;
.thumbnail {
display: inline-block;
}
}
}
@media #{$medium-and-small} {
margin-top: 1rem;
} }
} }
} }

View file

@ -57,12 +57,21 @@ class Search extends React.Component {
} }
componentDidMount () { componentDidMount () {
const query = window.location.search; const query = decodeURIComponent(window.location.search);
const q = query.lastIndexOf('q='); let term = query;
let term = '';
if (q !== -1) { const stripQueryValue = function (queryTerm) {
term = query.substring(q + 2, query.length).toLowerCase(); const queryIndex = query.indexOf('q=');
if (queryIndex !== -1) {
queryTerm = query.substring(queryIndex + 2, query.length).toLowerCase();
} }
return queryTerm;
};
// Strip off the initial "?q="
term = stripQueryValue(term);
// Strip off user entered "?q="
term = stripQueryValue(term);
while (term.indexOf('/') > -1) { while (term.indexOf('/') > -1) {
term = term.substring(0, term.indexOf('/')); term = term.substring(0, term.indexOf('/'));
} }