diff --git a/package.json b/package.json index 53e271315..0d4313466 100644 --- a/package.json +++ b/package.json @@ -6,14 +6,14 @@ "scripts": { "test": "npm run test:dev:unit", "test:ci:unit": "karma start --browsers PhantomJS --single-run", - "posttest:ci:unit": "npm run test:ci:lint", + "pretest:ci:unit": "npm run test:ci:lint", "test:ci:functional": "BROWSER=phantomjs ./tests/functional/test.sh start-ci", "posttest:ci:functional": "./tests/functional/test.sh stop", "test:dev:unit": "karma start", - "test:ci:lint": "./node_modules/eslint/bin/eslint.js ./src/**/*.js", + "test:ci:lint": "./node_modules/eslint/bin/eslint.js ./src", "test:dev:functional": "BROWSER=chrome ./tests/functional/test.sh start", "posttest:dev:functional": "./tests/functional/test.sh stop", - "test:dev:lint": "eslint ./src/scripts/**/*.js", + "test:dev:lint": "./node_modules/eslint/bin/eslint.js ./src", "test:stylelint": "stylelint './src/**/*.scss' --config ./webpack/.stylelintrc", "dev": "env NODE_PATH='./src' PORT=8000 UV_THREADPOOL_SIZE=100 node ./webpack/webpack-dev-server.js & env NODE_PATH='./src' PORT=8000 node ./bin/server.js", "start": "NODE_PATH='src' node ./start", diff --git a/src/components/Ayah/index.js b/src/components/Ayah/index.js index 68885911f..9f480babb 100644 --- a/src/components/Ayah/index.js +++ b/src/components/Ayah/index.js @@ -9,8 +9,6 @@ import Word from 'components/Word'; import debug from 'helpers/debug'; -import bindTooltip from 'utils/bindTooltip'; - const styles = require('./style.scss'); export default class Ayah extends Component { @@ -48,10 +46,6 @@ export default class Ayah extends Component { isSearched: false }; - componentDidMount() { - bindTooltip(); - } - shouldComponentUpdate(nextProps) { const conditions = [ this.props.ayah !== nextProps.ayah, @@ -99,7 +93,7 @@ export default class Ayah extends Component {

{content.name || content.resource.name}

@@ -148,20 +142,22 @@ export default class Ayah extends Component { } renderText() { - const { ayah, tooltip, currentAyah, isPlaying, audioActions, isSearched} = this.props; - - const text = ayah.words.map(word => { - return( - - ) - }); + const { ayah, tooltip, currentAyah, isPlaying, audioActions, isSearched } = this.props; + // NOTE: Some 'word's are glyphs (jeem). Not words and should not be clicked for audio + let wordAudioPosition = -1; + + const text = ayah.words.map(word => ( // eslint-disable-line + + )); return (

@@ -187,7 +183,7 @@ export default class Ayah extends Component { onClick={() => this.handlePlay(ayah.ayahKey)} className="text-muted" > - + {' '} bookmarkActions.removeBookmark(ayah.ayahKey)} className="text-muted" > - + + {' '} bookmarkActions.addBookmark(ayah.ayahKey)} className="text-muted" > - + {' '} { const { onOptionChange } = this.props; @@ -469,7 +461,7 @@ export default class ContentDropdown extends Component { } handleOptionSelected(id) { - const { onOptionChange, options: { content } } = this.props; + const { onOptionChange, content } = this.props; if (content.find(option => option === id)) { onOptionChange({ content: content.filter(option => option !== id) }); @@ -479,7 +471,7 @@ export default class ContentDropdown extends Component { } renderItems(items) { - const { options: { content } } = this.props; + const { content } = this.props; return items.map((slug) => { const checked = content.find(option => option === slug.id); @@ -515,29 +507,34 @@ export default class ContentDropdown extends Component { } render() { - const { className, options: { content } } = this.props; + const { className, content } = this.props; + const title = slugs.filter(slug => content.includes(slug.id)).map(slug => slug.name).join(', '); return ( - } - > - { - content.length && - - - - } - - - - {this.renderEnglishList()} - - - - - {this.renderLanguagesList()} - + + + { + content.length && + + + + } + + + + {this.renderEnglishList()} + + + + + {this.renderLanguagesList()} + + ); } } diff --git a/src/components/ContentDropdown/spec.js b/src/components/ContentDropdown/spec.js index 34b375361..b6a377767 100644 --- a/src/components/ContentDropdown/spec.js +++ b/src/components/ContentDropdown/spec.js @@ -12,7 +12,7 @@ describe('', () => { onOptionChange = sinon.stub(); wrapper = mountWithIntl( ); diff --git a/src/components/Copy/index.js b/src/components/Copy/index.js index b6013450e..02f5562c9 100644 --- a/src/components/Copy/index.js +++ b/src/components/Copy/index.js @@ -28,7 +28,7 @@ export default class Copy extends Component { className={!isCopied && 'text-muted'} data-metrics-event-name="Ayah:Copy" > - + {' '} { - const { onOptionChange, options: { fontSize } } = this.props; + const { onOptionChange, fontSize } = this.props; const changeFactor = { translation: 0.5, arabic: 0.5 @@ -94,15 +95,17 @@ export default class FontSizeDropdown extends Component { render() { return ( - - - - - +
  • + + + + {' '} + + +
  • ); } } diff --git a/src/components/FontSizeDropdown/style.scss b/src/components/FontSizeDropdown/style.scss index 298b6cf11..4f19f8725 100644 --- a/src/components/FontSizeDropdown/style.scss +++ b/src/components/FontSizeDropdown/style.scss @@ -1,6 +1,6 @@ @import '../../styles/variables.scss'; -:local .popover{ +.popover{ :global(.popover-title){ font-family: $font-montserrat; text-transform: uppercase; @@ -16,3 +16,9 @@ } } } + +.link{ + position: relative; + display: block; + cursor: pointer; +} diff --git a/src/components/Footer/index.js b/src/components/Footer/index.js index 6641a7fdd..adb461302 100644 --- a/src/components/Footer/index.js +++ b/src/components/Footer/index.js @@ -5,7 +5,6 @@ import Grid from 'react-bootstrap/lib/Grid'; import Col from 'react-bootstrap/lib/Col'; import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -import LocaleSwitcher from 'components/LocaleSwitcher'; const styles = require('./style.scss'); @@ -144,7 +143,6 @@ const Footer = () => (

    -

    ( + , + } + > + + + + + + ]} + rightControls={[ + , + , + , + + ]} + /> +); + +GlobalNavSurah.propTypes = { + surah: surahType.isRequired, + surahs: PropTypes.objectOf(surahType).isRequired, + options: optionsType.isRequired, + setOption: PropTypes.func.isRequired, +}; + +function mapStateToProps(state, ownProps) { + const surahId = parseInt(ownProps.params.surahId, 10); + const surah: Object = state.surahs.entities[surahId]; + + return { + surah, + surahs: state.surahs.entities, + options: state.options + }; +} + +export default connect(mapStateToProps, OptionsActions)(GlobalNavSurah); diff --git a/src/components/GlobalNav/index.js b/src/components/GlobalNav/index.js new file mode 100644 index 000000000..60aeaa33e --- /dev/null +++ b/src/components/GlobalNav/index.js @@ -0,0 +1,130 @@ +/* global window */ +import React, { PropTypes, Component } from 'react'; +import { connect } from 'react-redux'; +import Link from 'react-router/lib/Link'; +import Navbar from 'react-bootstrap/lib/Navbar'; +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 + } + + componentDidMount() { + window.addEventListener('scroll', this.handleNavbar, true); + } + + componentWillUnmount() { + window.removeEventListener('scroll', this.handleNavbar, true); + } + + handleNavbar = () => { + const { isStatic } = this.props; + const { scrolled } = this.state; + + if (window.pageYOffset > 50) { + if (!scrolled && !isStatic) { + this.setState({ scrolled: true }); + } + } else if (scrolled) { + this.setState({ scrolled: false }); + } + + return false; + } + + isHome() { + return this.props.location.pathname === '/'; + } + + renderRightControls() { + const { user, rightControls } = this.props; + + return rightControls || [ + , + user ? +

  • + + {user.firstName || user.name} + +
  • : +