Fix some aria warnings and use immutable everywhere

This commit is contained in:
Lucas Verney 2016-08-06 15:30:03 +02:00
parent 34713cdcde
commit 9d1ef1b0bf
16 changed files with 101 additions and 71 deletions

View File

@ -2,6 +2,7 @@ import React, { Component, PropTypes } from "react";
import CSSModules from "react-css-modules"; import CSSModules from "react-css-modules";
import { defineMessages, FormattedMessage } from "react-intl"; import { defineMessages, FormattedMessage } from "react-intl";
import FontAwesome from "react-fontawesome"; import FontAwesome from "react-fontawesome";
import Immutable from "immutable";
import { formatLength, messagesMap } from "../utils"; import { formatLength, messagesMap } from "../utils";
@ -32,9 +33,8 @@ class AlbumTrackRowCSS extends Component {
} }
} }
// TODO: Not object
AlbumTrackRowCSS.propTypes = { AlbumTrackRowCSS.propTypes = {
track: PropTypes.object.isRequired track: PropTypes.instanceOf(Immutable.Map).isRequired
}; };
export let AlbumTrackRow = CSSModules(AlbumTrackRowCSS, css); export let AlbumTrackRow = CSSModules(AlbumTrackRowCSS, css);
@ -56,9 +56,8 @@ class AlbumTracksTableCSS extends Component {
} }
} }
// TODO: Not object
AlbumTracksTableCSS.propTypes = { AlbumTracksTableCSS.propTypes = {
tracks: PropTypes.object.isRequired tracks: PropTypes.instanceOf(Immutable.List).isRequired
}; };
export let AlbumTracksTable = CSSModules(AlbumTracksTableCSS, css); export let AlbumTracksTable = CSSModules(AlbumTracksTableCSS, css);
@ -85,10 +84,9 @@ class AlbumRowCSS extends Component {
} }
} }
// TODO: Not object
AlbumRowCSS.propTypes = { AlbumRowCSS.propTypes = {
album: PropTypes.object.isRequired, album: PropTypes.instanceOf(Immutable.Map).isRequired,
songs: PropTypes.object.isRequired songs: PropTypes.instanceOf(Immutable.List).isRequired
}; };
export let AlbumRow = CSSModules(AlbumRowCSS, css); export let AlbumRow = CSSModules(AlbumRowCSS, css);
@ -101,8 +99,7 @@ export default class Album extends Component {
} }
} }
// TODO: Not object
Album.propTypes = { Album.propTypes = {
album: PropTypes.object.isRequired, album: PropTypes.instanceOf(Immutable.Map).isRequired,
songs: PropTypes.object.isRequired songs: PropTypes.instanceOf(Immutable.List).isRequired
}; };

View File

@ -1,24 +1,51 @@
import React, { Component, PropTypes } from "react"; import React, { Component, PropTypes } from "react";
import CSSModules from "react-css-modules"; import CSSModules from "react-css-modules";
import { defineMessages, FormattedMessage } from "react-intl";
import FontAwesome from "react-fontawesome";
import Immutable from "immutable";
import { messagesMap } from "../utils/";
import { AlbumRow } from "./Album"; import { AlbumRow } from "./Album";
import commonMessages from "../locales/messagesDescriptors/common";
import css from "../styles/Artist.scss"; import css from "../styles/Artist.scss";
const artistMessages = defineMessages(messagesMap(Array.concat([], commonMessages)));
class ArtistCSS extends Component { class ArtistCSS extends Component {
render () { render () {
const loading = (
<div className="row text-center">
<p>
<FontAwesome name="spinner" className="fa-pulse fa-3x fa-fw" aria-hidden="true" />
<span className="sr-only"><FormattedMessage {...artistMessages["app.common.loading"]} /></span>
</p>
</div>
);
if (!this.props.artist) {
// Loading
return loading;
}
let albumsRows = []; let albumsRows = [];
if (this.props.artist.get("albums").size > 0) { const { albums, songs } = this.props;
const artistAlbums = this.props.albums; const artistAlbums = this.props.artist.get("albums");
const artistSongs = this.props.songs; if (albums && songs && artistAlbums && artistAlbums.size > 0) {
this.props.artist.get("albums").forEach(function (album) { this.props.artist.get("albums").forEach(function (album) {
album = artistAlbums.get(album); album = albums.get(album);
const songs = album.get("tracks").map( const albumSongs = album.get("tracks").map(
id => artistSongs.get(id) id => songs.get(id)
); );
albumsRows.push(<AlbumRow album={album} songs={songs} key={album.get("id")} />); albumsRows.push(<AlbumRow album={album} songs={albumSongs} key={album.get("id")} />);
}); });
} }
else {
// Loading
albumsRows = loading;
}
return ( return (
<div> <div>
<div className="row" styleName="name"> <div className="row" styleName="name">
@ -41,11 +68,11 @@ class ArtistCSS extends Component {
} }
} }
// TODO: Not object
ArtistCSS.propTypes = { ArtistCSS.propTypes = {
artist: PropTypes.object.isRequired, isFetching: PropTypes.bool.isRequired,
albums: PropTypes.object.isRequired, artist: PropTypes.instanceOf(Immutable.Map),
songs: PropTypes.object.isRequired albums: PropTypes.instanceOf(Immutable.Map),
songs: PropTypes.instanceOf(Immutable.Map)
}; };
export default CSSModules(ArtistCSS, css); export default CSSModules(ArtistCSS, css);

View File

@ -43,7 +43,7 @@ class SongsTableRowCSS extends Component {
} }
SongsTableRowCSS.propTypes = { SongsTableRowCSS.propTypes = {
song: PropTypes.object.isRequired song: PropTypes.instanceOf(Immutable.Map).isRequired
}; };
export let SongsTableRow = CSSModules(SongsTableRowCSS, css); export let SongsTableRow = CSSModules(SongsTableRowCSS, css);

View File

@ -25,8 +25,8 @@ class GridItemCSSIntl extends Component {
const {formatMessage} = this.props.intl; const {formatMessage} = this.props.intl;
let nSubItems = this.props.item.get(this.props.subItemsType); let nSubItems = this.props.item.get(this.props.subItemsType);
if (Array.isArray(nSubItems)) { if (Immutable.List.isList(nSubItems)) {
nSubItems = nSubItems.length; nSubItems = nSubItems.size;
} }
let subItemsLabel = formatMessage(gridMessages[this.props.subItemsLabel], { itemCount: nSubItems }); let subItemsLabel = formatMessage(gridMessages[this.props.subItemsLabel], { itemCount: nSubItems });
@ -48,7 +48,7 @@ class GridItemCSSIntl extends Component {
} }
GridItemCSSIntl.propTypes = { GridItemCSSIntl.propTypes = {
item: PropTypes.object.isRequired, item: PropTypes.instanceOf(Immutable.Map).isRequired,
itemsType: PropTypes.string.isRequired, itemsType: PropTypes.string.isRequired,
itemsLabel: PropTypes.string.isRequired, itemsLabel: PropTypes.string.isRequired,
subItemsType: PropTypes.string.isRequired, subItemsType: PropTypes.string.isRequired,

View File

@ -2,6 +2,7 @@ import React, { Component, PropTypes } from "react";
import CSSModules from "react-css-modules"; import CSSModules from "react-css-modules";
import { defineMessages, injectIntl, intlShape, FormattedMessage } from "react-intl"; import { defineMessages, injectIntl, intlShape, FormattedMessage } from "react-intl";
import FontAwesome from "react-fontawesome"; import FontAwesome from "react-fontawesome";
import Immutable from "immutable";
import { messagesMap } from "../../utils"; import { messagesMap } from "../../utils";
@ -45,12 +46,12 @@ class WebPlayerCSSIntl extends Component {
<div className="col-xs-12"> <div className="col-xs-12">
<div className="row" styleName="artRow" onMouseOver={this.artOpacityHandler} onMouseOut={this.artOpacityHandler}> <div className="row" styleName="artRow" onMouseOver={this.artOpacityHandler} onMouseOut={this.artOpacityHandler}>
<div className="col-xs-12"> <div className="col-xs-12">
<img src={this.props.song.art} width="200" height="200" ref="art" styleName="art" /> <img src={this.props.song.get("art")} width="200" height="200" alt={formatMessage(webplayerMessages["app.common.art"])} ref="art" styleName="art" />
<h2>{this.props.song.title}</h2> <h2>{this.props.song.get("title")}</h2>
<h3> <h3>
<span className="text-capitalize"> <span className="text-capitalize">
<FormattedMessage {...webplayerMessages["app.webplayer.by"]} /> <FormattedMessage {...webplayerMessages["app.webplayer.by"]} />
</span> {this.props.song.artist} </span> {this.props.song.get("artist")}
</h3> </h3>
</div> </div>
</div> </div>
@ -89,7 +90,7 @@ class WebPlayerCSSIntl extends Component {
} }
WebPlayerCSSIntl.propTypes = { WebPlayerCSSIntl.propTypes = {
song: PropTypes.object.isRequired, song: PropTypes.instanceOf(Immutable.Map).isRequired,
isPlaying: PropTypes.bool.isRequired, isPlaying: PropTypes.bool.isRequired,
isRandom: PropTypes.bool.isRequired, isRandom: PropTypes.bool.isRequired,
isRepeat: PropTypes.bool.isRequired, isRepeat: PropTypes.bool.isRequired,

View File

@ -7,7 +7,7 @@ import { messagesMap } from "../../utils";
import commonMessages from "../../locales/messagesDescriptors/common"; import commonMessages from "../../locales/messagesDescriptors/common";
import messages from "../../locales/messagesDescriptors/layouts/Sidebar"; import messages from "../../locales/messagesDescriptors/layouts/Sidebar";
import WebPlayer from "../../containers/WebPlayer"; import WebPlayer from "../../views/WebPlayer";
import css from "../../styles/layouts/Sidebar.scss"; import css from "../../styles/layouts/Sidebar.scss";

View File

@ -3,6 +3,7 @@ module.exports = {
"app.api.emptyResponse": "Empty response text.", // Empty response from the API "app.api.emptyResponse": "Empty response text.", // Empty response from the API
"app.api.error": "Unknown API error.", // An unknown error occurred from the API "app.api.error": "Unknown API error.", // An unknown error occurred from the API
"app.common.album": "{itemCount, plural, one {album} other {albums}}", // Album "app.common.album": "{itemCount, plural, one {album} other {albums}}", // Album
"app.common.art": "Art", // Art
"app.common.artist": "{itemCount, plural, one {artist} other {artists}}", // Artist "app.common.artist": "{itemCount, plural, one {artist} other {artists}}", // Artist
"app.common.cancel": "Cancel", // Cancel "app.common.cancel": "Cancel", // Cancel
"app.common.close": "Close", // Close "app.common.close": "Close", // Close

View File

@ -3,6 +3,7 @@ module.exports = {
"app.api.emptyResponse": "Réponse vide reçue.", // Empty response from the API "app.api.emptyResponse": "Réponse vide reçue.", // Empty response from the API
"app.api.error": "Erreur inconnue.", // An unknown error occurred from the API "app.api.error": "Erreur inconnue.", // An unknown error occurred from the API
"app.common.album": "{itemCount, plural, one {album} other {albums}}", // Albums "app.common.album": "{itemCount, plural, one {album} other {albums}}", // Albums
"app.common.art": "Pochette", // Art
"app.common.artist": "{itemCount, plural, one {artiste} other {artistes}}", // Artists "app.common.artist": "{itemCount, plural, one {artiste} other {artistes}}", // Artists
"app.common.cancel": "Annuler", // Cancel "app.common.cancel": "Annuler", // Cancel
"app.common.close": "Fermer", // Close "app.common.close": "Fermer", // Close

View File

@ -14,6 +14,11 @@ const messages = [
description: "Go", description: "Go",
defaultMessage: "Go" defaultMessage: "Go"
}, },
{
id: "app.common.art",
description: "Art",
defaultMessage: "Art"
},
{ {
id: "app.common.artist", id: "app.common.artist",
description: "Artist", description: "Artist",

View File

@ -99,7 +99,7 @@ button.toggle {
*/ */
.main-panel { .main-panel {
padding: $mainPadding; padding: $mainPadding;
z-index: -10; /** TODO: z-index issue */ z-index: -10;
} }
/* /*

View File

@ -43,9 +43,9 @@ const mapStateToProps = (state, ownProps) => {
// Get songs // Get songs
const tracks = album.get("tracks"); const tracks = album.get("tracks");
if (Immutable.List.isList(tracks)) { if (Immutable.List.isList(tracks)) {
songs = new Immutable.Map( songs = new Immutable.List(
tracks.map( tracks.map(
id => [id, state.api.entities.getIn(["track", id])] id => state.api.entities.getIn(["track", id])
) )
); );
} }

View File

@ -18,22 +18,17 @@ export class ArtistPage extends Component {
} }
render () { render () {
if (this.props.artist) {
return (
<Artist artist={this.props.artist} albums={this.props.albums} songs={this.props.songs} />
);
}
return ( return (
<div></div> <Artist isFetching={this.props.isFetching} artist={this.props.artist} albums={this.props.albums} songs={this.props.songs} />
); // TODO: Loading );
} }
} }
const mapStateToProps = (state, ownProps) => { const mapStateToProps = (state, ownProps) => {
const artists = state.api.entities.get("artist"); const artists = state.api.entities.get("artist");
let artist = undefined; let artist = undefined;
let albums = new Immutable.List(); let albums = new Immutable.Map();
let songs = new Immutable.List(); let songs = new Immutable.Map();
if (artists) { if (artists) {
// Get artist // Get artist
artist = artists.find( artist = artists.find(
@ -59,6 +54,7 @@ const mapStateToProps = (state, ownProps) => {
} }
} }
return { return {
isFetching: state.api.isFetching,
artist: artist, artist: artist,
albums: albums, albums: albums,
songs: songs songs: songs

View File

@ -1,15 +1,17 @@
import React, { Component } from "react"; import React, { Component } from "react";
import Immutable from "immutable";
import WebPlayerComponent from "../components/elements/WebPlayer"; import WebPlayerComponent from "../components/elements/WebPlayer";
export default class WebPlayer extends Component { export default class WebPlayer extends Component {
render () { render () {
const webplayerProps = { const webplayerProps = {
song: { song: new Immutable.Map({
art: "http://albumartcollection.com/wp-content/uploads/2011/07/summer-album-art.jpg", art: "http://albumartcollection.com/wp-content/uploads/2011/07/summer-album-art.jpg",
title: "Tel-ho", title: "Tel-ho",
artist: "Lapso Laps", artist: "Lapso Laps",
}, }),
isPlaying: false, isPlaying: false,
isRandom: false, isRandom: false,
isRepeat: true isRepeat: true

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long