Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added src/assets/images/flavour.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
50 changes: 32 additions & 18 deletions src/components/CourseList.js
Original file line number Diff line number Diff line change
Expand Up @@ -263,24 +263,37 @@ class CourseList extends Component {
</Grid>
<Grid container direction="column" justify="center" alignItems="stretch">
{
courses === null ? (
<Grid item container direction="row" justify="center">
<CircularProgress />
</Grid>
) : (
<Grid item>
<Box
className={classes.listContainer}
>
{
courses.results.map((course) => (
<Course key={course.id} course={course} onLessonClick={this.loadProgram} />
))
}
</Box>
</Grid>
)
}
courses === null ? (
<Grid item container direction="row" justify="center">
<CircularProgress />
</Grid>
) : (null)
}
{
courses && courses.count === 0 ? (
<Grid item container direction="row" alignItems="center" justify="center">
<Typography variant="h4">
<FormattedMessage
id="app.course_list.nothing"
description="Informs the user that no courses match the filters"
defaultMessage="Sorry, no courses match your filters."
/>
</Typography>
</Grid>
) : (
<Grid item>
<Box
className={classes.listContainer}
>
{
courses ? courses.results.map((course) => (
<Course key={course.id} course={course} onLessonClick={this.loadProgram} />
)) : (null)
}
</Box>
</Grid>
)
}
</Grid>
{
courses && courses.total_pages > 1 ? (
Expand Down Expand Up @@ -333,6 +346,7 @@ CourseList.propTypes = {
fetchProgram: PropTypes.func.isRequired,
changeReadOnly: PropTypes.func.isRequired,
courses: PropTypes.shape({
count: PropTypes.number,
next: PropTypes.string,
previous: PropTypes.string,
total_pages: PropTypes.number,
Expand Down
44 changes: 40 additions & 4 deletions src/components/ProgramCollection.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import React, { Component } from 'react';
import { Link } from 'react-router-dom';
import { FormattedMessage, injectIntl } from 'react-intl';
import PropTypes from 'prop-types';
import { hot } from 'react-hot-loader';
import {
Expand Down Expand Up @@ -27,8 +29,8 @@ import {
Delete,
} from '@material-ui/icons';
import { Pagination, Autocomplete } from '@material-ui/lab';
import { Link } from 'react-router-dom';
import { FormattedMessage, injectIntl } from 'react-intl';

import flavourImage from '@/assets/images/flavour.png';

const styles = (theme) => ({
mainContainer: {
Expand Down Expand Up @@ -139,7 +141,12 @@ class ProgramCollection extends Component {
tag,
classes,
} = this.props;
const { ordering, tagFilters, sortMenuAnchorElement } = this.state;
const {
ordering,
searchQuery,
sortMenuAnchorElement,
tagFilters,
} = this.state;

const searchPlaceholder = intl.formatMessage({
id: 'app.program_collection.search',
Expand Down Expand Up @@ -289,7 +296,35 @@ class ProgramCollection extends Component {
</Grid>
<Grid container spacing={3}>
{
programs.results.map((program) => (
programs.count === 0 && !searchQuery && tagFilters.length === 0 ? (
<Grid item container direction="column" alignItems="center" justify="center">
<Grid item>
<img alt="Kids" width="300px" src={flavourImage} />
</Grid>
<Grid item>
<Typography variant="h4">
<FormattedMessage
id="app.program_collection.no_programs"
description="Notifies new users he or she has no programs"
defaultMessage="You don't have any programs yet!"
/>
</Typography>
</Grid>
</Grid>
) : (null)
}
{
programs.count === 0 && (searchQuery || tagFilters.length !== 0) ? (
<Grid item container direction="row" alignItems="center" justify="center">
<Typography variant="h4">
<FormattedMessage
id="app.program_collection.nothing"
description="Informs the user that no programs match the filters"
defaultMessage="Sorry, no programs match your filters."
/>
</Typography>
</Grid>
) : programs.results.map((program) => (
<Grid item xs={12} md={6} lg={3} key={program.id}>
<Card key={program.id}>
<CardActionArea
Expand Down Expand Up @@ -370,6 +405,7 @@ ProgramCollection.propTypes = {
username: PropTypes.string.isRequired,
}).isRequired,
programs: PropTypes.shape({
count: PropTypes.number,
next: PropTypes.string,
previous: PropTypes.string,
total_pages: PropTypes.number,
Expand Down
24 changes: 23 additions & 1 deletion src/components/__tests__/CourseList.test.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React from 'react';
import { MemoryRouter } from 'react-router';
import { CircularProgress } from '@material-ui/core';
import { Card, CircularProgress } from '@material-ui/core';
import { Redirect } from 'react-router-dom';
import Course from '../Course';
import CourseList from '../CourseList';
Expand All @@ -11,6 +11,7 @@ describe('The CourseList component', () => {
const fetchProgram = jest.fn().mockResolvedValue();
const changeReadOnly = jest.fn();
const courses = {
count: 2,
next: null,
previous: null,
total_pages: 2,
Expand Down Expand Up @@ -100,6 +101,27 @@ describe('The CourseList component', () => {
expect(wrapper.find(CircularProgress).length).toBe(1);
});

test('shows message when no results', () => {
const empty = {
count: 0,
next: null,
previous: null,
total_pages: 1,
results: [],
};
const wrapper = shallowWithIntl(
<CourseList
fetchCourses={fetchCourses}
fetchProgram={fetchProgram}
changeReadOnly={changeReadOnly}
courses={empty}
/>,
).dive().dive().dive();

expect(wrapper.find(Card).exists()).toBe(false);
expect(wrapper.find('WithStyles(ForwardRef(Typography))').children().prop('defaultMessage')).toBe('Sorry, no courses match your filters.');
});

test('fetches courses after page change', () => {
const wrapper = shallowWithIntl(
<CourseList
Expand Down
63 changes: 63 additions & 0 deletions src/components/__tests__/ProgramCollection.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import React from 'react';
import { BrowserRouter as Router } from 'react-router-dom';
import { Card } from '@material-ui/core';
import { Pagination } from '@material-ui/lab';
import { FormattedMessage } from 'react-intl';
import ProgramCollection from '../ProgramCollection';
Expand All @@ -21,6 +22,7 @@ describe('The ProgramCollection component', () => {

test('renders on the page with no errors', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 2,
Expand Down Expand Up @@ -59,6 +61,7 @@ describe('The ProgramCollection component', () => {

test('should set and clear sort menu anchor element when menu is opening and closing', () => {
const programs = {
count: 0,
next: null,
previous: null,
total_pages: 1,
Expand All @@ -82,8 +85,61 @@ describe('The ProgramCollection component', () => {
expect(wrapper.instance().state.sortMenuAnchorElement).toBe(null);
});

test('shows message when no results', () => {
const programs = {
count: 0,
next: null,
previous: null,
total_pages: 1,
results: [],
};
const wrapper = shallowWithIntl(
<ProgramCollection
programs={programs}
label="My Programs"
user={testUser}
onProgramClick={onProgramClick}
onRemoveClick={onRemoveClick}
onUpdate={onUpdate}
/>,
).dive().dive().dive();

wrapper.setState({
searchQuery: 'test',
});

expect(wrapper.find(Card).exists()).toBe(false);
expect(wrapper.find('img').exists()).toBe(false);
expect(wrapper.find('WithStyles(ForwardRef(Typography))').children().prop('defaultMessage')).toBe('Sorry, no programs match your filters.');
});

test('shows message when no programs', () => {
const programs = {
count: 0,
next: null,
previous: null,
total_pages: 1,
results: [],
};
const wrapper = shallowWithIntl(
<ProgramCollection
programs={programs}
label="My Programs"
user={testUser}
onProgramClick={onProgramClick}
onRemoveClick={onRemoveClick}
onUpdate={onUpdate}
/>,
).dive().dive().dive();

expect(wrapper.find(Card).exists()).toBe(false);
expect(wrapper.find('img').exists()).toBe(true);
expect(wrapper.find('WithStyles(ForwardRef(Typography))').children().prop('defaultMessage')).toBe('You don\'t have any programs yet!');
});

test('shows the correct number of programs for the user', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 1,
Expand Down Expand Up @@ -122,6 +178,7 @@ describe('The ProgramCollection component', () => {

test('shows the correct number of programs for other users', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 1,
Expand Down Expand Up @@ -160,6 +217,7 @@ describe('The ProgramCollection component', () => {

test('callback when program click', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 1,
Expand Down Expand Up @@ -198,6 +256,7 @@ describe('The ProgramCollection component', () => {

test('callback when remove click', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 1,
Expand Down Expand Up @@ -235,6 +294,7 @@ describe('The ProgramCollection component', () => {

test('callback when page changes', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 2,
Expand Down Expand Up @@ -276,6 +336,7 @@ describe('The ProgramCollection component', () => {

test('callback when search changes', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 2,
Expand Down Expand Up @@ -322,6 +383,7 @@ describe('The ProgramCollection component', () => {

test('callback when order changes', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 2,
Expand Down Expand Up @@ -379,6 +441,7 @@ describe('The ProgramCollection component', () => {

test('callback when tag changes', () => {
const programs = {
count: 2,
next: null,
previous: null,
total_pages: 2,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ exports[`The ProgramCollection component renders on the page with no errors 1`]
onUpdate={[MockFunction]}
programs={
Object {
"count": 2,
"next": null,
"previous": null,
"results": Array [
Expand Down Expand Up @@ -100,6 +101,7 @@ exports[`The ProgramCollection component renders on the page with no errors 1`]
onUpdate={[MockFunction]}
programs={
Object {
"count": 2,
"next": null,
"previous": null,
"results": Array [
Expand Down Expand Up @@ -175,6 +177,7 @@ exports[`The ProgramCollection component renders on the page with no errors 1`]
onUpdate={[MockFunction]}
programs={
Object {
"count": 2,
"next": null,
"previous": null,
"results": Array [
Expand Down
3 changes: 3 additions & 0 deletions src/translations/locales/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"app.control.run": "Run",
"app.control.step": "Step",
"app.control.stop": "Stop",
"app.course_list.nothing": "Sorry, no courses match your filters.",
"app.course_list.search": "Search courses",
"app.course_list.title": "Courses",
"app.global.not_exist": "Sorry, the page you're looking for doesn't exist.",
Expand All @@ -47,6 +48,7 @@
"app.mission_control.console": "Debug Console",
"app.mission_control.details": "Project Details",
"app.mission_control.edit_details": "Edit Project Details",
"app.mission_control.goal_label": "Goal",
"app.mission_control.left": "Left",
"app.mission_control.light_sensors": "Light Sensors",
"app.mission_control.milliVolts": "milliVolts",
Expand All @@ -71,6 +73,7 @@
"app.program_collection.filter": "Filter by tag",
"app.program_collection.name": "Name",
"app.program_collection.new": "New Program",
"app.program_collection.nothing": "Sorry, no programs match your filters.",
"app.program_collection.remove": "Delete",
"app.program_collection.search": "Search programs",
"app.program_collection.sort": "Sort",
Expand Down
3 changes: 3 additions & 0 deletions src/translations/locales/es.json
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
"app.control.run": "Ejecutar",
"app.control.step": "Avanzar",
"app.control.stop": "Parar",
"app.course_list.nothing": "Sorry, no courses match your filters.",
"app.course_list.search": "Search courses",
"app.course_list.title": "Courses",
"app.global.not_exist": "Perdón, la página que estás buscando no existe..",
Expand All @@ -47,6 +48,7 @@
"app.mission_control.console": "Depurar Consola",
"app.mission_control.details": "Project Details",
"app.mission_control.edit_details": "Edit Project Details",
"app.mission_control.goal_label": "Goal",
"app.mission_control.left": "Left",
"app.mission_control.light_sensors": "Light Sensors",
"app.mission_control.milliVolts": "milliVolts",
Expand All @@ -71,6 +73,7 @@
"app.program_collection.filter": "Filter by tag",
"app.program_collection.name": "Nombre",
"app.program_collection.new": "New Program",
"app.program_collection.nothing": "Sorry, no programs match your filters.",
"app.program_collection.remove": "Quitar",
"app.program_collection.search": "Buscar",
"app.program_collection.sort": "Ordenar",
Expand Down