Upgrade instructure-ui to 1.0

fixes CNVS-34969

test plan:
  - go /profile/settings and turn on high contrast
  - go to the course people page (/courses/#/users)
  - click on the +People button
  > expected result: the modal honors high contrast

  - enter some text in he text area
  > expected result: nothing bad happens, as the event
    handler for TextArea has changed.
  - there's a TextArea in MessageStudents also, but I don't
    know where to find it in the UI. You should probalby
    test it doesn't blow up either.

Change-Id: Ia8102dacfa2b01ee043002ee0f5c27943abe5743
Reviewed-on: https://gerrit.instructure.com/102133
Tested-by: Jenkins
Reviewed-by: Ryan Shaw <ryan@instructure.com>
QA-Review: Dan Sasaki
Product-Review: Ryan Shaw <ryan@instructure.com>
Product-Review: Ed Schiebel <eschiebel@instructure.com>
This commit is contained in:
Ed Schiebel 2017-02-14 16:54:51 -05:00
parent 7b024780c6
commit d1664390e2
34 changed files with 274 additions and 205 deletions

View File

@ -7,6 +7,7 @@ require [
'compiled/helpDialog' 'compiled/helpDialog'
'jsx/subnav_menu/updateSubnavMenuToggle' 'jsx/subnav_menu/updateSubnavMenuToggle'
'jsx/new_user_tutorial/initializeNewUserTutorials' 'jsx/new_user_tutorial/initializeNewUserTutorials'
'instructure-ui/ApplyTheme'
# modules that do their own thing on every page that simply need to # modules that do their own thing on every page that simply need to
# be required # be required
@ -30,6 +31,7 @@ require [
'compiled/behaviors/ping' 'compiled/behaviors/ping'
'LtiThumbnailLauncher' 'LtiThumbnailLauncher'
'compiled/badge_counts' 'compiled/badge_counts'
'instructure-ui-themes/canvas'
# Other stuff several bundles use. # Other stuff several bundles use.
# If any of these really arn't used on most pages, # If any of these really arn't used on most pages,
@ -41,7 +43,7 @@ require [
'jqueryui/tabs' 'jqueryui/tabs'
'compiled/registration/incompleteRegistrationWarning' 'compiled/registration/incompleteRegistrationWarning'
'moment' 'moment'
], ($, _, I18n, Backbone, helpDialog, updateSubnavMenuToggle, initializeNewUserTutorials) -> ], ($, _, I18n, Backbone, helpDialog, updateSubnavMenuToggle, initializeNewUserTutorials, ApplyTheme) ->
helpDialog.initTriggers() helpDialog.initTriggers()
@ -80,3 +82,9 @@ require [
$('body').on 'click', '[data-pushstate]', (event) -> $('body').on 'click', '[data-pushstate]', (event) ->
event.preventDefault() event.preventDefault()
Backbone.history.navigate $(this).attr('href'), yes Backbone.history.navigate $(this).attr('href'), yes
# setup the inst-ui default theme
if ENV.use_high_contrast
ApplyTheme.default.setDefaultTheme('canvas-a11y')
else
ApplyTheme.default.setDefaultTheme('canvas')

View File

@ -2,16 +2,21 @@ define([
'i18n!roster', 'i18n!roster',
'react', 'react',
'react-dom', 'react-dom',
'instructure-ui', 'instructure-ui/Modal',
'instructure-ui/Heading',
'instructure-ui/Button',
'instructure-ui/Spinner',
'instructure-ui/Alert',
'instructure-ui/ScreenReaderContent',
'./shapes', './shapes',
'./people_search', './people_search',
'./people_ready_list', './people_ready_list',
'./people_validation_issues', './people_validation_issues',
'./api_error' './api_error'
], (I18n, React, ReactDOM, ], (I18n, React, ReactDOM,
{Modal, ModalHeader, ModalBody, ModalFooter, {default: Modal, ModalHeader, ModalBody, ModalFooter},
Heading, Button, Spinner, Alert, {default: Heading}, {default: Button}, {default: Spinner}, {default: Alert},
ScreenReaderContent, ApplyTheme}, {default: ScreenReaderContent},
{courseParamsShape, apiStateShape, inputParamsShape, validateResultShape, personReadyToEnrollShape}, {courseParamsShape, apiStateShape, inputParamsShape, validateResultShape, personReadyToEnrollShape},
PeopleSearch, PeopleReadyList, PeopleValidationIssues, APIError) => { PeopleSearch, PeopleReadyList, PeopleValidationIssues, APIError) => {
const PEOPLESEARCH = 'peoplesearch'; const PEOPLESEARCH = 'peoplesearch';
@ -307,13 +312,5 @@ define([
); );
} }
} }
return AddPeople;
const DeleteMe = props => (
<ApplyTheme theme={ApplyTheme.generateTheme('a11y')}>
<AddPeople {...props} />
</ApplyTheme>
)
/* TODO: after instui gets updated, just return AddPeople */
return ENV.use_high_contrast ? DeleteMe : AddPeople;
}); });

View File

@ -1,8 +1,8 @@
define([ define([
'i18n!roster', 'i18n!roster',
'react', 'react',
'instructure-ui' 'instructure-ui/Alert'
], (I18n, React, {Alert}) => { ], (I18n, React, {default: Alert}) => {
class ApiError extends React.Component { class ApiError extends React.Component {
static propTypes = { static propTypes = {
error: React.PropTypes.oneOfType([ error: React.PropTypes.oneOfType([
@ -17,7 +17,7 @@ define([
{I18n.t('The following users could not be created.')} {I18n.t('The following users could not be created.')}
<ul className="apierror__error_list"> <ul className="apierror__error_list">
{ {
this.props.error.map((e, i) => <li key={i}>{e}</li>) this.props.error.map(e => <li key={Date.now()}>{e}</li>)
} }
</ul> </ul>
</div> </div>

View File

@ -2,9 +2,14 @@ define([
'i18n!roster', 'i18n!roster',
'react', 'react',
'./shapes', './shapes',
'instructure-ui' 'instructure-ui/Table',
], (I18n, React, shapes, {Table, ScreenReaderContent, 'instructure-ui/ScreenReaderContent',
TextInput, RadioInput, Typography, Link}) => { 'instructure-ui/TextInput',
'instructure-ui/RadioInput',
'instructure-ui/Typography',
'instructure-ui/Link'
], (I18n, React, shapes, {default: Table}, {default: ScreenReaderContent},
{default: TextInput}, {default: RadioInput}, {default: Typography}, {default: Link}) => {
const CREATE_NEW = '__CREATE_NEW__'; const CREATE_NEW = '__CREATE_NEW__';
const SKIP = '__SKIP'; const SKIP = '__SKIP';
const nameLabel = I18n.t("New user's name"); const nameLabel = I18n.t("New user's name");
@ -39,7 +44,9 @@ define([
onSelectNewForDuplicate = (event) => { onSelectNewForDuplicate = (event) => {
// if the event was not from the radio button, find and focus it // if the event was not from the radio button, find and focus it
if (!(event.target.tagName === 'input' && event.target.getAttribute('type') === 'radio')) { if (!(event.target.tagName === 'input' && event.target.getAttribute('type') === 'radio')) {
const radioButton = event.target.parentElement.parentElement.querySelector('input[type="radio"]'); let elem = event.target;
for (; elem.tagName !== 'TR'; elem = elem.parentElement);
const radioButton = elem.querySelector('input[type="radio"]');
radioButton.focus(); radioButton.focus();
} }
this.props.onNewForDuplicate(this.props.duplicates.address, this.props.duplicates.newUserInfo); this.props.onNewForDuplicate(this.props.duplicates.address, this.props.duplicates.newUserInfo);

View File

@ -2,9 +2,13 @@ define([
'i18n!roster', 'i18n!roster',
'react', 'react',
'./shapes', './shapes',
'instructure-ui' 'instructure-ui/Table',
], (I18n, React, shapes, {Table, ScreenReaderContent, 'instructure-ui/ScreenReaderContent',
TextInput, Checkbox, Link}) => { 'instructure-ui/TextInput',
'instructure-ui/Checkbox',
'instructure-ui/Link'
], (I18n, React, shapes, {default: Table}, {default: ScreenReaderContent},
{default: TextInput}, {default: Checkbox}, {default: Link}) => {
const namePrompt = I18n.t('Click to add a name'); const namePrompt = I18n.t('Click to add a name');
const nameLabel = I18n.t("New user's name"); const nameLabel = I18n.t("New user's name");
const emailLabel = I18n.t('Required Email Address'); const emailLabel = I18n.t('Required Email Address');
@ -31,6 +35,7 @@ define([
this.state = { this.state = {
selectAll: false selectAll: false
}; };
this.tbodyNode = null;
} }
componentWillReceiveProps (nextProps) { componentWillReceiveProps (nextProps) {
@ -44,11 +49,14 @@ define([
eatEvent(event); eatEvent(event);
// user may have clicked on the link. if so, put focus on the adjacent checkbox // user may have clicked on the link. if so, put focus on the adjacent checkbox
if (!(event.target.tagName === 'input' && event.target.getAttribute('type') === 'checkbox')) { if (!(event.target.tagName === 'INPUT' && event.target.getAttribute('type') === 'checkbox')) {
const checkbox = event.target.parentElement.parentElement.querySelector('input[type="checkbox"]'); // The link was rendered with the attribute data-address=address for this row.
checkbox.focus(); // Use it to find the checkbox with the matching value.
const checkbox = this.tbodyNode.querySelector(`input[type="checkbox"][value="${event.target.getAttribute('data-address')}"]`);
if (checkbox) {
checkbox.focus();
}
} }
const address = event.target.value || event.target.getAttribute('data-address'); const address = event.target.value || event.target.getAttribute('data-address');
this.onSelectNewForMissingByAddress(address); this.onSelectNewForMissingByAddress(address);
} }
@ -288,7 +296,7 @@ define([
<div className="addpeople__missing namelist"> <div className="addpeople__missing namelist">
<Table caption={<ScreenReaderContent>{I18n.t('Unmatched login list')}</ScreenReaderContent>}> <Table caption={<ScreenReaderContent>{I18n.t('Unmatched login list')}</ScreenReaderContent>}>
{this.renderTableHead()} {this.renderTableHead()}
<tbody> <tbody ref={(n) => { this.tbodyNode = n; }} >
{this.props.searchType === 'cc_path' ? this.renderMissingEmail() : this.renderMissingIds()} {this.props.searchType === 'cc_path' ? this.renderMissingEmail() : this.renderMissingIds()}
</tbody> </tbody>
</Table> </Table>

View File

@ -2,9 +2,11 @@ define([
'i18n!roster', 'i18n!roster',
'react', 'react',
'./shapes', './shapes',
'instructure-ui' 'instructure-ui/Alert',
'instructure-ui/Table',
'instructure-ui/ScreenReaderContent'
], (I18n, React, {personReadyToEnrollShape}, ], (I18n, React, {personReadyToEnrollShape},
{Alert, Table, ScreenReaderContent}) => { {default: Alert}, {default: Table}, {default: ScreenReaderContent}) => {
class PeopleReadyList extends React.Component { class PeopleReadyList extends React.Component {
static propTypes = { static propTypes = {
nameList: React.PropTypes.arrayOf(React.PropTypes.shape(personReadyToEnrollShape)), nameList: React.PropTypes.arrayOf(React.PropTypes.shape(personReadyToEnrollShape)),

View File

@ -1,12 +1,22 @@
define([ define([
'i18n!roster', 'i18n!roster',
'react', 'react',
'instructure-ui', 'instructure-ui/Button',
'instructure-ui/Typography',
'instructure-ui/RadioInputGroup',
'instructure-ui/RadioInput',
'instructure-ui/Select',
'instructure-ui/TextArea',
'instructure-ui/ScreenReaderContent',
'instructure-ui/Checkbox',
'instructure-ui/Alert',
'instructure-icons/react/Solid/IconUserSolid',
'./shapes', './shapes',
'../helpers' '../helpers'
], (I18n, React, {Button, Typography, RadioInputGroup, ], (I18n, React, {default: Button}, {default: Typography}, {default: RadioInputGroup},
RadioInput, Select, TextArea, ScreenReaderContent, {default: RadioInput}, {default: Select}, {default: TextArea}, {default: ScreenReaderContent},
Checkbox, Alert}, {courseParamsShape, inputParamsShape}, {default: Checkbox}, {default: Alert}, {default: IconUserSolid},
{courseParamsShape, inputParamsShape},
{parseNameList, findEmailInEntry, emailValidator}) => { {parseNameList, findEmailInEntry, emailValidator}) => {
class PeopleSearch extends React.Component { class PeopleSearch extends React.Component {
static propTypes = Object.assign({}, inputParamsShape, courseParamsShape); static propTypes = Object.assign({}, inputParamsShape, courseParamsShape);
@ -38,8 +48,8 @@ define([
onChangeSearchType = (newValue) => { onChangeSearchType = (newValue) => {
this.props.onChange({searchType: newValue}); this.props.onChange({searchType: newValue});
} }
onChangeNameList = (newValue) => { onChangeNameList = (event) => {
this.props.onChange({nameList: newValue}); this.props.onChange({nameList: event.target.value});
} }
onChangeSection = (event) => { onChangeSection = (event) => {
@ -98,17 +108,16 @@ define([
defaultValue={this.props.searchType} defaultValue={this.props.searchType}
description={I18n.t('Add user(s) by')} description={I18n.t('Add user(s) by')}
onChange={this.onChangeSearchType} onChange={this.onChangeSearchType}
layout="columns"
> >
<RadioInput <RadioInput
id="peoplesearch_radio_cc_path" id="peoplesearch_radio_cc_path"
isBlock={false}
key="cc_path" key="cc_path"
value="cc_path" value="cc_path"
label={I18n.t('Email Address')} label={I18n.t('Email Address')}
/> />
<RadioInput <RadioInput
id="peoplesearch_radio_unique_id" id="peoplesearch_radio_unique_id"
isBlock={false}
key="unique_id" key="unique_id"
value="unique_id" value="unique_id"
label={I18n.t('Login ID')} label={I18n.t('Login ID')}
@ -116,7 +125,6 @@ define([
{this.props.canReadSIS {this.props.canReadSIS
? <RadioInput ? <RadioInput
id="peoplesearch_radio_sis_user_id" id="peoplesearch_radio_sis_user_id"
isBlock={false}
key="sis_user_id" key="sis_user_id"
value="sis_user_id" value="sis_user_id"
label={I18n.t('SIS ID')} label={I18n.t('SIS ID')}
@ -173,7 +181,9 @@ define([
</div> </div>
</fieldset> </fieldset>
<div className="peoplesearch__instructions"> <div className="peoplesearch__instructions">
<i className="icon-user" /> <div className="usericon" aria-hidden>
<IconUserSolid />
</div>
<Typography size="medium"> <Typography size="medium">
{I18n.t('When adding multiple users, use a comma or line break to separate users.')} {I18n.t('When adding multiple users, use a comma or line break to separate users.')}
</Typography> </Typography>

View File

@ -4,8 +4,8 @@ define([
'./shapes', './shapes',
'./duplicate_section', './duplicate_section',
'./missing_people_section', './missing_people_section',
'instructure-ui' 'instructure-ui/Alert'
], (I18n, React, shapes, DuplicateSection, MissingPeopleSection, {Alert}) => { ], (I18n, React, shapes, DuplicateSection, MissingPeopleSection, {default: Alert}) => {
class PeopleValidationIssues extends React.Component { class PeopleValidationIssues extends React.Component {
static propTypes = { static propTypes = {
searchType: React.PropTypes.string.isRequired, searchType: React.PropTypes.string.isRequired,

View File

@ -10,7 +10,7 @@ define([
const apiStateShape = { const apiStateShape = {
pendingCount: PropTypes.number, // number of api calls in-flight pendingCount: PropTypes.number, // number of api calls in-flight
error: PropTypes.string // error message or undefined error: PropTypes.oneOfType([PropTypes.string, PropTypes.arrayOf(PropTypes.string)]) // error message or undefined
}; };
const inputParamsShape = { const inputParamsShape = {

View File

@ -1,19 +1,24 @@
import ApplyTheme from 'instructure-ui/ApplyTheme'
import 'instructure-ui-themes/canvas'
import moment from 'moment'
import tz from 'timezone_core'
import './fakeRequireJSFallback'
// Sets up moment to use the right locale
const moment = require('moment')
// we already put a <script> tag for the locale corresponding ENV.MOMENT_LOCALE // we already put a <script> tag for the locale corresponding ENV.MOMENT_LOCALE
// on the page from rails, so this should not cause a new network request. // on the page from rails, so this should not cause a new network request.
moment().locale(ENV.MOMENT_LOCALE) moment().locale(ENV.MOMENT_LOCALE)
// These timezones and locales should already be put on the page as <script> // These timezones and locales should already be put on the page as <script>
// tags from rails. this block should not create any network requests. // tags from rails. this block should not create any network requests.
const tz = require('timezone_core')
if (typeof ENV !== 'undefined') { if (typeof ENV !== 'undefined') {
if (ENV.TIMEZONE) tz.changeZone(ENV.TIMEZONE) if (ENV.TIMEZONE) tz.changeZone(ENV.TIMEZONE)
if (ENV.CONTEXT_TIMEZONE) tz.preload(ENV.CONTEXT_TIMEZONE) if (ENV.CONTEXT_TIMEZONE) tz.preload(ENV.CONTEXT_TIMEZONE)
if (ENV.BIGEASY_LOCALE) tz.changeLocale(ENV.BIGEASY_LOCALE, ENV.MOMENT_LOCALE) if (ENV.BIGEASY_LOCALE) tz.changeLocale(ENV.BIGEASY_LOCALE, ENV.MOMENT_LOCALE)
} }
require('./fakeRequireJSFallback') // setup the inst-ui default theme
if (ENV.use_high_contrast) {
ApplyTheme.setDefaultTheme('canvas-a11y')
} else {
ApplyTheme.setDefaultTheme('canvas')
}

View File

@ -31,7 +31,7 @@ define([
/> />
{ {
canMasquerade ? ( canMasquerade ? (
<Typography size="x-small" weight="bold" tag="div"> <Typography size="x-small" weight="bold" as="div">
<a <a
href={`/courses/${courseId}?become_user_id=${user.id}`} href={`/courses/${courseId}?become_user_id=${user.id}`}
aria-label={I18n.t('Masquerade as %{name}', { name: user.short_name })} aria-label={I18n.t('Masquerade as %{name}', { name: user.short_name })}

View File

@ -35,7 +35,7 @@ define([
return ( return (
<div <div
className="StudentContextTray-Rating"> className="StudentContextTray-Rating">
<Heading level="h5" tag="h4"> <Heading level="h5" as="h4">
{this.props.label} {this.props.label}
</Heading> </Heading>
<div className="StudentContextTray-Rating__Stars"> <div className="StudentContextTray-Rating__Stars">

View File

@ -20,7 +20,7 @@ define([
SectionInfo, SectionInfo,
SubmissionProgressBars, SubmissionProgressBars,
MessageStudents, MessageStudents,
{Heading, Button, Link, Typography, ScreenReaderContent, Spinner, Tray, ApplyTheme}) { {Heading, Button, Link, Typography, ScreenReaderContent, Spinner, Tray}) {
class StudentContextTray extends React.Component { class StudentContextTray extends React.Component {
@ -231,7 +231,7 @@ define([
<div className="StudentContextTray-Header__Content"> <div className="StudentContextTray-Header__Content">
{this.state.user.short_name ? ( {this.state.user.short_name ? (
<div className="StudentContextTray-Header__Name"> <div className="StudentContextTray-Header__Name">
<Heading level="h3" tag="h2"> <Heading level="h3" as="h2">
<span className="StudentContextTray-Header__NameLink"> <span className="StudentContextTray-Header__NameLink">
<Link <Link
href={`/courses/${this.props.courseId}/users/${this.props.studentId}`} href={`/courses/${this.props.courseId}/users/${this.props.studentId}`}
@ -243,14 +243,14 @@ define([
</div> </div>
) : null} ) : null}
<div className="StudentContextTray-Header__CourseName"> <div className="StudentContextTray-Header__CourseName">
<Typography size="medium" tag="div" lineHeight="condensed"> <Typography size="medium" as="div" lineHeight="condensed">
{this.state.course.name} {this.state.course.name}
</Typography> </Typography>
</div> </div>
<Typography size="x-small" color="secondary" tag="div"> <Typography size="x-small" color="secondary" as="div">
<SectionInfo course={this.state.course} user={this.state.user} /> <SectionInfo course={this.state.course} user={this.state.user} />
</Typography> </Typography>
<Typography size="x-small" color="secondary" tag="div"> <Typography size="x-small" color="secondary" as="div">
<LastActivity user={this.state.user} /> <LastActivity user={this.state.user} />
</Typography> </Typography>
</div> </div>
@ -280,7 +280,7 @@ define([
{Object.keys(this.state.analytics).length > 0 ? ( {Object.keys(this.state.analytics).length > 0 ? (
<section <section
className="StudentContextTray__Section StudentContextTray-Ratings"> className="StudentContextTray__Section StudentContextTray-Ratings">
<Heading level="h4" tag="h3" border="bottom"> <Heading level="h4" as="h3" border="bottom">
{I18n.t("Activity Compared to Class")} {I18n.t("Activity Compared to Class")}
</Heading> </Heading>
<div className="StudentContextTray-Ratings__Layout"> <div className="StudentContextTray-Ratings__Layout">
@ -301,13 +301,5 @@ define([
) )
} }
} }
return StudentContextTray;
const DeleteMe = (props) => (
<ApplyTheme theme={ApplyTheme.generateTheme('a11y')}>
<StudentContextTray {...props}/>
</ApplyTheme>
)
/* TODO: after instui gets updated, just return StudentContextTray */
return ENV.use_high_contrast ? DeleteMe : StudentContextTray
}) })

View File

@ -71,7 +71,7 @@ define([
return ( return (
<section <section
className="StudentContextTray__Section StudentContextTray-Progress"> className="StudentContextTray__Section StudentContextTray-Progress">
<Heading level="h4" tag="h3" border="bottom"> <Heading level="h4" as="h3" border="bottom">
{I18n.t("Last %{length} Graded Items", {length: submissions.length})} {I18n.t("Last %{length} Graded Items", {length: submissions.length})}
</Heading> </Heading>
{submissions.map((submission) => { {submissions.map((submission) => {

View File

@ -129,7 +129,7 @@ define([
renderBodyContent () { renderBodyContent () {
if (this.props.courses.length > 0) { if (this.props.courses.length > 0) {
return [( return [(
<ScreenReaderContent key="select-all" tag="tr"> <ScreenReaderContent key="select-all" as="tr">
<td> <td>
<Checkbox <Checkbox
onChange={this.onSelectAllToggle} onChange={this.onSelectAllToggle}
@ -154,7 +154,7 @@ define([
// in order to create a sticky table header, we'll create a separate table with // in order to create a sticky table header, we'll create a separate table with
// just the visual sticky headers, that will be hidden from screen readers // just the visual sticky headers, that will be hidden from screen readers
return ( return (
<PresentationContent tagName="div"> <PresentationContent as="div">
<div className="btps-table__header-wrapper"> <div className="btps-table__header-wrapper">
<Table caption={<ScreenReaderContent>{I18n.t('Blueprint Courses')}</ScreenReaderContent>}> <Table caption={<ScreenReaderContent>{I18n.t('Blueprint Courses')}</ScreenReaderContent>}>
{this.renderColGroup()} {this.renderColGroup()}
@ -193,7 +193,7 @@ define([
<Table caption={<ScreenReaderContent>{I18n.t('Blueprint Courses')}</ScreenReaderContent>}> <Table caption={<ScreenReaderContent>{I18n.t('Blueprint Courses')}</ScreenReaderContent>}>
{this.renderColGroup()} {this.renderColGroup()}
{/* on the real table, we'll include the headers again, but make them screen reader only */} {/* on the real table, we'll include the headers again, but make them screen reader only */}
<ScreenReaderContent tag="thead"> <ScreenReaderContent as="thead">
{this.renderHeaders()} {this.renderHeaders()}
</ScreenReaderContent> </ScreenReaderContent>
<tbody className="bps-table__body"> <tbody className="bps-table__body">

View File

@ -73,7 +73,7 @@ define([
static renderMutedIcon (screenreaderText) { static renderMutedIcon (screenreaderText) {
return ( return (
<Typography weight="bold" style="normal" size="small" color="error"> <Typography weight="bold" fontStyle="normal" size="small" color="error">
<IconMutedSolid title={screenreaderText} /> <IconMutedSolid title={screenreaderText} />
</Typography> </Typography>
); );
@ -81,7 +81,7 @@ define([
static renderWarningIcon (screenreaderText) { static renderWarningIcon (screenreaderText) {
return ( return (
<Typography weight="bold" style="normal" size="small" color="brand"> <Typography weight="bold" fontStyle="normal" size="small" color="brand">
<IconWarningSolid title={screenreaderText} /> <IconWarningSolid title={screenreaderText} />
</Typography> </Typography>
); );
@ -163,7 +163,7 @@ define([
<div className="Gradebook__ColumnHeaderContent"> <div className="Gradebook__ColumnHeaderContent">
<span className="Gradebook__ColumnHeaderDetail"> <span className="Gradebook__ColumnHeaderDetail">
{this.renderAssignmentLink()} {this.renderAssignmentLink()}
<Typography weight="normal" style="normal" size="x-small"> <Typography weight="normal" fontStyle="normal" size="x-small">
{this.renderPointsPossible()} {this.renderPointsPossible()}
</Typography> </Typography>
</span> </span>

View File

@ -30,7 +30,7 @@ define([
const weightDesc = I18n.t('%{weight} of grade', { weight: weightStr }); const weightDesc = I18n.t('%{weight} of grade', { weight: weightStr });
return ( return (
<Typography weight="normal" style="normal" size="x-small"> <Typography weight="normal" fontStyle="normal" size="x-small">
{weightDesc} {weightDesc}
</Typography> </Typography>
); );
@ -50,7 +50,7 @@ define([
zIndex="9999" zIndex="9999"
trigger={ trigger={
<span className="Gradebook__ColumnHeaderAction"> <span className="Gradebook__ColumnHeaderAction">
<Typography weight="bold" style="normal" size="large" color="brand"> <Typography weight="bold" fontStyle="normal" size="large" color="brand">
<IconMoreSolid title={optionsTitle} /> <IconMoreSolid title={optionsTitle} />
</Typography> </Typography>
</span> </span>

View File

@ -20,7 +20,7 @@ define([
return ( return (
<div className="Gradebook__ColumnHeaderContent"> <div className="Gradebook__ColumnHeaderContent">
<span className="Gradebook__ColumnHeaderDetail"> <span className="Gradebook__ColumnHeaderDetail">
<Typography weight="normal" style="normal" size="small"> <Typography weight="normal" fontStyle="normal" size="small">
{ I18n.t('Student Name') } { I18n.t('Student Name') }
</Typography> </Typography>
</span> </span>
@ -29,7 +29,7 @@ define([
zIndex="9999" zIndex="9999"
trigger={ trigger={
<span className="Gradebook__ColumnHeaderAction"> <span className="Gradebook__ColumnHeaderAction">
<Typography weight="bold" style="normal" size="large" color="brand"> <Typography weight="bold" fontStyle="normal" size="large" color="brand">
<IconMoreSolid title={I18n.t('Student Name Options')} /> <IconMoreSolid title={I18n.t('Student Name Options')} />
</Typography> </Typography>
</span> </span>

View File

@ -20,7 +20,7 @@ define([
return ( return (
<div className="Gradebook__ColumnHeaderContent"> <div className="Gradebook__ColumnHeaderContent">
<span className="Gradebook__ColumnHeaderDetail"> <span className="Gradebook__ColumnHeaderDetail">
<Typography weight="normal" style="normal" size="small"> <Typography weight="normal" fontStyle="normal" size="small">
{ I18n.t('Total') } { I18n.t('Total') }
</Typography> </Typography>
</span> </span>
@ -29,7 +29,7 @@ define([
zIndex="9999" zIndex="9999"
trigger={ trigger={
<span className="Gradebook__ColumnHeaderAction"> <span className="Gradebook__ColumnHeaderAction">
<Typography weight="bold" style="normal" size="large" color="brand"> <Typography weight="bold" fontStyle="normal" size="large" color="brand">
<IconMoreSolid title={I18n.t('Total Options')} /> <IconMoreSolid title={I18n.t('Total Options')} />
</Typography> </Typography>
</span> </span>

View File

@ -5,11 +5,11 @@ define([
], (React, I18n, { Typography, Heading }) => { ], (React, I18n, { Typography, Heading }) => {
const HomeTray = () => ( const HomeTray = () => (
<div> <div>
<Heading tag="h2" level="h1" >{I18n.t('Home')}</Heading> <Heading as="h2" level="h1" >{I18n.t('Home')}</Heading>
<Typography size="large" tag="p"> <Typography size="large" as="p">
{I18n.t('This is your course landing page!')} {I18n.t('This is your course landing page!')}
</Typography> </Typography>
<Typography tag="p"> <Typography as="p">
{ {
I18n.t("When people visit your course, this is the first page they'll see. " + I18n.t("When people visit your course, this is the first page they'll see. " +
"We've set your home page to Modules, but you have the option to change it.") "We've set your home page to Modules, but you have the option to change it.")

View File

@ -5,7 +5,7 @@ define([
], (React, I18n, { Heading }) => { ], (React, I18n, { Heading }) => {
const HomeTray = () => ( const HomeTray = () => (
<div> <div>
<Heading tag="h2" level="h1" >{I18n.t('Modules')}</Heading> <Heading as="h2" level="h1" >{I18n.t('Modules')}</Heading>
</div> </div>
); );

View File

@ -223,13 +223,8 @@ define([
return null return null
} }
const onTextInputChange = (field) => { const onTextChange = field =>
return (e) => this.handleChange(field, e.target.value) e => this.handleChange(field, e.target.value)
}
const onTextAreaChange = (field) => {
return (value) => this.handleChange(field, value)
}
const tokens = this.state.data.recipients.map((recipient) => { const tokens = this.state.data.recipients.map((recipient) => {
const displayName = recipient.displayName || recipient.email const displayName = recipient.displayName || recipient.email
@ -277,7 +272,7 @@ define([
<TextInput <TextInput
label={I18n.t("Subject")} label={I18n.t("Subject")}
defaultValue={this.props.subject} defaultValue={this.props.subject}
onChange={onTextInputChange('subject')} onChange={onTextChange('subject')}
messages={this.errorMessagesFor('subject')} messages={this.errorMessagesFor('subject')}
disabled={this.state.sending || this.state.success} disabled={this.state.sending || this.state.success}
/> />
@ -286,7 +281,7 @@ define([
<TextArea <TextArea
label={I18n.t("Body")} label={I18n.t("Body")}
defaultValue={this.props.body} defaultValue={this.props.body}
onChange={onTextAreaChange('body')} onChange={onTextChange('body')}
messages={this.errorMessagesFor('body')} messages={this.errorMessagesFor('body')}
disabled={this.state.sending || this.state.success} disabled={this.state.sending || this.state.success}
/> />

View File

@ -69,21 +69,12 @@
.peoplesearch__instructions { .peoplesearch__instructions {
margin: 1.5em 0; margin: 1.5em 0;
text-align: center; text-align: center;
i.icon-user { .usericon {
display:block;
height: 50px;
margin: 0 auto; margin: 0 auto;
}
i.icon-user::before {
font-size: 48px; font-size: 48px;
line-height: 50px;
} }
} }
/* need a little space between inline inst-ui <RadioInput>s */
label[for^='peoplesearch_radio'] {
margin-right: 1em;
}
} }
.namelist { .namelist {
margin: 1.5em 0; margin: 1.5em 0;

View File

@ -93,6 +93,7 @@ module.exports = {
// once we are all-webpack we should remove this line and just change all the 'require's // once we are all-webpack we should remove this line and just change all the 'require's
// to instructure-ui compnentns to have the right path // to instructure-ui compnentns to have the right path
'instructure-ui': path.resolve(__dirname, '../node_modules/instructure-ui/lib/components'), 'instructure-ui': path.resolve(__dirname, '../node_modules/instructure-ui/lib/components'),
'instructure-ui-themes': path.resolve(__dirname, '../node_modules/instructure-ui/lib/themes'),
backbone: 'Backbone', backbone: 'Backbone',
timezone$: 'timezone_core', timezone$: 'timezone_core',

View File

@ -75,6 +75,7 @@ module Canvas
{name: 'ic-ajax', location: 'symlink_to_node_modules/ic-ajax/dist/amd'}, {name: 'ic-ajax', location: 'symlink_to_node_modules/ic-ajax/dist/amd'},
{name: 'ic-tabs', location: 'symlink_to_node_modules/ic-tabs'}, {name: 'ic-tabs', location: 'symlink_to_node_modules/ic-tabs'},
{name: 'instructure-ui', location: 'symlink_to_node_modules/instructure-ui/dist', main: 'instructure-ui'}, {name: 'instructure-ui', location: 'symlink_to_node_modules/instructure-ui/dist', main: 'instructure-ui'},
{name: 'instructure-ui-themes', location: 'symlink_to_node_modules/instructure-ui/dist/themes'},
{name: 'instructure-icons', location: 'symlink_to_node_modules/instructure-icons', main: 'react/index'}, {name: 'instructure-icons', location: 'symlink_to_node_modules/instructure-icons', main: 'react/index'},
{name: 'lodash', location: 'symlink_to_node_modules/lodash', main: 'lodash'}, {name: 'lodash', location: 'symlink_to_node_modules/lodash', main: 'lodash'},
{name: 'moxios', location: 'symlink_to_node_modules/moxios', main: 'dist/moxios'}, {name: 'moxios', location: 'symlink_to_node_modules/moxios', main: 'dist/moxios'},

View File

@ -5,19 +5,17 @@
"engines": { "engines": {
"node": "0.12 || >=6.3" "node": "0.12 || >=6.3"
}, },
"dependencies": "only the things that need to be on the job servers in prod so they can generate brand css when someone uses the theme editor. (brandable_css and things that include css files that we @import from our scss files)",
"dependencies": { "dependencies": {
"brandable_css": "0.0.68", "brandable_css": "0.0.68",
"canvas_offline_course_viewer": "https://github.com/instructure/canvas_offline_course_viewer.git#0.2.1", "canvas_offline_course_viewer": "https://github.com/instructure/canvas_offline_course_viewer.git#0.2.1",
"fullcalendar": "https://github.com/ryankshaw/fullcalendar.git#aa686b36d10cee1e1e3ec7c7784145e46667d47d", "fullcalendar": "https://github.com/ryankshaw/fullcalendar.git#aa686b36d10cee1e1e3ec7c7784145e46667d47d",
"instructure-ui": "0.18.2-bugfix.12",
"instructure-icons": "1.2.1", "instructure-icons": "1.2.1",
"instructure-ui": "1.0.1",
"tinymce": "4.1.9" "tinymce": "4.1.9"
}, },
"devDependencies": "the first group is all the things our build tooling needs",
"devDependencies": "the second group is the client-side stuff we send to browsers",
"devDependencies": { "devDependencies": {
"axe-core": "2.1.7", "axe-core": "2.1.7",
"axios": "0.15.2",
"babel-cli": "^6.10.1", "babel-cli": "^6.10.1",
"babel-core": "^6.10.4", "babel-core": "^6.10.4",
"babel-eslint": "^7.1.0", "babel-eslint": "^7.1.0",
@ -28,11 +26,15 @@
"babel-preset-react": "^6.11.1", "babel-preset-react": "^6.11.1",
"babel-preset-stage-1": "^6.5.0", "babel-preset-stage-1": "^6.5.0",
"babel-register": "^6.9.0", "babel-register": "^6.9.0",
"backbone": "1.1.1",
"classnames": "~2.2.5",
"coffee-loader": "^0.7.2", "coffee-loader": "^0.7.2",
"coffee-script": "1.6.2", "coffee-script": "1.6.2",
"color-slicer": "0.8.0",
"compute-cluster": "0.0.9", "compute-cluster": "0.0.9",
"core-js-builder": "^2.4.1", "core-js-builder": "^2.4.1",
"css-loader": "0.26.1", "css-loader": "0.26.1",
"d3": "3.4.1",
"ember-template-compiler": "^1.8.0", "ember-template-compiler": "^1.8.0",
"enzyme": "2.7.1", "enzyme": "2.7.1",
"eslint": "^3.13.0", "eslint": "^3.13.0",
@ -44,13 +46,17 @@
"eslint-plugin-react": "^6.9.0", "eslint-plugin-react": "^6.9.0",
"exports-loader": "^0.6.2", "exports-loader": "^0.6.2",
"expose-loader": "^0.7.0", "expose-loader": "^0.7.0",
"fontfaceobserver": "^2.0.8",
"gglobby": "0.0.3", "gglobby": "0.0.3",
"glob": "^7.0.3", "glob": "^7.0.3",
"gulp": "^3.9", "gulp": "^3.9",
"gulp-load-plugins": "^1.5.0", "gulp-load-plugins": "^1.5.0",
"gulp-rev": "^7.0.0", "gulp-rev": "^7.0.0",
"happypack": "^3.0.2", "handlebars": "1.3.0",
"handlebars-loader": "^1.1.4", "handlebars-loader": "^1.1.4",
"happypack": "^3.0.2",
"ic-ajax": "~2.0.1",
"ic-tabs": "0.1.3",
"imports-loader": "0.7.0", "imports-loader": "0.7.0",
"istanbul-instrumenter-loader": "0.2.0", "istanbul-instrumenter-loader": "0.2.0",
"json-loader": "^0.5.3", "json-loader": "^0.5.3",
@ -81,7 +87,6 @@
"axios": "0.15.2",
"backbone": "1.1.1", "backbone": "1.1.1",
"classnames": "~2.2.5", "classnames": "~2.2.5",
"color-slicer": "0.8.0", "color-slicer": "0.8.0",
@ -95,16 +100,18 @@
"moxios": "^0.3.0", "moxios": "^0.3.0",
"page": "visionmedia/page.js#1.6.4", "page": "visionmedia/page.js#1.6.4",
"parse-decimal-number": "0.1.1", "parse-decimal-number": "0.1.1",
"phantomjs-prebuilt": "^2.1.4",
"qs": "https://github.com/hapijs/qs.git#a341cdf2fadba5ede1ce6c95c7051f6f31f37b81", "qs": "https://github.com/hapijs/qs.git#a341cdf2fadba5ede1ce6c95c7051f6f31f37b81",
"qunitjs": "^1.14.0",
"react": "0.14.8", "react": "0.14.8",
"react-crop": "^4.0.2",
"react-dom": "0.14.8",
"react-dnd": "2.1.4",
"react-dnd-html5-backend": "2.1.2",
"react-addons-css-transition-group": "0.14.8", "react-addons-css-transition-group": "0.14.8",
"react-addons-pure-render-mixin": "0.14.8", "react-addons-pure-render-mixin": "0.14.8",
"react-addons-test-utils": "0.14.8", "react-addons-test-utils": "0.14.8",
"react-addons-update": "0.14.8", "react-addons-update": "0.14.8",
"react-crop": "^4.0.2",
"react-dnd": "2.1.4",
"react-dnd-html5-backend": "2.1.2",
"react-dom": "0.14.8",
"react-modal": "1.6.5", "react-modal": "1.6.5",
"react-redux": "4.4.5", "react-redux": "4.4.5",
"react-select-box": "https://github.com/instructure-react/react-select-box.git#b1ddd39223d48793fbe3dc4e87aca00d57197b5f", "react-select-box": "https://github.com/instructure-react/react-select-box.git#b1ddd39223d48793fbe3dc4e87aca00d57197b5f",
@ -115,7 +122,17 @@
"redux-actions": "0.11.0", "redux-actions": "0.11.0",
"redux-logger": "2.6.1", "redux-logger": "2.6.1",
"redux-thunk": "2.1.0", "redux-thunk": "2.1.0",
"spin.js": "2.3.2" "requirejs": "~2.2.0",
"script-loader": "^0.7.0",
"sinon": "2.0.0-pre.5",
"spin.js": "2.3.2",
"style-loader": "^0.13.1",
"stylelint": "7.8.0",
"timezone": "1.0.5",
"uglify-js": "~2.7.0",
"webpack": "2.2.1",
"webpack-manifest-plugin": "^1.0.1",
"webpack-parallel-uglify-plugin": "0.2.0"
}, },
"repository": "instructure/canvas-lms", "repository": "instructure/canvas-lms",
"scripts": { "scripts": {

View File

@ -38,15 +38,14 @@ define([
/>) />)
const missingPeopleSection = TestUtils.findRenderedDOMComponentWithClass(component, 'namelist') const missingPeopleSection = TestUtils.findRenderedDOMComponentWithClass(component, 'namelist')
const rows = missingPeopleSection.querySelectorAll('tr'); const headings = missingPeopleSection.querySelectorAll('thead tr th');
equal(rows.length, 3, 'three rows')
const headings = rows[0].querySelectorAll('th');
equal(headings.length, 4, 'four column headings'); equal(headings.length, 4, 'four column headings');
const createUserBtn = rows[1].querySelectorAll('td')[1].firstChild; const rows = missingPeopleSection.querySelectorAll('tbody tr');
equal(createUserBtn.tagName, 'BUTTON', 'create new user button'); const createUserBtn = rows[0].querySelectorAll('td')[1].querySelector('button')
const nameInput = rows[2].querySelector('input[type="text"]'); equal(createUserBtn.innerHTML, 'Click to add a name', 'create new user button');
const nameInput = rows[1].querySelector('input[type="text"]');
ok(nameInput, 'name input'); ok(nameInput, 'name input');
const emailInput = rows[2].querySelector('input[type="email"]'); const emailInput = rows[1].querySelector('input[type="email"]');
ok(emailInput, 'email input'); ok(emailInput, 'email input');
}); });
test('cannot create users because we don\'t have the URL', () => { test('cannot create users because we don\'t have the URL', () => {

View File

@ -36,7 +36,7 @@ define([
...previousExportProps() ...previousExportProps()
}; };
this.wrapper = mount(<ActionMenu {...propsWithPreviousExport} />); this.wrapper = mount(<ActionMenu {...propsWithPreviousExport} />);
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
}, },
teardown () { teardown () {
@ -163,7 +163,7 @@ define([
this.wrapper = mount(<ActionMenu {...workingMenuProps()} />, { attachTo: document.querySelector('#fixture')}); this.wrapper = mount(<ActionMenu {...workingMenuProps()} />, { attachTo: document.querySelector('#fixture')});
this.trigger = this.wrapper.find('PopoverMenu'); this.trigger = this.wrapper.find('button');
this.trigger.simulate('click'); this.trigger.simulate('click');
this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]'); this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]');
@ -211,7 +211,7 @@ define([
this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]'); this.menuItem = document.querySelector('[role="menuitem"] [data-menu-id="export"]');
equal(this.menuItem.textContent, 'Export in progress'); equal(this.menuItem.textContent, 'Export in progress');
equal(this.menuItem.parentElement.getAttribute('aria-disabled'), 'true'); equal(this.menuItem.parentElement.parentElement.getAttribute('aria-disabled'), 'true');
return exportResult; return exportResult;
}); });
@ -303,7 +303,7 @@ define([
this.spies.gotoUrl = this.stub(ActionMenu, 'gotoUrl'); this.spies.gotoUrl = this.stub(ActionMenu, 'gotoUrl');
this.wrapper = mount(<ActionMenu {...workingMenuProps()} />); this.wrapper = mount(<ActionMenu {...workingMenuProps()} />);
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
this.menuItem = document.querySelectorAll('[role="menuitem"] [data-menu-id="import"]')[0]; this.menuItem = document.querySelectorAll('[role="menuitem"] [data-menu-id="import"]')[0];
}, },

View File

@ -105,9 +105,12 @@ define([
title: undefined, title: undefined,
href: createAssignmentProp().htmlUrl href: createAssignmentProp().htmlUrl
}; };
const actualProps = actualElements.props();
equal(actualElements.length, 1); equal(actualElements.length, 1);
deepEqual(actualElements.props(), expectedLinkProps); deepEqual(actualProps.children, expectedLinkProps.children);
equal(actualProps.title, expectedLinkProps.title);
equal(actualProps.href, expectedLinkProps.href);
}); });
test('renders the points possible', function () { test('renders the points possible', function () {
@ -164,28 +167,28 @@ define([
test('shows the menu item in an enabled state', function () { test('shows the menu item in an enabled state', function () {
this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />); this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />);
this.renderOutput.find('PopoverMenu').simulate('click'); this.renderOutput.find('.Gradebook__ColumnHeaderAction').simulate('click');
const specificMenuItem = document.querySelector('[data-menu-item-id="show-assignment-details"]'); const specificMenuItem = document.querySelector('[data-menu-item-id="show-assignment-details"]');
equal(specificMenuItem.textContent, 'Assignment Details'); equal(specificMenuItem.textContent, 'Assignment Details');
notOk(specificMenuItem.parentElement.getAttribute('aria-disabled')); notOk(specificMenuItem.parentElement.parentElement.getAttribute('aria-disabled'));
}); });
test('disables the menu item when the disabled prop is true', function () { test('disables the menu item when the disabled prop is true', function () {
this.props.assignmentDetailsAction.disabled = true; this.props.assignmentDetailsAction.disabled = true;
this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />); this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />);
this.renderOutput.find('PopoverMenu').simulate('click'); this.renderOutput.find('.Gradebook__ColumnHeaderAction').simulate('click');
const specificMenuItem = document.querySelector('[data-menu-item-id="show-assignment-details"]'); const specificMenuItem = document.querySelector('[data-menu-item-id="show-assignment-details"]');
equal(specificMenuItem.parentElement.getAttribute('aria-disabled'), 'true'); equal(specificMenuItem.parentElement.parentElement.getAttribute('aria-disabled'), 'true');
}); });
test('clicking the menu item invokes the Assignment Details dialog', function () { test('clicking the menu item invokes the Assignment Details dialog', function () {
this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />); this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />);
this.renderOutput.find('PopoverMenu').simulate('click'); this.renderOutput.find('.Gradebook__ColumnHeaderAction').simulate('click');
const specificMenuItem = document.querySelector('[data-menu-item-id="show-assignment-details"]'); const specificMenuItem = document.querySelector('[data-menu-item-id="show-assignment-details"]');
@ -206,7 +209,7 @@ define([
submissionsLoaded submissionsLoaded
/> />
); );
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('.Gradebook__ColumnHeaderAction').simulate('click');
const menuItem = document.querySelector('[data-menu-item-id="curve-grades"]'); const menuItem = document.querySelector('[data-menu-item-id="curve-grades"]');
menuItem.click(); menuItem.click();
return menuItem; return menuItem;
@ -221,17 +224,17 @@ define([
const menuItem = this.setupAndClick(); const menuItem = this.setupAndClick();
equal(menuItem.textContent, 'Curve Grades'); equal(menuItem.textContent, 'Curve Grades');
notOk(menuItem.parentElement.getAttribute('aria-disabled')); notOk(menuItem.parentElement.parentElement.getAttribute('aria-disabled'));
}); });
test('Curve Grades menu item is disabled when isDisabled is true', function () { test('Curve Grades menu item is disabled when isDisabled is true', function () {
const menuItem = this.setupAndClick({ isDisabled: true }); const menuItem = this.setupAndClick({ isDisabled: true });
ok(menuItem.parentElement.getAttribute('aria-disabled')); ok(menuItem.parentElement.parentElement.getAttribute('aria-disabled'));
}); });
test('Curve Grades menu item is enabled when isDisabled is false', function () { test('Curve Grades menu item is enabled when isDisabled is false', function () {
const menuItem = this.setupAndClick({ isDisabled: false }); const menuItem = this.setupAndClick({ isDisabled: false });
notOk(menuItem.parentElement.getAttribute('aria-disabled')); notOk(menuItem.parentElement.parentElement.getAttribute('aria-disabled'));
}); });
test('onSelect is called when menu item is clicked', function () { test('onSelect is called when menu item is clicked', function () {
@ -268,25 +271,25 @@ define([
test('shows the menu item in an enabled state', function () { test('shows the menu item in an enabled state', function () {
this.wrapper = mount(<AssignmentColumnHeader {...this.props} />); this.wrapper = mount(<AssignmentColumnHeader {...this.props} />);
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('.Gradebook__ColumnHeaderAction').simulate('click');
const menuItem = document.querySelector('[data-menu-item-id="message-students-who"]'); const menuItem = document.querySelector('[data-menu-item-id="message-students-who"]');
equal(menuItem.textContent, 'Message Students Who'); equal(menuItem.textContent, 'Message Students Who');
notOk(menuItem.parentElement.getAttribute('aria-disabled')); notOk(menuItem.parentElement.parentElement.getAttribute('aria-disabled'));
}); });
test('disables the menu item when submissions are not loaded', function () { test('disables the menu item when submissions are not loaded', function () {
this.props.submissionsLoaded = false; this.props.submissionsLoaded = false;
this.wrapper = mount(<AssignmentColumnHeader {...this.props} />); this.wrapper = mount(<AssignmentColumnHeader {...this.props} />);
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('.Gradebook__ColumnHeaderAction').simulate('click');
const menuItem = document.querySelector('[data-menu-item-id="message-students-who"]'); const menuItem = document.querySelector('[data-menu-item-id="message-students-who"]');
equal(menuItem.parentElement.getAttribute('aria-disabled'), 'true'); equal(menuItem.parentElement.parentElement.getAttribute('aria-disabled'), 'true');
}); });
test('clicking the menu item invokes the Message Students Who dialog', function () { test('clicking the menu item invokes the Message Students Who dialog', function () {
this.wrapper = mount(<AssignmentColumnHeader {...this.props} />); this.wrapper = mount(<AssignmentColumnHeader {...this.props} />);
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('.Gradebook__ColumnHeaderAction').simulate('click');
const messageStudentsStub = this.stub(window, 'messageStudents'); const messageStudentsStub = this.stub(window, 'messageStudents');
const menuItem = document.querySelector('[data-menu-item-id="message-students-who"]'); const menuItem = document.querySelector('[data-menu-item-id="message-students-who"]');
menuItem.click(); menuItem.click();
@ -394,7 +397,7 @@ define([
test('shows the menu item in an enabled state', function () { test('shows the menu item in an enabled state', function () {
this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />); this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />);
this.renderOutput.find('PopoverMenu').simulate('click'); this.renderOutput.find('.Gradebook__ColumnHeaderAction').simulate('click');
const specificMenuItem = document.querySelector('[data-menu-item-id="set-default-grade"]'); const specificMenuItem = document.querySelector('[data-menu-item-id="set-default-grade"]');
@ -406,16 +409,16 @@ define([
this.props.setDefaultGradeAction.disabled = true; this.props.setDefaultGradeAction.disabled = true;
this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />); this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />);
this.renderOutput.find('PopoverMenu').simulate('click'); this.renderOutput.find('.Gradebook__ColumnHeaderAction').simulate('click');
const specificMenuItem = document.querySelector('[data-menu-item-id="set-default-grade"]'); const specificMenuItem = document.querySelector('[data-menu-item-id="set-default-grade"]');
equal(specificMenuItem.parentElement.getAttribute('aria-disabled'), 'true'); equal(specificMenuItem.parentElement.parentElement.getAttribute('aria-disabled'), 'true');
}); });
test('clicking the menu item invokes the onSelect handler', function () { test('clicking the menu item invokes the onSelect handler', function () {
this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />); this.renderOutput = mount(<AssignmentColumnHeader {...this.props} />);
this.renderOutput.find('PopoverMenu').simulate('click'); this.renderOutput.find('.Gradebook__ColumnHeaderAction').simulate('click');
const specificMenuItem = document.querySelector('[data-menu-item-id="set-default-grade"]'); const specificMenuItem = document.querySelector('[data-menu-item-id="set-default-grade"]');

View File

@ -44,7 +44,7 @@ define([
test('#handleIndividualGradebookSelect calls setLocation', function () { test('#handleIndividualGradebookSelect calls setLocation', function () {
const setLocationStub = this.stub(GradebookMenu.prototype, 'setLocation'); const setLocationStub = this.stub(GradebookMenu.prototype, 'setLocation');
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
document.querySelector('[data-menu-item-id="individual-gradebook"]').click(); document.querySelector('[data-menu-item-id="individual-gradebook"]').click();
const url = `${this.wrapper.props().courseUrl}/gradebook/change_gradebook_version?version=individual`; const url = `${this.wrapper.props().courseUrl}/gradebook/change_gradebook_version?version=individual`;
ok(setLocationStub.withArgs(url).calledOnce); ok(setLocationStub.withArgs(url).calledOnce);
@ -52,7 +52,7 @@ define([
test('#handleGradeHistorySelect calls setLocation', function () { test('#handleGradeHistorySelect calls setLocation', function () {
const setLocationStub = this.stub(GradebookMenu.prototype, 'setLocation'); const setLocationStub = this.stub(GradebookMenu.prototype, 'setLocation');
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
document.querySelector('[data-menu-item-id="grade-history"]').click(); document.querySelector('[data-menu-item-id="grade-history"]').click();
const url = `${this.wrapper.props().courseUrl}/gradebook/history`; const url = `${this.wrapper.props().courseUrl}/gradebook/history`;
ok(setLocationStub.withArgs(url).calledOnce); ok(setLocationStub.withArgs(url).calledOnce);
@ -69,7 +69,7 @@ define([
navigate={this.navigateStub} navigate={this.navigateStub}
/> />
); );
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
this.menuItems = document.querySelector('[role="menu"]').children; this.menuItems = document.querySelector('[role="menu"]').children;
}, },
teardown () { teardown () {
@ -108,7 +108,7 @@ define([
navigate={() => {}} navigate={() => {}}
/> />
); );
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
this.menuItems = document.querySelector('[role="menu"]').children; this.menuItems = document.querySelector('[role="menu"]').children;
}, },
teardown () { teardown () {
@ -139,7 +139,7 @@ define([
navigate={this.navigateStub} navigate={this.navigateStub}
/> />
); );
this.wrapper.find('PopoverMenu').simulate('click'); this.wrapper.find('button').simulate('click');
this.menuItems = document.querySelector('[role="menu"]').children; this.menuItems = document.querySelector('[role="menu"]').children;
}, },
teardown () { teardown () {

View File

@ -34,3 +34,12 @@ requirejs.config({
deps: thingsToLoadWithRequireJS, // dynamically load all test files deps: thingsToLoadWithRequireJS, // dynamically load all test files
callback: window.__karma__.start callback: window.__karma__.start
}); });
require(['instructure-ui/ApplyTheme', 'instructure-ui-themes/canvas'],
function(ApplyTheme) {
if (ENV.use_high_contrast) {
ApplyTheme.defualt.setDefaultTheme('canvas-a11y')
} else {
ApplyTheme.default.setDefaultTheme('canvas')
}
});

View File

@ -1,4 +1,6 @@
import 'vendor/ie11-polyfill.js' import 'vendor/ie11-polyfill.js'
import ApplyTheme from 'instructure-ui/ApplyTheme'
import 'instructure-ui-themes/canvas'
import './support/sinon/sinon-qunit-1.0.0' import './support/sinon/sinon-qunit-1.0.0'
const fixturesDiv = document.createElement('div') const fixturesDiv = document.createElement('div')
@ -7,7 +9,16 @@ document.body.appendChild(fixturesDiv)
if (!window.ENV) window.ENV = {} if (!window.ENV) window.ENV = {}
const requireAll = requireContext => requireContext.keys().map(requireContext) // setup the inst-ui default theme
if (ENV.use_high_contrast) {
ApplyTheme.setDefaultTheme('canvas-a11y')
} else {
ApplyTheme.setDefaultTheme('canvas')
}
function requireAll (requireContext) {
return requireContext.keys().map(requireContext);
}
if (__SPEC_FILE) { if (__SPEC_FILE) {
require(__SPEC_FILE) require(__SPEC_FILE)

View File

@ -247,7 +247,7 @@ describe "Gradezilla" do
gradezilla_page.visit(@course) gradezilla_page.visit(@course)
# And I click the dropdown menu on the assignment # And I click the dropdown menu on the assignment
f('.gradebook-header-drop').click f('.Gradebook__ColumnHeaderAction').click
# And I click the download submissions button # And I click the download submissions button
f('[data-action="downloadSubmissions"]').click f('[data-action="downloadSubmissions"]').click
@ -256,7 +256,7 @@ describe "Gradezilla" do
fj("div:contains('Download Assignment Submissions'):first .ui-dialog-titlebar-close").click fj("div:contains('Download Assignment Submissions'):first .ui-dialog-titlebar-close").click
# And I click the dropdown menu on the assignment again # And I click the dropdown menu on the assignment again
f('.gradebook-header-drop').click f('.Gradebook__ColumnHeaderAction').click
# And I click the re-upload submissions link # And I click the re-upload submissions link
f('[data-action="reuploadSubmissions"]').click f('[data-action="reuploadSubmissions"]').click
@ -292,7 +292,7 @@ describe "Gradezilla" do
gradezilla_page.visit(@course) gradezilla_page.visit(@course)
f('.gradebook-header-drop').click f('.Gradebook__ColumnHeaderAction').click
expect(f('.gradebook-header-menu')).not_to include_text("SpeedGrader") expect(f('.gradebook-header-menu')).not_to include_text("SpeedGrader")
end end

115
yarn.lock
View File

@ -30,7 +30,7 @@ acorn-dynamic-import@^2.0.0:
dependencies: dependencies:
acorn "^4.0.3" acorn "^4.0.3"
acorn-jsx@^3.0.0: acorn-jsx@^3.0.0, acorn-jsx@^3.0.1:
version "3.0.1" version "3.0.1"
resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-3.0.1.tgz#afdf9488fb1ecefc8348f6fb22f464e32a58b36b"
dependencies: dependencies:
@ -987,7 +987,7 @@ babel-template@^6.22.0, babel-template@^6.23.0:
babylon "^6.11.0" babylon "^6.11.0"
lodash "^4.2.0" lodash "^4.2.0"
babel-traverse@^6.0.0, babel-traverse@^6.15.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1: babel-traverse@^6.15.0, babel-traverse@^6.22.0, babel-traverse@^6.23.0, babel-traverse@^6.23.1:
version "6.23.1" version "6.23.1"
resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48" resolved "https://registry.yarnpkg.com/babel-traverse/-/babel-traverse-6.23.1.tgz#d3cb59010ecd06a97d81310065f966b699e14f48"
dependencies: dependencies:
@ -1010,7 +1010,7 @@ babel-types@^6.15.0, babel-types@^6.19.0, babel-types@^6.22.0, babel-types@^6.23
lodash "^4.2.0" lodash "^4.2.0"
to-fast-properties "^1.0.1" to-fast-properties "^1.0.1"
babylon@^6.0.0, babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0: babylon@^6.11.0, babylon@^6.13.0, babylon@^6.15.0:
version "6.16.1" version "6.16.1"
resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3" resolved "https://registry.yarnpkg.com/babylon/-/babylon-6.16.1.tgz#30c5a22f481978a9e7f8cdfdf496b11d94b404d3"
@ -1394,7 +1394,7 @@ clap@^1.0.9:
dependencies: dependencies:
chalk "^1.1.3" chalk "^1.1.3"
classnames@2.2.5, classnames@^2.1.3, classnames@^2.2.0, classnames@^2.2.1, classnames@~2.2.5: classnames@2.2.5, classnames@^2.2.0, classnames@^2.2.1, classnames@~2.2.5:
version "2.2.5" version "2.2.5"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d" resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.5.tgz#fb3801d453467649ef3603c7d61a02bd129bde6d"
@ -2143,13 +2143,9 @@ doiuse@^2.4.1:
through2 "^0.6.3" through2 "^0.6.3"
yargs "^3.5.4" yargs "^3.5.4"
dom-helpers@3.0.0: dom-helpers@3.2.0:
version "3.0.0" version "3.2.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.0.0.tgz#124869cea3f09dbff84256fede7f36616ccfee23" resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.2.0.tgz#70af056e6b1507a71084abc1aac0f93a23f7ea1c"
dom-helpers@^2.3.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-2.4.0.tgz#9bb4b245f637367b1fa670274272aa28fe06c367"
dom-serialize@^2.2.0: dom-serialize@^2.2.0:
version "2.2.1" version "2.2.1"
@ -2244,6 +2240,12 @@ encodeurl@~1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
dependencies:
iconv-lite "~0.4.13"
end-of-stream@~0.1.5: end-of-stream@~0.1.5:
version "0.1.5" version "0.1.5"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf" resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-0.1.5.tgz#8e177206c3c80837d85632e8b9359dfe8b2f6eaf"
@ -2733,6 +2735,18 @@ fbjs@^0.6.1:
ua-parser-js "^0.7.9" ua-parser-js "^0.7.9"
whatwg-fetch "^0.9.0" whatwg-fetch "^0.9.0"
fbjs@^0.8.8:
version "0.8.9"
resolved "https://registry.yarnpkg.com/fbjs/-/fbjs-0.8.9.tgz#180247fbd347dcc9004517b904f865400a0c8f14"
dependencies:
core-js "^1.0.0"
isomorphic-fetch "^2.1.1"
loose-envify "^1.0.0"
object-assign "^4.1.0"
promise "^7.1.1"
setimmediate "^1.0.5"
ua-parser-js "^0.7.9"
fd-slicer@~1.0.1: fd-slicer@~1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65" resolved "https://registry.yarnpkg.com/fd-slicer/-/fd-slicer-1.0.1.tgz#8b5bcbd9ec327c5041bf9ab023fd6750f1177e65"
@ -3059,6 +3073,14 @@ gglobby@0.0.3:
version "0.0.3" version "0.0.3"
resolved "https://registry.yarnpkg.com/gglobby/-/gglobby-0.0.3.tgz#c7d686c1ff2ca4e882a58adf38a7de2691ba7f99" resolved "https://registry.yarnpkg.com/gglobby/-/gglobby-0.0.3.tgz#c7d686c1ff2ca4e882a58adf38a7de2691ba7f99"
glamor@2.20.22:
version "2.20.22"
resolved "https://registry.yarnpkg.com/glamor/-/glamor-2.20.22.tgz#86c11a143deee7d4c051de50d69387d8b4e700ba"
dependencies:
babel-runtime "^6.18.0"
fbjs "^0.8.8"
object-assign "^4.1.0"
glob-base@^0.3.0: glob-base@^0.3.0:
version "0.3.0" version "0.3.0"
resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4" resolved "https://registry.yarnpkg.com/glob-base/-/glob-base-0.3.0.tgz#dbb164f6221b1c0b1ccf82aea328b497df0ea3c4"
@ -3540,7 +3562,7 @@ ic-tabs@0.1.3:
dependencies: dependencies:
ic-styled "^1.1.6" ic-styled "^1.1.6"
iconv-lite@0.4.15, iconv-lite@^0.4.5: iconv-lite@0.4.15, iconv-lite@^0.4.5, iconv-lite@~0.4.13:
version "0.4.15" version "0.4.15"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb" resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.15.tgz#fe265a218ac6a57cfe854927e9d04c19825eddeb"
@ -3640,31 +3662,25 @@ install@~0.1.7:
version "0.1.8" version "0.1.8"
resolved "https://registry.yarnpkg.com/install/-/install-0.1.8.tgz#9980ef93e30dfb534778d163bc86ddd472ad5fe8" resolved "https://registry.yarnpkg.com/install/-/install-0.1.8.tgz#9980ef93e30dfb534778d163bc86ddd472ad5fe8"
instructure-icons@0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/instructure-icons/-/instructure-icons-0.1.0.tgz#4aba133373de129081579344c8d2b1ebba313bd8"
dependencies:
shortid "2.2.6"
instructure-icons@1.2.1: instructure-icons@1.2.1:
version "1.2.1" version "1.2.1"
resolved "https://registry.yarnpkg.com/instructure-icons/-/instructure-icons-1.2.1.tgz#6ae4e8de07ff6821192746bef79a2cab01a179be" resolved "https://registry.yarnpkg.com/instructure-icons/-/instructure-icons-1.2.1.tgz#6ae4e8de07ff6821192746bef79a2cab01a179be"
dependencies: dependencies:
shortid "2.2.6" shortid "2.2.6"
instructure-ui@0.18.2-bugfix.12: instructure-ui@1.0.1:
version "0.18.2-bugfix.12" version "1.0.1"
resolved "https://registry.yarnpkg.com/instructure-ui/-/instructure-ui-0.18.2-bugfix.12.tgz#95cee0932d9aafa3cb7b11ce92db9f5c32544dd4" resolved "https://registry.yarnpkg.com/instructure-ui/-/instructure-ui-1.0.1.tgz#9d84525fd6cd73c6f9168f1d36ca8001017b48e1"
dependencies: dependencies:
classnames "2.2.5" classnames "2.2.5"
deep-equal "1.0.1" deep-equal "1.0.1"
dom-helpers "3.0.0" dom-helpers "3.2.0"
instructure-icons "0.1.0" glamor "2.20.22"
instructure-icons "1.2.1"
invariant "2.2.2" invariant "2.2.2"
keycode "2.1.7" keycode "2.1.8"
object.omit "2.0.1" object.omit "2.0.1"
object.pick "1.2.0" object.pick "1.2.0"
react-overlays "0.6.3"
shortid "2.2.6" shortid "2.2.6"
tinycolor2 "1.4.1" tinycolor2 "1.4.1"
@ -3904,6 +3920,13 @@ isobject@^2.0.0, isobject@^2.1.0:
dependencies: dependencies:
isarray "1.0.0" isarray "1.0.0"
isomorphic-fetch@^2.1.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz#611ae1acf14f5e81f729507472819fe9733558a9"
dependencies:
node-fetch "^1.0.1"
whatwg-fetch ">=0.10.0"
isstream@~0.1.2: isstream@~0.1.2:
version "0.1.2" version "0.1.2"
resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a"
@ -4192,9 +4215,9 @@ kew@~0.7.0:
version "0.7.0" version "0.7.0"
resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b" resolved "https://registry.yarnpkg.com/kew/-/kew-0.7.0.tgz#79d93d2d33363d6fdd2970b335d9141ad591d79b"
keycode@2.1.7: keycode@2.1.8:
version "2.1.7" version "2.1.8"
resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.1.7.tgz#7b9255919f6cff562b09a064d222dca70b020f5c" resolved "https://registry.yarnpkg.com/keycode/-/keycode-2.1.8.tgz#94d2b7098215eff0e8f9a8931d5a59076c4532fb"
kind-of@^3.0.2: kind-of@^3.0.2:
version "3.1.0" version "3.1.0"
@ -4773,6 +4796,13 @@ neo-async@^1.0.0:
version "1.8.2" version "1.8.2"
resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-1.8.2.tgz#31795888b79dd04357a7c52113a65183e93b6735" resolved "https://registry.yarnpkg.com/neo-async/-/neo-async-1.8.2.tgz#31795888b79dd04357a7c52113a65183e93b6735"
node-fetch@^1.0.1:
version "1.6.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-gyp@^3.3.1: node-gyp@^3.3.1:
version "3.5.0" version "3.5.0"
resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.5.0.tgz#a8fe5e611d079ec16348a3eb960e78e11c85274a" resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-3.5.0.tgz#a8fe5e611d079ec16348a3eb960e78e11c85274a"
@ -5664,7 +5694,7 @@ progress@^1.1.8, progress@~1.1.8:
version "1.1.8" version "1.1.8"
resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be" resolved "https://registry.yarnpkg.com/progress/-/progress-1.1.8.tgz#e260c78f6161cdd9b0e56cc3e0a85de17c7a57be"
promise@^7.0.3: promise@^7.0.3, promise@^7.1.1:
version "7.1.1" version "7.1.1"
resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf" resolved "https://registry.yarnpkg.com/promise/-/promise-7.1.1.tgz#489654c692616b8aa55b0724fa809bb7db49c5bf"
dependencies: dependencies:
@ -5834,21 +5864,6 @@ react-modal@1.6.5:
exenv "1.2.0" exenv "1.2.0"
lodash.assign "^4.2.0" lodash.assign "^4.2.0"
react-overlays@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/react-overlays/-/react-overlays-0.6.3.tgz#e4e1f5b04b2cc5fc167083b9414ad42e9949b9bd"
dependencies:
classnames "^2.1.3"
dom-helpers "^2.3.0"
react-prop-types "^0.2.1"
warning "^2.1.0"
react-prop-types@^0.2.1:
version "0.2.2"
resolved "https://registry.yarnpkg.com/react-prop-types/-/react-prop-types-0.2.2.tgz#ae49914d4952382113d0e210b2e51016f0bd7f19"
dependencies:
warning "^2.0.0"
react-redux@4.4.5: react-redux@4.4.5:
version "4.4.5" version "4.4.5"
resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-4.4.5.tgz#f509a2981be2252d10c629ef7c559347a4aec457" resolved "https://registry.yarnpkg.com/react-redux/-/react-redux-4.4.5.tgz#f509a2981be2252d10c629ef7c559347a4aec457"
@ -6344,7 +6359,7 @@ set-immediate-shim@^1.0.1:
version "1.0.1" version "1.0.1"
resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61" resolved "https://registry.yarnpkg.com/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz#4b2b1b27eb808a9f8dcc481a58e5e56f599f3f61"
setimmediate@^1.0.4: setimmediate@^1.0.4, setimmediate@^1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285" resolved "https://registry.yarnpkg.com/setimmediate/-/setimmediate-1.0.5.tgz#290cbb232e306942d7d7ea9b83732ab7856f8285"
@ -7190,12 +7205,6 @@ vows@0.6.0:
dependencies: dependencies:
eyes ">=0.1.6" eyes ">=0.1.6"
warning@^2.0.0, warning@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/warning/-/warning-2.1.0.tgz#21220d9c63afc77a8c92111e011af705ce0c6901"
dependencies:
loose-envify "^1.0.0"
watchpack@^0.2.1: watchpack@^0.2.1:
version "0.2.9" version "0.2.9"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b" resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-0.2.9.tgz#62eaa4ab5e5ba35fdfc018275626e3c0f5e3fb0b"
@ -7297,6 +7306,10 @@ webpack@2.2.1:
webpack-sources "^0.1.4" webpack-sources "^0.1.4"
yargs "^6.0.0" yargs "^6.0.0"
whatwg-fetch@>=0.10.0:
version "2.0.3"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz#9c84ec2dcf68187ff00bc64e1274b442176e1c84"
whatwg-fetch@^0.9.0: whatwg-fetch@^0.9.0:
version "0.9.0" version "0.9.0"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-0.9.0.tgz#0e3684c6cb9995b43efc9df03e4c365d95fd9cc0"