diff --git a/src/components/Audioplayer/RepeatDropdown/index.js b/src/components/Audioplayer/RepeatDropdown/index.js index e3e2f5227..6b58449c1 100644 --- a/src/components/Audioplayer/RepeatDropdown/index.js +++ b/src/components/Audioplayer/RepeatDropdown/index.js @@ -1,30 +1,17 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import OverlayTrigger from 'react-bootstrap/lib/OverlayTrigger'; import Popover from 'react-bootstrap/lib/Popover'; import Nav from 'react-bootstrap/lib/Nav'; import NavItem from 'react-bootstrap/lib/NavItem'; import FormControl from 'react-bootstrap/lib/FormControl'; import { intlShape, injectIntl } from 'react-intl'; - import SwitchToggle from 'components/SwitchToggle'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import surahType from 'types/surahType'; - const style = require('../style.scss'); class RepeatButton extends Component { - static propTypes = { - chapter: surahType, - repeat: PropTypes.shape({ - from: PropTypes.number, - to: PropTypes.number, - times: PropTypes.number - }).isRequired, - setRepeat: PropTypes.func.isRequired, - current: PropTypes.number.isRequired, - intl: intlShape.isRequired - }; handleToggle = () => { const { repeat, setRepeat, current } = this.props; @@ -37,7 +24,7 @@ class RepeatButton extends Component { from: current, to: current }); - } + }; handleNavChange = (nav) => { const { setRepeat, current } = this.props; @@ -281,4 +268,12 @@ class RepeatButton extends Component { } } +RepeatButton.propTypes = { + chapter: customPropTypes.surahType, + repeat: customPropTypes.timeInterval, + setRepeat: PropTypes.func.isRequired, + current: PropTypes.number.isRequired, + intl: intlShape.isRequired +}; + export default injectIntl(RepeatButton); diff --git a/src/components/Audioplayer/Segments/index.js b/src/components/Audioplayer/Segments/index.js index 91ae279db..90b210a48 100644 --- a/src/components/Audioplayer/Segments/index.js +++ b/src/components/Audioplayer/Segments/index.js @@ -1,15 +1,9 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import Helmet from 'react-helmet'; -import { segmentType } from 'types'; - import debug from 'helpers/debug'; -export default class Segments extends Component { - static propTypes = { - segments: PropTypes.objectOf(segmentType).isRequired, - currentVerse: PropTypes.string, - currentTime: PropTypes.number - }; +class Segments extends Component { shouldComponentUpdate(nextProps) { return [ @@ -53,3 +47,11 @@ export default class Segments extends Component { ); } } + +Segments.propTypes = { + segments: customPropTypes.segments.isRequired, + currentVerse: PropTypes.string, + currentTime: PropTypes.number +}; + +export default Segments; diff --git a/src/components/Audioplayer/Track/index.js b/src/components/Audioplayer/Track/index.js index 619403bdd..74c0c92b7 100644 --- a/src/components/Audioplayer/Track/index.js +++ b/src/components/Audioplayer/Track/index.js @@ -18,7 +18,7 @@ export default class Track extends Component { ); return onTrackChange(fraction); - } + }; render() { const { progress } = this.props; diff --git a/src/components/Audioplayer/index.js b/src/components/Audioplayer/index.js index 2d3aa554c..a12dccf51 100644 --- a/src/components/Audioplayer/index.js +++ b/src/components/Audioplayer/index.js @@ -1,18 +1,16 @@ /* global document */ // TODO: This file is too too large. import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; import { camelize } from 'humps'; import Loadable from 'react-loadable'; - import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; // Helpers import debug from 'helpers/debug'; import scroller from 'utils/scroller'; -import { surahType, segmentType, verseType } from 'types'; - // Redux import * as AudioActions from 'redux/actions/audioplayer'; @@ -29,38 +27,6 @@ const RepeatDropdown = Loadable({ }); export class Audioplayer extends Component { - static propTypes = { - className: PropTypes.string, - chapter: surahType, - onLoadAyahs: PropTypes.func.isRequired, - segments: PropTypes.objectOf(segmentType), - // NOTE: should be PropTypes.instanceOf(Audio) but not on server. - files: PropTypes.object, // eslint-disable-line - currentVerse: PropTypes.string, - buildOnClient: PropTypes.func.isRequired, - isLoadedOnClient: PropTypes.bool.isRequired, - isLoading: PropTypes.bool.isRequired, - play: PropTypes.func.isRequired, - pause: PropTypes.func.isRequired, - next: PropTypes.func.isRequired, // eslint-disable-line - previous: PropTypes.func.isRequired, // eslint-disable-line - update: PropTypes.func.isRequired, - repeat: PropTypes.shape({ - from: PropTypes.number, - to: PropTypes.number, - time: PropTypes.number, - }).isRequired, - shouldScroll: PropTypes.bool.isRequired, - setRepeat: PropTypes.func.isRequired, - setAyah: PropTypes.func.isRequired, - toggleScroll: PropTypes.func.isRequired, - isPlaying: PropTypes.bool, - currentTime: PropTypes.number, - duration: PropTypes.number, - // NOTE: should be PropTypes.instanceOf(Audio) but not on server. - currentFile: PropTypes.any, // eslint-disable-line - startVerse: verseType // eslint-disable-line - }; componentDidMount() { const { isLoadedOnClient, buildOnClient, chapter, currentFile } = this.props; // eslint-disable-line no-shadow, max-len @@ -510,4 +476,33 @@ const mapStateToProps = (state, ownProps) => { }; }; +Audioplayer.propTypes = { + className: PropTypes.string, + chapter: customPropTypes.surahType, + onLoadAyahs: PropTypes.func.isRequired, + segments: customPropTypes.segments, + // NOTE: should be PropTypes.instanceOf(Audio) but not on server. + files: PropTypes.object, // eslint-disable-line + currentVerse: PropTypes.string, + buildOnClient: PropTypes.func.isRequired, + isLoadedOnClient: PropTypes.bool.isRequired, + isLoading: PropTypes.bool.isRequired, + play: PropTypes.func.isRequired, + pause: PropTypes.func.isRequired, + next: PropTypes.func.isRequired, // eslint-disable-line + previous: PropTypes.func.isRequired, // eslint-disable-line + update: PropTypes.func.isRequired, + repeat: customPropTypes.timeInterval.isRequired, + shouldScroll: PropTypes.bool.isRequired, + setRepeat: PropTypes.func.isRequired, + setAyah: PropTypes.func.isRequired, + toggleScroll: PropTypes.func.isRequired, + isPlaying: PropTypes.bool, + currentTime: PropTypes.number, + duration: PropTypes.number, + // NOTE: should be PropTypes.instanceOf(Audio) but not on server. + currentFile: PropTypes.any, // eslint-disable-line + startVerse: customPropTypes.verseType // eslint-disable-line +}; + export default connect(mapStateToProps, AudioActions)(Audioplayer); diff --git a/src/components/Bismillah/index.js b/src/components/Bismillah/index.js index 2b8a40036..235a2d2fb 100644 --- a/src/components/Bismillah/index.js +++ b/src/components/Bismillah/index.js @@ -1,5 +1,5 @@ import React from 'react'; -import { surahType } from 'types'; +import * as customPropTypes from 'customPropTypes'; const Bismillah = ({ chapter }) => { if (chapter && chapter.bismillahPre) { @@ -19,7 +19,7 @@ const Bismillah = ({ chapter }) => { }; Bismillah.propTypes = { - chapter: surahType.isRequired + chapter: customPropTypes.surahType.isRequired }; export default Bismillah; diff --git a/src/components/ContentDropdown/index.js b/src/components/ContentDropdown/index.js index 648e227eb..a90d8ab63 100644 --- a/src/components/ContentDropdown/index.js +++ b/src/components/ContentDropdown/index.js @@ -1,8 +1,8 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; import { loadTranslations } from 'redux/actions/options'; -import { contentType } from 'types'; import Menu, { MenuItem } from 'quran-components/lib/Menu'; import Checkbox from 'quran-components/lib/Checkbox'; import Loader from 'quran-components/lib/Loader'; @@ -28,12 +28,6 @@ const compareAlphabetically = property => class ContentDropdown extends Component { - static propTypes = { - onOptionChange: PropTypes.func.isRequired, - translations: PropTypes.arrayOf(PropTypes.number).isRequired, - translationOptions: PropTypes.arrayOf(contentType), - loadTranslations: PropTypes.func.isRequired - }; componentDidMount() { if (!this.props.translationOptions.length) { @@ -129,6 +123,13 @@ class ContentDropdown extends Component { } } +ContentDropdown.propTypes = { + onOptionChange: PropTypes.func.isRequired, + translations: PropTypes.arrayOf(PropTypes.number).isRequired, + translationOptions: customPropTypes.translationOptions, + loadTranslations: PropTypes.func.isRequired +}; + export default connect(state => ({ translationOptions: state.options.options.translations, loadingTranslations: state.options.loadingTranslations, diff --git a/src/components/Copy/index.js b/src/components/Copy/index.js index 92491f95b..6f8882917 100644 --- a/src/components/Copy/index.js +++ b/src/components/Copy/index.js @@ -2,11 +2,7 @@ import React, { Component, PropTypes } from 'react'; import copyToClipboard from 'copy-to-clipboard'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -export default class Copy extends Component { - static propTypes = { - text: PropTypes.string.isRequired, - verseKey: PropTypes.string.isRequired, - } +class Copy extends Component { state = { isCopied: false @@ -17,7 +13,7 @@ export default class Copy extends Component { this.setState({ isCopied: true }); setTimeout(() => this.setState({ isCopied: false }), 1000); - } + }; render() { const { isCopied } = this.state; @@ -37,5 +33,11 @@ export default class Copy extends Component { ); } - } + +Copy.propTypes = { + text: PropTypes.string.isRequired, + verseKey: PropTypes.string.isRequired, +}; + +export default Copy; diff --git a/src/components/FontSizeDropdown/index.js b/src/components/FontSizeDropdown/index.js index 6435c63ee..9129ba028 100644 --- a/src/components/FontSizeDropdown/index.js +++ b/src/components/FontSizeDropdown/index.js @@ -1,17 +1,10 @@ import React, { Component, PropTypes } from 'react'; - +import * as customPropTypes from 'customPropTypes'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; const style = require('./style.scss'); -export default class FontSizeDropdown extends Component { - static propTypes = { - onOptionChange: PropTypes.func, - fontSize: PropTypes.shape({ - arabic: PropTypes.number, - translation: PropTypes.number - }).isRequired - } +class FontSizeDropdown extends Component { handleOptionSelected = (type, direction) => { const { onOptionChange, fontSize } = this.props; @@ -90,3 +83,10 @@ export default class FontSizeDropdown extends Component { ); } } + +FontSizeDropdown.propTypes = { + onOptionChange: PropTypes.func, + fontSize: customPropTypes.fontSize.isRequired +}; + +export default FontSizeDropdown; diff --git a/src/components/FontStyles/index.js b/src/components/FontStyles/index.js index c19539c46..800566818 100644 --- a/src/components/FontStyles/index.js +++ b/src/components/FontStyles/index.js @@ -12,11 +12,8 @@ import selector from './selector'; }), { load } ) -export default class FontStyles extends Component { - static propTypes = { - fontFaces: PropTypes.objectOf(PropTypes.bool).isRequired, - load: PropTypes.func.isRequired - }; + +class FontStyles extends Component { shouldComponentUpdate(nextProps) { return JSON.stringify(this.props.fontFaces) !== JSON.stringify(nextProps.fontFaces); @@ -54,3 +51,10 @@ export default class FontStyles extends Component { ); } } + +FontStyles.propTypes = { + fontFaces: PropTypes.objectOf(PropTypes.bool).isRequired, + load: PropTypes.func.isRequired +}; + +export default FontStyles; diff --git a/src/components/GlobalNav/Surah/index.js b/src/components/GlobalNav/Surah/index.js index 746e47d24..5c5957a6b 100644 --- a/src/components/GlobalNav/Surah/index.js +++ b/src/components/GlobalNav/Surah/index.js @@ -1,12 +1,10 @@ import React, { PropTypes, Component } from 'react'; +import * as customPropTypes from 'customPropTypes'; +import * as OptionsActions from 'redux/actions/options.js'; import { connect } from 'react-redux'; import Link from 'react-router/lib/Link'; import Drawer from 'quran-components/lib/Drawer'; import Menu from 'quran-components/lib/Menu'; - -import { surahType, optionsType } from 'types'; -import * as OptionsActions from 'redux/actions/options.js'; - import SearchInput from 'components/SearchInput'; import SurahsDropdown from 'components/SurahsDropdown'; import ReadingModeToggle from 'components/ReadingModeToggle'; @@ -26,14 +24,6 @@ import GlobalNav from '../index'; const styles = require('../style.scss'); class GlobalNavSurah extends Component { - static propTypes = { - chapter: surahType.isRequired, - chapters: PropTypes.objectOf(surahType).isRequired, - options: optionsType.isRequired, - setOption: PropTypes.func.isRequired, - versesIds: PropTypes.instanceOf(Set), - load: PropTypes.func.isRequired - }; state = { drawerOpen: false @@ -156,4 +146,13 @@ function mapStateToProps(state, ownProps) { }; } +GlobalNavSurah.propTypes = { + chapter: customPropTypes.surahType.isRequired, + chapters: customPropTypes.chapters.isRequired, + options: customPropTypes.optionsType.isRequired, + setOption: PropTypes.func.isRequired, + versesIds: PropTypes.instanceOf(Set), + load: PropTypes.func.isRequired +}; + export default connect(mapStateToProps, { ...OptionsActions, load })(GlobalNavSurah); diff --git a/src/components/GlobalNav/index.js b/src/components/GlobalNav/index.js index 5723d105c..7a016927a 100644 --- a/src/components/GlobalNav/index.js +++ b/src/components/GlobalNav/index.js @@ -1,5 +1,6 @@ /* global window */ import React, { PropTypes, Component } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; import Link from 'react-router/lib/Link'; import Navbar from 'react-bootstrap/lib/Navbar'; @@ -8,30 +9,10 @@ import Nav from 'react-bootstrap/lib/Nav'; import LocaleSwitcher from 'components/LocaleSwitcher'; import debug from 'helpers/debug'; -import { userType } from 'types'; const styles = require('./style.scss'); class GlobalNav extends Component { - static propTypes = { - // handleToggleSidebar: PropTypes.func.isRequired, - leftControls: PropTypes.arrayOf(PropTypes.element), - rightControls: PropTypes.arrayOf(PropTypes.element), - handleSidebarToggle: PropTypes.func.isRequired, - isStatic: PropTypes.bool.isRequired, - user: userType, - location: PropTypes.shape({ - action: PropTypes.string, - hash: PropTypes.string, - pathname: PropTypes.string, - search: PropTypes.string, - query: PropTypes.objectOf(PropTypes.string) - }) - }; - - static defaultProps = { - isStatic: false - }; state = { scrolled: false @@ -123,6 +104,20 @@ class GlobalNav extends Component { } } +GlobalNav.propTypes = { + // handleToggleSidebar: PropTypes.func.isRequired, + leftControls: PropTypes.arrayOf(PropTypes.element), + rightControls: PropTypes.arrayOf(PropTypes.element), + handleSidebarToggle: PropTypes.func.isRequired, + isStatic: PropTypes.bool.isRequired, + user: customPropTypes.userType, + location: customPropTypes.location +}; + +GlobalNav.defaultProps = { + isStatic: false +}; + export default connect( state => ({ user: state.auth.user diff --git a/src/components/GlobalSidebar/index.js b/src/components/GlobalSidebar/index.js index ac3cf067d..a1e2d02c9 100644 --- a/src/components/GlobalSidebar/index.js +++ b/src/components/GlobalSidebar/index.js @@ -9,20 +9,10 @@ const styles = require('./style.scss'); const NavbarHeader = Navbar.Header; class GlobalSidebar extends Component { - static propTypes = { - open: PropTypes.bool.isRequired, - handleOpen: PropTypes.func, - settingsModalProps: PropTypes.object, // eslint-disable-line - children: PropTypes.node - }; - - static defaultProps = { - open: false - }; state = { settingsModalOpen: false - } + }; componentDidMount() { document.body.addEventListener('click', this.onBodyClick.bind(this), true); @@ -116,4 +106,15 @@ class GlobalSidebar extends Component { } } +GlobalSidebar.propTypes = { + open: PropTypes.bool.isRequired, + handleOpen: PropTypes.func, + settingsModalProps: PropTypes.object, // eslint-disable-line + children: PropTypes.node +}; + +GlobalSidebar.defaultProps = { + open: false +}; + export default GlobalSidebar; diff --git a/src/components/Home/LastVisit/index.js b/src/components/Home/LastVisit/index.js index d7802ebd6..c1e74dbb0 100644 --- a/src/components/Home/LastVisit/index.js +++ b/src/components/Home/LastVisit/index.js @@ -1,7 +1,7 @@ import React, { PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import debug from 'helpers/debug'; import Link from 'react-router/lib/Link'; -import { surahType } from 'types'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; const styles = require('containers/Home/style.scss'); @@ -25,7 +25,7 @@ const LastVisit = (props) => { }; LastVisit.propTypes = { - chapter: surahType.isRequired, + chapter: customPropTypes.surahType.isRequired, verse: PropTypes.number.isRequired }; diff --git a/src/components/Home/SurahsList/index.js b/src/components/Home/SurahsList/index.js index dc197f794..390e39e63 100644 --- a/src/components/Home/SurahsList/index.js +++ b/src/components/Home/SurahsList/index.js @@ -1,9 +1,8 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import * as customPropTypes from 'customPropTypes'; import debug from 'helpers/debug'; import Link from 'react-router/lib/Link'; -import { surahType } from 'types'; - const styles = require('./style.scss'); const SurahsList = (props) => { @@ -36,7 +35,7 @@ const SurahsList = (props) => { }; SurahsList.propTypes = { - chapters: PropTypes.arrayOf(surahType).isRequired + chapters: customPropTypes.chapters.isRequired }; export default SurahsList; diff --git a/src/components/IndexHeader/index.js b/src/components/IndexHeader/index.js index 2b67fbc7c..90d01ba1b 100644 --- a/src/components/IndexHeader/index.js +++ b/src/components/IndexHeader/index.js @@ -1,6 +1,5 @@ import React, { Component, PropTypes } from 'react'; import Link from 'react-router/lib/Link'; - import SearchInput from 'components/SearchInput'; import debug from 'helpers/debug'; import Jumbotron from 'quran-components/lib/Jumbotron'; @@ -8,10 +7,7 @@ import Jumbotron from 'quran-components/lib/Jumbotron'; const logo = require('../../../static/images/logo-lg-w.png'); const styles = require('./style.scss'); -export default class IndexHeader extends Component { - static propTypes = { - noSearch: PropTypes.bool - }; +class IndexHeader extends Component { renderSearch() { if (this.props.noSearch) { @@ -44,3 +40,9 @@ export default class IndexHeader extends Component { ); } } + +IndexHeader.propTypes = { + noSearch: PropTypes.bool +}; + +export default IndexHeader; diff --git a/src/components/LazyLoad/index.js b/src/components/LazyLoad/index.js index 84f52cb74..028c0d55c 100644 --- a/src/components/LazyLoad/index.js +++ b/src/components/LazyLoad/index.js @@ -4,21 +4,7 @@ import ReactDOM from 'react-dom'; import debug from 'helpers/debug'; -export default class LazyLoad extends Component { - static propTypes = { - isLoading: PropTypes.bool.isRequired, - isEnd: PropTypes.bool.isRequired, - onLazyLoad: PropTypes.func.isRequired, - loadingComponent: PropTypes.element, - endComponent: PropTypes.element, - offset: PropTypes.number - } - - static defaultProps = { - loadingComponent: 'Loading...', - endComponent: 'End.', - offset: 1000 - } +class LazyLoad extends Component { componentDidMount() { if (__CLIENT__) { @@ -57,3 +43,20 @@ export default class LazyLoad extends Component { return loadingComponent; } } + +LazyLoad.propTypes = { + isLoading: PropTypes.bool.isRequired, + isEnd: PropTypes.bool.isRequired, + onLazyLoad: PropTypes.func.isRequired, + loadingComponent: PropTypes.element, + endComponent: PropTypes.element, + offset: PropTypes.number +}; + +LazyLoad.defaultProps = { + loadingComponent: 'Loading...', + endComponent: 'End.', + offset: 1000 +}; + +export default LazyLoad; diff --git a/src/components/Line/index.js b/src/components/Line/index.js index 5cd06dbac..a7a529e77 100644 --- a/src/components/Line/index.js +++ b/src/components/Line/index.js @@ -1,25 +1,11 @@ import React, { PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import debug from 'helpers/debug'; - -import { wordType } from 'types'; import Word from 'components/Word'; const styles = require('../Verse/style.scss'); -export default class Line extends React.Component { - static propTypes = { - line: PropTypes.arrayOf(wordType).isRequired, - tooltip: PropTypes.string, - currentVerse: PropTypes.string.isRequired, - audioActions: PropTypes.shape({ - pause: PropTypes.func.isRequired, - setAyah: PropTypes.func.isRequired, - play: PropTypes.func.isRequired, - setCurrentWord: PropTypes.func.isRequired, - }), - isPlaying: PropTypes.bool, - useTextFont: PropTypes.bool - }; +class Line extends React.Component { // NOTE: this is commented out as it caused problems with 55:31 with missing text. // shouldComponentUpdate(nextProps) { @@ -73,3 +59,14 @@ export default class Line extends React.Component { ); } } + +Line.propTypes = { + line: customPropTypes.line.isRequired, + tooltip: PropTypes.string, + currentVerse: PropTypes.string.isRequired, + audioActions: customPropTypes.audioActions, + isPlaying: PropTypes.bool, + useTextFont: PropTypes.bool +}; + +export default Line; diff --git a/src/components/LocaleSwitcher/index.js b/src/components/LocaleSwitcher/index.js index 4e4c74bbb..863dd4118 100644 --- a/src/components/LocaleSwitcher/index.js +++ b/src/components/LocaleSwitcher/index.js @@ -7,10 +7,7 @@ import config from '../../config'; const { locales, defaultLocale } = config; -export default class LocaleSwitcher extends Component { - static propTypes = { - className: PropTypes.string - }; +class LocaleSwitcher extends Component { state = { currentLocale: defaultLocale, @@ -68,3 +65,9 @@ export default class LocaleSwitcher extends Component { ); } } + +LocaleSwitcher.propTypes = { + className: PropTypes.string +}; + +export default LocaleSwitcher; diff --git a/src/components/NightModeToggle/index.js b/src/components/NightModeToggle/index.js index 46fe461ef..5addc28ef 100644 --- a/src/components/NightModeToggle/index.js +++ b/src/components/NightModeToggle/index.js @@ -4,10 +4,6 @@ import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; import { MenuItem } from 'quran-components/lib/Menu'; class NightModeToggle extends Component { - static propTypes = { - isNightMode: PropTypes.bool.isRequired, - onToggle: PropTypes.func.isRequired - } componentDidMount() { const { isNightMode } = this.props; @@ -41,4 +37,9 @@ class NightModeToggle extends Component { } } +NightModeToggle.propTypes = { + isNightMode: PropTypes.bool.isRequired, + onToggle: PropTypes.func.isRequired +}; + export default NightModeToggle; diff --git a/src/components/PageView/index.js b/src/components/PageView/index.js index 9709cfece..5a6f784c9 100644 --- a/src/components/PageView/index.js +++ b/src/components/PageView/index.js @@ -1,4 +1,5 @@ import React, { PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; import Line from 'components/Line'; @@ -47,7 +48,7 @@ const PageView = ({ lines, keys, currentVerse, options, isPlaying, audioActions, PageView.propTypes = { keys: PropTypes.array, // eslint-disable-line lines: PropTypes.object.isRequired, // eslint-disable-line - audioActions: PropTypes.object.isRequired, // eslint-disable-line + audioActions: customPropTypes.audioActions.isRequired, // eslint-disable-line currentVerse: PropTypes.string, bookmarks: PropTypes.object.isRequired, // eslint-disable-line options: PropTypes.object.isRequired, // eslint-disable-line diff --git a/src/components/ReciterDropdown/index.js b/src/components/ReciterDropdown/index.js index 16d24735a..31cd3163a 100644 --- a/src/components/ReciterDropdown/index.js +++ b/src/components/ReciterDropdown/index.js @@ -1,22 +1,14 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; import Menu, { MenuItem } from 'quran-components/lib/Menu'; import Radio from 'quran-components/lib/Radio'; - import Loader from 'quran-components/lib/Loader'; import Icon from 'quran-components/lib/Icon'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; - import { loadRecitations } from 'redux/actions/options'; -import { recitationType } from 'types'; class ReciterDropdown extends Component { - static propTypes = { - onOptionChange: PropTypes.func, - audio: PropTypes.number, - loadRecitations: PropTypes.func.isRequired, - recitations: PropTypes.arrayOf(recitationType) - }; componentDidMount() { if (!this.props.recitations.length) { @@ -61,6 +53,13 @@ class ReciterDropdown extends Component { } } +ReciterDropdown.propTypes = { + onOptionChange: PropTypes.func, + audio: PropTypes.number, + loadRecitations: PropTypes.func.isRequired, + recitations: customPropTypes.recitations +}; + export default connect(state => ({ recitations: state.options.options.recitations, loadingRecitations: state.options.loadingRecitations, diff --git a/src/components/SearchAutocomplete/index.js b/src/components/SearchAutocomplete/index.js index b7f2ea6f3..742c4e175 100644 --- a/src/components/SearchAutocomplete/index.js +++ b/src/components/SearchAutocomplete/index.js @@ -1,9 +1,8 @@ // TODO: Should be handled by redux and not component states. import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; import { push } from 'react-router-redux'; -import { surahType } from 'types'; - import { suggest } from 'redux/actions/suggest'; const styles = require('./style.scss'); @@ -11,25 +10,6 @@ const styles = require('./style.scss'); const ayahRegex = /^(\d+)(?::(\d+))?$/; class SearchAutocomplete extends Component { - static propTypes = { - chapters: PropTypes.objectOf(surahType).isRequired, - value: PropTypes.string, - // TODO: This should not be doing html stuff. Should use react onKeydown. - input: PropTypes.any, // eslint-disable-line - push: PropTypes.func.isRequired, - suggest: PropTypes.func.isRequired, - suggestions: PropTypes.arrayOf(PropTypes.shape({ - ayah: PropTypes.string, - href: PropTypes.string.isRequired, - text: PropTypes.string.isRequired - })), - lang: PropTypes.string, - delay: PropTypes.number, - }; - - static defaultProps = { - delay: 200 - } componentDidMount() { this.props.input.addEventListener('keydown', this.handleInputKeyDown.bind(this)); @@ -220,4 +200,20 @@ function mapStateToProps(state, ownProps) { }; } +SearchAutocomplete.propTypes = { + chapters: customPropTypes.chapters.isRequired, + value: PropTypes.string, + // TODO: This should not be doing html stuff. Should use react onKeydown. + input: PropTypes.any, // eslint-disable-line + push: PropTypes.func.isRequired, + suggest: PropTypes.func.isRequired, + suggestions: customPropTypes.suggestions, + lang: PropTypes.string, + delay: PropTypes.number, +}; + +SearchAutocomplete.defaultProps = { + delay: 200 +}; + export default connect(mapStateToProps, { push, suggest })(SearchAutocomplete); diff --git a/src/components/SearchInput/index.js b/src/components/SearchInput/index.js index a500c8d60..df9885d4a 100644 --- a/src/components/SearchInput/index.js +++ b/src/components/SearchInput/index.js @@ -9,11 +9,6 @@ import SearchAutocomplete from 'components/SearchAutocomplete'; import debug from 'helpers/debug'; class SearchInput extends Component { - static propTypes = { - push: PropTypes.func.isRequired, - className: PropTypes.string, - intl: intlShape.isRequired - }; static contextTypes = { metrics: MetricsPropTypes.metrics @@ -116,4 +111,10 @@ class SearchInput extends Component { } } +SearchInput.propTypes = { + push: PropTypes.func.isRequired, + className: PropTypes.string, + intl: intlShape.isRequired +}; + export default injectIntl(connect(null, { push })(SearchInput)); diff --git a/src/components/SettingsModal/index.js b/src/components/SettingsModal/index.js index b137cbad3..2b8114410 100644 --- a/src/components/SettingsModal/index.js +++ b/src/components/SettingsModal/index.js @@ -1,15 +1,13 @@ import React, { PropTypes } from 'react'; +import * as customProptypes from 'customPropTypes'; import { connect } from 'react-redux'; import Modal from 'react-bootstrap/lib/Modal'; - import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; import ReciterDropdown from 'components/ReciterDropdown'; import ContentDropdown from 'components/ContentDropdown'; import TooltipDropdown from 'components/TooltipDropdown'; - import { setOption } from 'redux/actions/options.js'; import { load } from 'redux/actions/verses.js'; -import { optionsType, surahType } from 'types'; const ModalHeader = Modal.Header; const ModalTitle = Modal.Title; @@ -73,11 +71,11 @@ const SettingsModal = ({ }; SettingsModal.propTypes = { - chapter: surahType, + chapter: customProptypes.surahType, ayahIds: PropTypes.instanceOf(Set), open: PropTypes.bool, handleHide: PropTypes.func.isRequired, - options: optionsType, + options: customProptypes.optionsType, setOption: PropTypes.func.isRequired, load: PropTypes.func.isRequired, }; diff --git a/src/components/Share/index.js b/src/components/Share/index.js index eadf66bb7..f3b8699ba 100644 --- a/src/components/Share/index.js +++ b/src/components/Share/index.js @@ -1,6 +1,6 @@ import React, { PropTypes } from 'react'; import { ShareButtons, generateShareIcon } from 'react-share'; -import { surahType } from 'types'; +import * as customPropTypes from 'customPropTypes'; const styles = require('./style.scss'); @@ -39,7 +39,7 @@ const Share = ({ chapter, verseKey }) => { Share.propTypes = { verseKey: PropTypes.string, - chapter: surahType.isRequired + chapter: customPropTypes.surahType.isRequired }; export default Share; diff --git a/src/components/SmartBanner/index.js b/src/components/SmartBanner/index.js index 2d0dd362e..3dd954306 100644 --- a/src/components/SmartBanner/index.js +++ b/src/components/SmartBanner/index.js @@ -1,42 +1,10 @@ /* global window */ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import useragent from 'express-useragent'; import cookie from 'react-cookie'; class SmartBanner extends Component { - static propTypes = { - daysHidden: PropTypes.number, - daysReminder: PropTypes.number, - appStoreLanguage: PropTypes.string, - button: PropTypes.string, - storeText: PropTypes.objectOf(PropTypes.string), - price: PropTypes.objectOf(PropTypes.string), - force: PropTypes.string, - title: PropTypes.string, - author: PropTypes.string, - }; - - static defaultProps = { - daysHidden: 15, - daysReminder: 90, - appStoreLanguage: 'us', - button: 'View', - storeText: { - ios: 'On the App Store', - android: 'In Google Play', - windows: 'In Windows Store', - kindle: 'In the Amazon Appstore', - }, - price: { - ios: 'Free', - android: 'Free', - windows: 'Free', - kindle: 'Free', - }, - force: '', - title: '', - author: '', - }; state = { settings: {}, @@ -199,4 +167,38 @@ class SmartBanner extends Component { } } +SmartBanner.propTypes = { + daysHidden: PropTypes.number, + daysReminder: PropTypes.number, + appStoreLanguage: PropTypes.string, + button: PropTypes.string, + storeText: customPropTypes.storeText, + price: customPropTypes.storeText, + force: PropTypes.string, + title: PropTypes.string, + author: PropTypes.string, +}; + +SmartBanner.defaultProps = { + daysHidden: 15, + daysReminder: 90, + appStoreLanguage: 'us', + button: 'View', + storeText: { + ios: 'On the App Store', + android: 'In Google Play', + windows: 'In Windows Store', + kindle: 'In the Amazon Appstore', + }, + price: { + ios: 'Free', + android: 'Free', + windows: 'Free', + kindle: 'Free', + }, + force: '', + title: '', + author: '', +}; + export default SmartBanner; diff --git a/src/components/SurahInfo/index.js b/src/components/SurahInfo/index.js index 6aff87295..16d13b1b4 100644 --- a/src/components/SurahInfo/index.js +++ b/src/components/SurahInfo/index.js @@ -1,6 +1,5 @@ import React, { PropTypes } from 'react'; - -import { surahType, infoType } from 'types'; +import * as customPropTypes from 'customPropTypes'; import Loader from 'quran-components/lib/Loader'; const style = require('./style.scss'); @@ -52,8 +51,8 @@ const SurahInfo = ({ chapter, info, isShowingSurahInfo, onClose }) => { SurahInfo.propTypes = { onClose: PropTypes.func, isShowingSurahInfo: PropTypes.bool, - chapter: surahType, - info: infoType + chapter: customPropTypes.surahType, + info: customPropTypes.infoType }; export default SurahInfo; diff --git a/src/components/SurahsDropdown/index.js b/src/components/SurahsDropdown/index.js index 1a0a4dcab..5cb04bd7d 100644 --- a/src/components/SurahsDropdown/index.js +++ b/src/components/SurahsDropdown/index.js @@ -1,19 +1,13 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import LinkContainer from 'react-router-bootstrap/lib/LinkContainer'; - import NavDropdown from 'react-bootstrap/lib/NavDropdown'; import MenuItem from 'react-bootstrap/lib/MenuItem'; - import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import { surahType } from 'types'; const styles = require('./style.scss'); -export default class SurahsDropdown extends Component { - static propTypes = { - chapters: PropTypes.objectOf(surahType).isRequired, - title: PropTypes.string, - }; +class SurahsDropdown extends Component { shouldComponentUpdate(nextProps) { return this.props.chapters !== nextProps.chapters; @@ -60,3 +54,10 @@ export default class SurahsDropdown extends Component { ); } } + +SurahsDropdown.propTypes = { + chapters: customPropTypes.chapters.isRequired, + title: PropTypes.string, +}; + +export default SurahsDropdown; diff --git a/src/components/TopOptions/index.js b/src/components/TopOptions/index.js index 01a07aa51..afb4ad2ad 100644 --- a/src/components/TopOptions/index.js +++ b/src/components/TopOptions/index.js @@ -1,6 +1,6 @@ import React from 'react'; import Share from 'components/Share'; -import { surahType } from 'types'; +import * as customPropTypes from 'customPropTypes'; const TopOptions = ({ chapter }) => (
@@ -17,7 +17,7 @@ const TopOptions = ({ chapter }) => ( ); TopOptions.propTypes = { - chapter: surahType.isRequired + chapter: customPropTypes.surahType.isRequired }; export default TopOptions; diff --git a/src/components/Translation/index.js b/src/components/Translation/index.js index 5526ec3a8..7d948be3f 100644 --- a/src/components/Translation/index.js +++ b/src/components/Translation/index.js @@ -1,18 +1,12 @@ /* eslint-disable react/prefer-stateless-function */ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { connect } from 'react-redux'; - -import { translationType } from 'types'; import { loadFootNote } from 'redux/actions/footNote'; const styles = require('./style.scss'); class Translation extends Component { - static propTypes = { - translation: translationType.isRequired, - index: PropTypes.number, - loadFootNote: PropTypes.func.isRequired, - }; componentDidMount() { const { index } = this.props; @@ -63,6 +57,12 @@ class Translation extends Component { } } +Translation.propTypes = { + translation: customPropTypes.translationType.isRequired, + index: PropTypes.number, + loadFootNote: PropTypes.func.isRequired, +}; + export default connect(state => ({}), // eslint-disable-line no-unused-vars { loadFootNote } )(Translation); diff --git a/src/components/Verse/index.js b/src/components/Verse/index.js index db93f90a8..7a6a004e5 100644 --- a/src/components/Verse/index.js +++ b/src/components/Verse/index.js @@ -1,10 +1,9 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import Link from 'react-router/lib/Link'; import Element from 'react-scroll/lib/components/Element'; import { connect } from 'react-redux'; import Loadable from 'react-loadable'; - -import { verseType, matchType, surahType } from 'types'; import { load as loadAudio } from 'redux/actions/audioplayer'; import ComponentLoader from 'components/ComponentLoader'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; @@ -25,44 +24,6 @@ const Share = Loadable({ }); class Verse extends Component { - static propTypes = { - isSearched: PropTypes.bool, - verse: verseType.isRequired, - chapter: surahType.isRequired, - bookmarked: PropTypes.bool, // TODO: Add this for search - bookmarkActions: PropTypes.shape({ - isLoaded: PropTypes.func.isRequired, - load: PropTypes.func.isRequired, - addBookmark: PropTypes.func.isRequired, - removeBookmark: PropTypes.func.isRequired, - }), - mediaActions: PropTypes.shape({ - setMedia: PropTypes.func.isRequired, - removeMedia: PropTypes.func.isRequired, - }), - audioActions: PropTypes.shape({ - pause: PropTypes.func.isRequired, - setAyah: PropTypes.func.isRequired, - play: PropTypes.func.isRequired, - setCurrentWord: PropTypes.func.isRequired, - }), // not required because in search it is not. - match: PropTypes.arrayOf(matchType), - isPlaying: PropTypes.bool, - isAuthenticated: PropTypes.bool, - tooltip: PropTypes.string, - currentWord: PropTypes.number, // gets passed in an integer, null by default - iscurrentVerse: PropTypes.bool, - currentVerse: PropTypes.string, - userAgent: PropTypes.func, - audio: PropTypes.number.isRequired, - loadAudio: PropTypes.func.isRequired - }; - - - static defaultProps = { - currentWord: null, - isSearched: false - }; // TODO: Should this belong here? componentDidMount() { @@ -340,4 +301,29 @@ class Verse extends Component { } } +Verse.propTypes = { + isSearched: PropTypes.bool, + verse: customPropTypes.verseType.isRequired, + chapter: customPropTypes.surahType.isRequired, + bookmarked: PropTypes.bool, // TODO: Add this for search + bookmarkActions: customPropTypes.bookmarkActions, + mediaActions: customPropTypes.mediaActions, + audioActions: customPropTypes.audioActions, + match: customPropTypes.match, + isPlaying: PropTypes.bool, + isAuthenticated: PropTypes.bool, + tooltip: PropTypes.string, + currentWord: PropTypes.number, // gets passed in an integer, null by default + iscurrentVerse: PropTypes.bool, + currentVerse: PropTypes.string, + userAgent: PropTypes.func, + audio: PropTypes.number.isRequired, + loadAudio: PropTypes.func.isRequired +}; + +Verse.defaultProps = { + currentWord: null, + isSearched: false +}; + export default connect(() => ({}), { loadAudio })(Verse); diff --git a/src/components/VersesDropdown/index.js b/src/components/VersesDropdown/index.js index 27f8c9715..e619f2b28 100644 --- a/src/components/VersesDropdown/index.js +++ b/src/components/VersesDropdown/index.js @@ -1,26 +1,13 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import DropdownButton from 'react-bootstrap/lib/DropdownButton'; import MenuItem from 'react-bootstrap/lib/MenuItem'; import { Link } from 'react-scroll'; - import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import { surahType } from 'types'; const style = require('./style.scss'); -export default class VersesDropdown extends Component { - static propTypes = { - ayat: PropTypes.number.isRequired, - loadedAyahs: PropTypes.instanceOf(Set).isRequired, - chapter: surahType.isRequired, // Set - onClick: PropTypes.func.isRequired, - isReadingMode: PropTypes.bool, - className: PropTypes.string - }; - - static defaultProps = { - className: 'col-md-3' - }; +class VersesDropdown extends Component { renderItem = (ayah, index) => { const { chapter, loadedAyahs, isReadingMode, onClick } = this.props; @@ -73,3 +60,18 @@ export default class VersesDropdown extends Component { ); } } + +VersesDropdown.propTypes = { + ayat: PropTypes.number.isRequired, + loadedAyahs: PropTypes.instanceOf(Set).isRequired, + chapter: customPropTypes.surahType.isRequired, // Set + onClick: PropTypes.func.isRequired, + isReadingMode: PropTypes.bool, + className: PropTypes.string +}; + +VersesDropdown.defaultProps = { + className: 'col-md-3' +}; + +export default VersesDropdown; diff --git a/src/components/Word/index.js b/src/components/Word/index.js index bb93e969f..2c496209f 100644 --- a/src/components/Word/index.js +++ b/src/components/Word/index.js @@ -9,17 +9,7 @@ const CHAR_TYPE_PAUSE = 'pause'; const CHAR_TYPE_RUB = 'rub'; const CHAR_TYPE_SAJDAH = 'sajdah'; -export default class Word extends Component { - static propTypes = { - word: PropTypes.object.isRequired, // eslint-disable-line - tooltip: PropTypes.string, - audioActions: PropTypes.object.isRequired, // eslint-disable-line - audioPosition: PropTypes.number, - currentVerse: PropTypes.string.isRequired, - isPlaying: PropTypes.bool, - isSearched: PropTypes.bool, - useTextFont: PropTypes.bool // tmp change to compare text and code based rendering - }; +class Word extends Component { buildTooltip = (word, tooltip) => { let title; @@ -97,5 +87,17 @@ export default class Word extends Component { ); } - } + +Word.propTypes = { + word: PropTypes.object.isRequired, // eslint-disable-line + tooltip: PropTypes.string, + audioActions: PropTypes.object.isRequired, // eslint-disable-line + audioPosition: PropTypes.number, + currentVerse: PropTypes.string.isRequired, + isPlaying: PropTypes.bool, + isSearched: PropTypes.bool, + useTextFont: PropTypes.bool // tmp change to compare text and code based rendering +}; + +export default Word; diff --git a/src/containers/App/index.js b/src/containers/App/index.js index 2faa70f1b..b286543f9 100644 --- a/src/containers/App/index.js +++ b/src/containers/App/index.js @@ -1,15 +1,14 @@ /* eslint-disable react/prefer-stateless-function */ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { metrics } from 'react-metrics'; import { connect } from 'react-redux'; import { asyncConnect } from 'redux-connect'; import Helmet from 'react-helmet'; import Modal from 'react-bootstrap/lib/Modal'; import Loadable from 'react-loadable'; - import ComponentLoader from 'components/ComponentLoader'; import GlobalNav from 'components/GlobalNav'; - import debug from 'helpers/debug'; import config from 'config'; import metricsConfig from 'helpers/metrics'; @@ -17,11 +16,7 @@ import Footer from 'components/Footer'; import NoScript from 'components/NoScript'; import { removeMedia } from 'redux/actions/media'; import { removeFootNote } from 'redux/actions/footNote'; - import Loader from 'quran-components/lib/Loader'; - -import { footNoteType } from 'types'; - import authConnect from './connect'; const ModalHeader = Modal.Header; @@ -39,19 +34,6 @@ const SmartBanner = Loadable({ }); class App extends Component { - static propTypes = { - media: PropTypes.shape({ - content: PropTypes.object - }).isRequired, - removeMedia: PropTypes.func.isRequired, - removeFootNote: PropTypes.func.isRequired, - children: PropTypes.element, - main: PropTypes.element, - nav: PropTypes.element, - sidebar: PropTypes.element, - footNote: footNoteType, - loadingFootNote: PropTypes.bool - }; static contextTypes = { store: PropTypes.object.isRequired @@ -150,6 +132,18 @@ class App extends Component { const metricsApp = metrics(metricsConfig)(App); const AsyncApp = asyncConnect([{ promise: authConnect }])(metricsApp); +App.propTypes = { + media: customPropTypes.media.isRequired, + removeMedia: PropTypes.func.isRequired, + removeFootNote: PropTypes.func.isRequired, + children: PropTypes.element, + main: PropTypes.element, + nav: PropTypes.element, + sidebar: PropTypes.element, + footNote: customPropTypes.footNoteType, + loadingFootNote: PropTypes.bool +}; + export default connect( state => ({ media: state.media, diff --git a/src/containers/ChapterInfo/index.js b/src/containers/ChapterInfo/index.js index 914118eeb..617d9dd84 100644 --- a/src/containers/ChapterInfo/index.js +++ b/src/containers/ChapterInfo/index.js @@ -1,5 +1,5 @@ +import * as customPropTypes from 'customPropTypes'; import React from 'react'; - import { connect } from 'react-redux'; import { asyncConnect } from 'redux-connect'; @@ -8,7 +8,6 @@ import Loadable from 'react-loadable'; import Button from 'quran-components/lib/Button'; import ComponentLoader from 'components/ComponentLoader'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import { surahType, infoType } from 'types'; import makeHeadTags from 'helpers/makeHeadTags'; import { chaptersConnect, chapterInfoConnect } from '../Surah/connect'; @@ -62,8 +61,8 @@ const ChapterInfo = ({ chapter, info }) => ( ); ChapterInfo.propTypes = { - chapter: surahType, - info: infoType + chapter: customPropTypes.surahType, + info: customPropTypes.infoType }; const AsyncChapterInfo = asyncConnect([ diff --git a/src/containers/Contact/index.js b/src/containers/Contact/index.js index a9b1ac15e..0d804fc46 100644 --- a/src/containers/Contact/index.js +++ b/src/containers/Contact/index.js @@ -3,7 +3,7 @@ import superagent from 'superagent'; import IndexHeader from 'components/IndexHeader'; -export default class Contact extends Component { +class Contact extends Component { state = { success: false }; @@ -113,3 +113,5 @@ export default class Contact extends Component { ); } } + +export default Contact; diff --git a/src/containers/Home/index.js b/src/containers/Home/index.js index b93b3f5b0..1f6f522b3 100644 --- a/src/containers/Home/index.js +++ b/src/containers/Home/index.js @@ -1,4 +1,5 @@ -import React, { PropTypes } from 'react'; +import React from 'react'; +import * as customPropTypes from 'customPropTypes'; import Helmet from 'react-helmet'; import IndexHeader from 'components/IndexHeader'; import cookie from 'react-cookie'; @@ -6,12 +7,10 @@ import { asyncConnect } from 'redux-connect'; import { connect } from 'react-redux'; import debug from 'helpers/debug'; import { isAllLoaded, loadAll } from 'redux/actions/chapters.js'; - import LastVisit from 'components/Home/LastVisit'; import SurahsList from 'components/Home/SurahsList'; import QuickSurahs from 'components/Home/QuickSurahs'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import { surahType } from 'types'; const styles = require('./style.scss'); @@ -48,7 +47,7 @@ const Home = (props) => { }; Home.propTypes = { - chapters: PropTypes.objectOf(surahType).isRequired + chapters: customPropTypes.chapters.isRequired }; const AsyncHome = asyncConnect([{ diff --git a/src/containers/Profile/index.js b/src/containers/Profile/index.js index 39450ee1a..7b834041d 100644 --- a/src/containers/Profile/index.js +++ b/src/containers/Profile/index.js @@ -1,21 +1,15 @@ import React, { Component } from 'react'; +import * as customPropTypes from 'customPropTypes'; import Helmet from 'react-helmet'; import { connect } from 'react-redux'; import { Link } from 'react-router'; - import Image from 'react-bootstrap/lib/Image'; import Tabs from 'react-bootstrap/lib/Tabs'; import Tab from 'react-bootstrap/lib/Tab'; -import { bookmarkType, userType } from 'types'; - const styles = require('./style.scss'); class Profile extends Component { // eslint-disable-line - static propTypes = { - user: userType.isRequired, - bookmarks: bookmarkType.isRequired - }; render() { const { user, bookmarks } = this.props; @@ -59,6 +53,11 @@ class Profile extends Component { // eslint-disable-line } } +Profile.propTypes = { + user: customPropTypes.userType.isRequired, + bookmarks: customPropTypes.bookmarkType.isRequired +}; + export default connect( state => ({ user: state.auth.user, diff --git a/src/containers/Search/index.js b/src/containers/Search/index.js index cfc96ee87..c83efa6a7 100644 --- a/src/containers/Search/index.js +++ b/src/containers/Search/index.js @@ -1,6 +1,6 @@ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import { PropTypes as MetricsPropTypes } from 'react-metrics'; - import { asyncConnect } from 'redux-connect'; import { connect } from 'react-redux'; import { push } from 'react-router-redux'; @@ -8,40 +8,14 @@ import Helmet from 'react-helmet'; import ReactPaginate from 'react-paginate'; import { FormattedHTMLMessage } from 'react-intl'; import IndexHeader from 'components/IndexHeader'; - import Verse from 'components/Verse'; import Loader from 'quran-components/lib/Loader'; - import { search } from 'redux/actions/search.js'; - import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import { verseType, optionsType } from 'types'; - const style = require('./style.scss'); class Search extends Component { - static propTypes = { - isErrored: PropTypes.bool, - isLoading: PropTypes.bool, - totalCount: PropTypes.number, - totalPages: PropTypes.number, - currentPage: PropTypes.number, - perPage: PropTypes.number, - query: PropTypes.string, - results: PropTypes.arrayOf(PropTypes.string), - entities: PropTypes.arrayOf(verseType), - push: PropTypes.func.isRequired, - location: PropTypes.shape({ // eslint-disable-line - q: PropTypes.string, - p: PropTypes.string - }), - options: optionsType - }; - - static defaultProps = { - results: [] - }; static contextTypes = { metrics: MetricsPropTypes.metrics @@ -187,6 +161,28 @@ class Search extends Component { } } +Search.propTypes = { + isErrored: PropTypes.bool, + isLoading: PropTypes.bool, + totalCount: PropTypes.number, + totalPages: PropTypes.number, + currentPage: PropTypes.number, + perPage: PropTypes.number, + query: PropTypes.string, + results: PropTypes.arrayOf(PropTypes.string), + entities: PropTypes.arrayOf(customPropTypes.verseType), + push: PropTypes.func.isRequired, + location: PropTypes.shape({ // eslint-disable-line + q: PropTypes.string, + p: PropTypes.string + }), + options: customPropTypes.optionsType +}; + +Search.defaultProps = { + results: [] +}; + const AsyncSearch = asyncConnect([{ promise({ store: { dispatch }, location }) { if (__CLIENT__) { diff --git a/src/containers/Surah/index.js b/src/containers/Surah/index.js index 2242ea965..9e207c39d 100644 --- a/src/containers/Surah/index.js +++ b/src/containers/Surah/index.js @@ -1,5 +1,6 @@ /* global window, document */ import React, { Component, PropTypes } from 'react'; +import * as customPropTypes from 'customPropTypes'; import Link from 'react-router/lib/Link'; // redux import { bindActionCreators } from 'redux'; @@ -25,8 +26,6 @@ import scroller from 'utils/scroller'; import makeHeadTags from 'helpers/makeHeadTags'; import debug from 'helpers/debug'; -import { surahType, verseType, infoType } from 'types'; - import * as AudioActions from 'redux/actions/audioplayer.js'; import * as AyahActions from 'redux/actions/verses.js'; import * as BookmarkActions from 'redux/actions/bookmarks.js'; @@ -58,27 +57,6 @@ const TopOptions = Loadable({ }); class Surah extends Component { - static propTypes = { - chapter: surahType.isRequired, - chapters: PropTypes.objectOf(surahType).isRequired, - actions: PropTypes.object.isRequired, // eslint-disable-line - lines: PropTypes.object.isRequired, // eslint-disable-line - isEndOfSurah: PropTypes.bool.isRequired, - verseIds: PropTypes.instanceOf(Set), - currentVerse: PropTypes.string, - info: infoType, - bookmarks: PropTypes.object.isRequired, // eslint-disable-line - isLoading: PropTypes.bool.isRequired, - isLoaded: PropTypes.bool.isRequired, - isSingleAyah: PropTypes.bool.isRequired, - isAuthenticated: PropTypes.bool.isRequired, - options: PropTypes.object.isRequired, // eslint-disable-line - params: PropTypes.shape({ - chapterId: PropTypes.string.isRequired - }).isRequired, - verses: PropTypes.objectOf(verseType), - isPlaying: PropTypes.bool - }; state = { lazyLoading: false, @@ -421,6 +399,28 @@ class Surah extends Component { } } +Surah.propTypes = { + chapter: customPropTypes.surahType.isRequired, + chapters: customPropTypes.chapters.isRequired, + actions: PropTypes.object.isRequired, // eslint-disable-line + lines: PropTypes.object.isRequired, // eslint-disable-line + isEndOfSurah: PropTypes.bool.isRequired, + verseIds: PropTypes.instanceOf(Set), + currentVerse: PropTypes.string, + info: customPropTypes.infoType, + bookmarks: PropTypes.object.isRequired, // eslint-disable-line + isLoading: PropTypes.bool.isRequired, + isLoaded: PropTypes.bool.isRequired, + isSingleAyah: PropTypes.bool.isRequired, + isAuthenticated: PropTypes.bool.isRequired, + options: PropTypes.object.isRequired, // eslint-disable-line + params: PropTypes.shape({ + chapterId: PropTypes.string.isRequired + }).isRequired, + verses: customPropTypes.verses, + isPlaying: PropTypes.bool +}; + const AsyncSurah = asyncConnect([ { promise: chaptersConnect }, { promise: chapterInfoConnect }, diff --git a/src/customPropTypes.js b/src/customPropTypes.js new file mode 100644 index 000000000..edc2b5d3f --- /dev/null +++ b/src/customPropTypes.js @@ -0,0 +1,226 @@ +import { PropTypes } from 'react'; + +export const bookmarkActions = PropTypes.shape({ + isLoaded: PropTypes.func.isRequired, + load: PropTypes.func.isRequired, + addBookmark: PropTypes.func.isRequired, + removeBookmark: PropTypes.func.isRequired +}); + +export const bookmarkType = PropTypes.shape({ + id: PropTypes.string.isRequired, + verseKey: PropTypes.string.isRequired, + createdAt: PropTypes.string.isRequired, + updatedAt: PropTypes.string.isRequired, +}); + +export const contentType = PropTypes.shape({ + id: PropTypes.number, + authorName: PropTypes.string, + languageName: PropTypes.string +}); + +export const footNoteType = PropTypes.shape({ + id: PropTypes.number, + text: PropTypes.string, + language_name: PropTypes.string +}); + +export const infoType = PropTypes.shape({ + chapterId: PropTypes.number.isRequired, + text: PropTypes.string.isRequired, + source: PropTypes.string.isRequired, + shortText: PropTypes.string.isRequired, + languageName: PropTypes.string.isRequired +}); + +export const media = PropTypes.shape({ + content: PropTypes.object +}); + +export const mediaActions = PropTypes.shape({ + setMedia: PropTypes.func.isRequired, + removeMedia: PropTypes.func.isRequired +}); + +export const audioActions = PropTypes.shape({ + pause: PropTypes.func.isRequired, + setAyah: PropTypes.func.isRequired, + play: PropTypes.func.isRequired, + setCurrentWord: PropTypes.func.isRequired, +}); + +export const language = PropTypes.shape({ + beta: PropTypes.bool, + direction: PropTypes.string.isRequired, + english: PropTypes.string.isRequired, + esAnalyzerDefault: PropTypes.string, + languageCode: PropTypes.string.isRequired, + priority: PropTypes.number.isRequired, + unicode: PropTypes.string, +}); + +export const matchType = PropTypes.shape({ + score: PropTypes.number.isRequired, + text: PropTypes.string.isRequired, + languageCode: PropTypes.string.isRequired, + subType: PropTypes.string.isRequired, + cardinalityType: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + resourceId: PropTypes.number.isRequired, + description: PropTypes.string, + language: language.isRequired, + sourceId: PropTypes.number.isRequired, + type: PropTypes.string.isRequired, + authorId: PropTypes.number.isRequired, + slug: PropTypes.string.isRequired, + isAvailable: PropTypes.bool +}); + +export const fontSize = PropTypes.shape({ + arabic: PropTypes.number, + translations: PropTypes.number +}); + +export const location = PropTypes.shape({ + action: PropTypes.string, + hash: PropTypes.string, + pathname: PropTypes.string, + search: PropTypes.string, + query: PropTypes.objectOf(PropTypes.string) +}); + +export const optionsType = PropTypes.shape({ + isReadingMode: PropTypes.bool, + isShowingSurahInfo: PropTypes.bool, + audio: PropTypes.number, + quran: PropTypes.number, + content: PropTypes.arrayOf(PropTypes.number), + tooltip: PropTypes.string, + fontSize: fontSize.isRequired +}); + +export const recitationTypes = PropTypes.shape({ + id: PropTypes.number, + style: PropTypes.string, + reciter_name_eng: PropTypes.string +}); + +export const surahType = PropTypes.shape({ + id: PropTypes.number.isRequired, + versesCount: PropTypes.number.isRequired, + bismillahPre: PropTypes.bool.isRequired, + revelationOrder: PropTypes.number.isRequired, + revelationPlace: PropTypes.string.isRequired, + pages: PropTypes.arrayOf(PropTypes.number).isRequired, + nameComplex: PropTypes.string.isRequired, + nameSimple: PropTypes.string.isRequired, + nameArabic: PropTypes.string.isRequired, +}); + +export const timeInterval = PropTypes.shape({ + from: PropTypes.number, + to: PropTypes.number, + time: PropTypes.number, +}); + +export const translationType = PropTypes.shape({ + languageName: PropTypes.string.isRequired, + text: PropTypes.string.isRequired, + resourceName: PropTypes.string.isRequired +}); + +export const translation = PropTypes.shape({ + languageName: PropTypes.string, + text: PropTypes.string +}); + +export const transliteration = PropTypes.shape({ + languageName: PropTypes.string, + text: PropTypes.string +}); + +export const translationOptions = PropTypes.arrayOf(contentType); + +export const userType = PropTypes.shape({ + provider: PropTypes.string, + uid: PropTypes.string, + firstName: PropTypes.string, + lastName: PropTypes.string, + username: PropTypes.string, + link: PropTypes.string, + image: PropTypes.string, + email: PropTypes.string, + name: PropTypes.string +}); + +export const wordType = PropTypes.shape({ + arabic: PropTypes.string, + verseKey: PropTypes.string.isRequired, + charType: PropTypes.string.isRequired, + className: PropTypes.string.isRequired, + code: PropTypes.string.isRequired, + lineNumber: PropTypes.number.isRequired, + pageNumber: PropTypes.number.isRequired, + position: PropTypes.number.isRequired, + translation, + transliteration, + wordId: PropTypes.number +}); + +export const verseType = PropTypes.shape({ + id: PropTypes.number.isRequired, + chapterId: PropTypes.number.isRequired, + pageNumber: PropTypes.number.isRequired, + juzNumber: PropTypes.number.isRequired, + hizbNumber: PropTypes.number.isRequired, + rubNumber: PropTypes.number.isRequired, + verseKey: PropTypes.string.isRequired, + sajdah: PropTypes.bool, + words: PropTypes.arrayOf(wordType).isRequired, + textMadani: PropTypes.string.isRequired, + textSimple: PropTypes.string.isRequired, + translations: PropTypes.arrayOf(translationType), // NOTE: In search, it is not required. + audio: PropTypes.object // NOTE: In search, it is not required. +}); + +export const verses = PropTypes.objectOf(verseType); + +export const words = PropTypes.shape({ + startTime: PropTypes.number.isRequired, + endTime: PropTypes.number.isRequired, + duration: PropTypes.number.isRequired, +}); + +export const segmentType = PropTypes.shape({ + words, + intervals: PropTypes.oneOfType([ + PropTypes.array, + PropTypes.object + ]) // TODO: This should be done a better way. +}); + +export const segments = PropTypes.objectOf(segmentType); + +export const match = PropTypes.arrayOf(matchType); + +export const chapters = PropTypes.objectOf(surahType); + +export const line = PropTypes.arrayOf(wordType); + +export const recitations = PropTypes.arrayOf(recitationTypes); + +export const suggestion = PropTypes.shape({ + ayah: PropTypes.string, + href: PropTypes.string.isRequired, + text: PropTypes.string.isRequired +}); + +export const suggestions = PropTypes.arrayOf(suggestion); + +export const storeText = PropTypes.shape({ + ios: PropTypes.string.isRequired, + android: PropTypes.string.isRequired, + windows: PropTypes.string.isRequired, + kindle: PropTypes.string.isRequired, +}); diff --git a/src/types/bookmarkType.js b/src/types/bookmarkType.js deleted file mode 100644 index b33c50434..000000000 --- a/src/types/bookmarkType.js +++ /dev/null @@ -1,8 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - id: PropTypes.string.isRequired, - verseKey: PropTypes.string.isRequired, - createdAt: PropTypes.string.isRequired, - updatedAt: PropTypes.string.isRequired, -}); diff --git a/src/types/contentType.js b/src/types/contentType.js deleted file mode 100644 index fc7ca6b5c..000000000 --- a/src/types/contentType.js +++ /dev/null @@ -1,7 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - id: PropTypes.number, - authorName: PropTypes.string, - languageName: PropTypes.string -}); diff --git a/src/types/footNoteType.js b/src/types/footNoteType.js deleted file mode 100644 index 6669b34c8..000000000 --- a/src/types/footNoteType.js +++ /dev/null @@ -1,7 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - id: PropTypes.number, - text: PropTypes.string, - language_name: PropTypes.string -}); diff --git a/src/types/index.js b/src/types/index.js deleted file mode 100644 index af5c89f1e..000000000 --- a/src/types/index.js +++ /dev/null @@ -1,13 +0,0 @@ -export { default as verseType } from './verseType'; -export { default as surahType } from './surahType'; -export { default as userType } from './userType'; -export { default as optionsType } from './optionsType'; -export { default as bookmarkType } from './bookmarkType'; -export { default as segmentType } from './segmentType'; -export { default as wordType } from './wordType'; -export { default as matchType } from './matchType'; -export { default as recitationType } from './recitationType'; -export { default as translationType } from './translationType'; -export { default as contentType } from './contentType'; -export { default as footNoteType } from './footNoteType'; -export { default as infoType } from './infoType'; diff --git a/src/types/infoType.js b/src/types/infoType.js deleted file mode 100644 index bd284088d..000000000 --- a/src/types/infoType.js +++ /dev/null @@ -1,9 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - chapterId: PropTypes.number.isRequired, - text: PropTypes.string.isRequired, - source: PropTypes.string.isRequired, - shortText: PropTypes.string.isRequired, - languageName: PropTypes.string.isRequired -}); diff --git a/src/types/matchType.js b/src/types/matchType.js deleted file mode 100644 index d644eebf1..000000000 --- a/src/types/matchType.js +++ /dev/null @@ -1,26 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - score: PropTypes.number.isRequired, - text: PropTypes.string.isRequired, - languageCode: PropTypes.string.isRequired, - subType: PropTypes.string.isRequired, - cardinalityType: PropTypes.string.isRequired, - name: PropTypes.string.isRequired, - resourceId: PropTypes.number.isRequired, - description: PropTypes.string, - language: PropTypes.shape({ - beta: PropTypes.bool, - direction: PropTypes.string.isRequired, - english: PropTypes.string.isRequired, - esAnalyzerDefault: PropTypes.string, - languageCode: PropTypes.string.isRequired, - priority: PropTypes.number.isRequired, - unicode: PropTypes.string, - }).isRequired, - sourceId: PropTypes.number.isRequired, - type: PropTypes.string.isRequired, - authorId: PropTypes.number.isRequired, - slug: PropTypes.string.isRequired, - isAvailable: PropTypes.bool -}); diff --git a/src/types/optionsType.js b/src/types/optionsType.js deleted file mode 100644 index 166def45d..000000000 --- a/src/types/optionsType.js +++ /dev/null @@ -1,14 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - isReadingMode: PropTypes.bool, - isShowingSurahInfo: PropTypes.bool, - audio: PropTypes.number, - quran: PropTypes.number, - content: PropTypes.arrayOf(PropTypes.number), - tooltip: PropTypes.string, - fontSize: PropTypes.shape({ - arabic: PropTypes.number, - translations: PropTypes.number - }).isRequired -}); diff --git a/src/types/recitationType.js b/src/types/recitationType.js deleted file mode 100644 index a83c18252..000000000 --- a/src/types/recitationType.js +++ /dev/null @@ -1,7 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - id: PropTypes.number, - style: PropTypes.string, - reciter_name_eng: PropTypes.string -}); diff --git a/src/types/segmentType.js b/src/types/segmentType.js deleted file mode 100644 index d564817fb..000000000 --- a/src/types/segmentType.js +++ /dev/null @@ -1,13 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - words: PropTypes.objectOf(PropTypes.shape({ - startTime: PropTypes.number.isRequired, - endTime: PropTypes.number.isRequired, - duration: PropTypes.number.isRequired, - })), - intervals: PropTypes.oneOfType([ - PropTypes.array, - PropTypes.object - ]) // TODO: This should be done a better way. -}); diff --git a/src/types/surahType.js b/src/types/surahType.js deleted file mode 100644 index 121e48d21..000000000 --- a/src/types/surahType.js +++ /dev/null @@ -1,13 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - id: PropTypes.number.isRequired, - versesCount: PropTypes.number.isRequired, - bismillahPre: PropTypes.bool.isRequired, - revelationOrder: PropTypes.number.isRequired, - revelationPlace: PropTypes.string.isRequired, - pages: PropTypes.arrayOf(PropTypes.number).isRequired, - nameComplex: PropTypes.string.isRequired, - nameSimple: PropTypes.string.isRequired, - nameArabic: PropTypes.string.isRequired, -}); diff --git a/src/types/translationType.js b/src/types/translationType.js deleted file mode 100644 index de4406bf5..000000000 --- a/src/types/translationType.js +++ /dev/null @@ -1,7 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - languageName: PropTypes.string.isRequired, - text: PropTypes.string.isRequired, - resourceName: PropTypes.string.isRequired -}); diff --git a/src/types/userType.js b/src/types/userType.js deleted file mode 100644 index fdacf55a3..000000000 --- a/src/types/userType.js +++ /dev/null @@ -1,13 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - provider: PropTypes.string, - uid: PropTypes.string, - firstName: PropTypes.string, - lastName: PropTypes.string, - username: PropTypes.string, - link: PropTypes.string, - image: PropTypes.string, - email: PropTypes.string, - name: PropTypes.string -}); diff --git a/src/types/verseType.js b/src/types/verseType.js deleted file mode 100644 index 1f5850e3b..000000000 --- a/src/types/verseType.js +++ /dev/null @@ -1,19 +0,0 @@ -import { PropTypes } from 'react'; -import wordType from './wordType'; -import translationType from './translationType'; - -export default PropTypes.shape({ - id: PropTypes.number.isRequired, - chapterId: PropTypes.number.isRequired, - pageNumber: PropTypes.number.isRequired, - juzNumber: PropTypes.number.isRequired, - hizbNumber: PropTypes.number.isRequired, - rubNumber: PropTypes.number.isRequired, - verseKey: PropTypes.string.isRequired, - sajdah: PropTypes.bool, - words: PropTypes.arrayOf(wordType).isRequired, - textMadani: PropTypes.string.isRequired, - textSimple: PropTypes.string.isRequired, - translations: PropTypes.arrayOf(translationType), // NOTE: In search, it is not required. - audio: PropTypes.object // NOTE: In search, it is not required. -}); diff --git a/src/types/wordType.js b/src/types/wordType.js deleted file mode 100644 index 76e247740..000000000 --- a/src/types/wordType.js +++ /dev/null @@ -1,21 +0,0 @@ -import { PropTypes } from 'react'; - -export default PropTypes.shape({ - arabic: PropTypes.string, - verseKey: PropTypes.string.isRequired, - charType: PropTypes.string.isRequired, - className: PropTypes.string.isRequired, - code: PropTypes.string.isRequired, - lineNumber: PropTypes.number.isRequired, - pageNumber: PropTypes.number.isRequired, - position: PropTypes.number.isRequired, - translation: PropTypes.shape({ - languageName: PropTypes.string, - text: PropTypes.string - }), - transliteration: PropTypes.shape({ - languageName: PropTypes.string, - text: PropTypes.string - }), - wordId: PropTypes.number, -});