diff --git a/api/models/related.js b/api/models/related.js new file mode 100644 index 0000000..1c70e4c --- /dev/null +++ b/api/models/related.js @@ -0,0 +1,20 @@ +module.exports = function init(sequelize, DataTypes) { + const Related = sequelize.define('related', { + qari: DataTypes.INTEGER, + related: { type: DataTypes.INTEGER, field: 'related', primaryKey: true } + }, { + timestamps: false, + paranoid: true, + underscored: true, + tableName: 'related', + instanceMethods: { + toJSON: function json() { + return { + id: this.related + }; + } + } + + }); + return Related; +}; diff --git a/api/routes/qaris.js b/api/routes/qaris.js index 7c1234c..674495b 100644 --- a/api/routes/qaris.js +++ b/api/routes/qaris.js @@ -28,5 +28,8 @@ router.get('/:id/audio_files/:type', (req, res) => { }); }); +router.get('/related/:id', (req, res) => { + models.related.findAll({ where: { qari: req.params.id}}).then(related => res.send(related)); +}); export default router; diff --git a/src/actions/related.js b/src/actions/related.js new file mode 100644 index 0000000..20f9be9 --- /dev/null +++ b/src/actions/related.js @@ -0,0 +1,15 @@ +import { arrayOf } from 'normalizr'; +import { relatedSchema } from 'utils/schemas'; + +export const LOAD = '@@quran/related/LOAD'; +export const LOAD_SUCCESS = '@@quran/related/LOAD_SUCCESS'; +export const LOAD_FAIL = '@@quran/related/LOAD_FAIL'; + +export function load(id) { + return { + types: [LOAD, LOAD_SUCCESS, LOAD_FAIL], + schema: arrayOf(relatedSchema), + promise: (client) => client.get(`/qaris/related/${id}`), + id + }; +} diff --git a/src/components/Related/index.js b/src/components/Related/index.js new file mode 100644 index 0000000..976588a --- /dev/null +++ b/src/components/Related/index.js @@ -0,0 +1,16 @@ +import React, { PropTypes } from 'react'; +const styles = require('./style.scss'); +import Link from 'react-router/lib/Link'; +const Related = ({related = [], qaris, toggle}) => { + const li = related.map((item, index) => (
  • {qaris[item].name}
  • )); + return ( + + ); +}; + +Related.PropTypes = { + related: PropTypes.array.isRequired, + qaris: PropTypes.any.isRequired +}; + +export default Related; diff --git a/src/components/Related/style.scss b/src/components/Related/style.scss new file mode 100644 index 0000000..4ab6d62 --- /dev/null +++ b/src/components/Related/style.scss @@ -0,0 +1,27 @@ +.container { + list-style: none; + visibility: hidden; + opacity: 0; + transition: height .5s, opacity 0.5s linear; + margin: 0; + height: 0; + position: relative; + top: 10px; +} + +.active { + visibility: visible; + opacity: 1; + margin: 5px; + height: 15px; + +} + +.item { + display: inline-block; + padding-right: 5px; +} + +.link { + color: white; +} \ No newline at end of file diff --git a/src/containers/App/index.js b/src/containers/App/index.js index a1be23d..4383b37 100644 --- a/src/containers/App/index.js +++ b/src/containers/App/index.js @@ -79,5 +79,5 @@ export default asyncConnect([ return dispatch(loadSurahs()); } } - }, + } ])(App); diff --git a/src/containers/Qari/index.js b/src/containers/Qari/index.js index 6e9626f..1ccd555 100644 --- a/src/containers/Qari/index.js +++ b/src/containers/Qari/index.js @@ -8,29 +8,35 @@ import Button from 'react-bootstrap/lib/Button'; import Helmet from 'react-helmet'; import { load, play, next, random} from 'actions/audioplayer'; import { load as loadFiles } from 'actions/files'; +import { load as loadRelated } from 'actions/related'; import zeroPad from 'utils/zeroPad'; import formatSeconds from 'utils/formatSeconds'; import Track from 'components/Audioplayer/Track'; import LinkContainer from 'utils/LinkContainer'; +import Related from 'components/Related'; const styles = require('./style.scss'); class Qaris extends Component { static propTypes = { surahs: PropTypes.object.isRequired, + qaris: PropTypes.any.isRequired, qari: PropTypes.object.isRequired, files: PropTypes.object.isRequired, currentTime: PropTypes.any, progress: PropTypes.number, + related: PropTypes.array.isRequired, load: PropTypes.func.isRequired, play: PropTypes.func.isRequired, currentSurah: PropTypes.any, currentQari: PropTypes.any, next: PropTypes.func.isRequired, random: PropTypes.func.isRequired, - shouldRandom: PropTypes.bool, + shouldContinuous: PropTypes.bool, isPlaying: PropTypes.bool.isRequired }; + state = { toggleRelated: false }; + handleSurahSelection = (surah) => { const { qari, currentSurah, currentQari } = this.props; const currenSurahId = currentSurah ? currentSurah.id : {}; @@ -38,13 +44,19 @@ class Qaris extends Component { this.props.load({ qari, surah }); } } + handleRelated = () => { + this.setState({ + toggleRelated: !this.state.toggleRelated + }); + } render() { - const { surahs, qari, files, currentSurah, isPlaying, shouldRandom, currentQari, currentTime, progress } = this.props; + const { surahs, qari, files, currentSurah, isPlaying, shouldContinuous, currentQari, currentTime, progress, qaris, related } = this.props; + const { toggleRelated} = this.state; const handlePlayAll = () => { this.props.random(); - if (!shouldRandom) { + if (!shouldContinuous) { const randomSurah = Math.floor(Math.random() * (113 + 1)); const surahId = (currentSurah && currentSurah.id) ? currentSurah.id + 1 : randomSurah; this.handleSurahSelection(Object.values(surahs).filter(() => files[1])[surahId]); @@ -73,11 +85,20 @@ class Qaris extends Component {
    + {related.length > 0 && ( + )} +
    @@ -159,12 +180,14 @@ class Qaris extends Component { const connectedQaris = connect( (state, ownProps) => ({ + related: state.related.qaris, surahs: state.surahs.entities, + qaris: state.qaris.entities, qari: state.qaris.entities[ownProps.params.id], files: state.files.entities[ownProps.params.id], isPlaying: state.audioplayer.isPlaying, currentTime: state.audioplayer.currentTime, - shouldRandom: state.audioplayer.shouldRandom, + shouldContinuous: state.audioplayer.shouldContinuous, progress: state.audioplayer.progress, currentSurah: (state.audioplayer && state.audioplayer.surah) ? state.audioplayer.surah : {}, currentQari: state.audioplayer.qari @@ -176,4 +199,9 @@ export default asyncConnect([{ promise({ params, store: { dispatch } }) { return dispatch(loadFiles(params.id)); } +}, +{ + promise({ params, store: { dispatch } }) { + return dispatch(loadRelated(params.id)); + } }])(connectedQaris); diff --git a/src/containers/Qari/style.scss b/src/containers/Qari/style.scss index 80c63dc..b807624 100644 --- a/src/containers/Qari/style.scss +++ b/src/containers/Qari/style.scss @@ -152,7 +152,6 @@ border-color: white; background: #FFF; color: $brand-primary; - height: 60px; } } @@ -178,3 +177,9 @@ .link { color: $black; } + +.relatedToggle { + background: black; + padding: 5px; + border-radius: 13px; +} \ No newline at end of file diff --git a/src/reducers/index.js b/src/reducers/index.js index 3d928f8..9b471a6 100644 --- a/src/reducers/index.js +++ b/src/reducers/index.js @@ -7,6 +7,7 @@ import qaris from 'reducers/qaris'; import sections from 'reducers/sections'; import surahs from 'reducers/surahs'; import files from 'reducers/files'; +import related from 'reducers/related'; import download from 'reducers/download'; export default combineReducers({ @@ -17,5 +18,6 @@ export default combineReducers({ qaris, sections, surahs, - download + download, + related }); diff --git a/src/reducers/related.js b/src/reducers/related.js new file mode 100644 index 0000000..4026ae0 --- /dev/null +++ b/src/reducers/related.js @@ -0,0 +1,31 @@ +import { + LOAD, + LOAD_SUCCESS +} from 'actions/related'; + +const initialState = { + errored: false, + loaded: false, + entities: {} +}; + +export default function reducer(state = initialState, action = {}) { + switch (action.type) { + case LOAD: + return { + ...state, + loaded: false, + loading: true + }; + case LOAD_SUCCESS: + return { + ...state, + loaded: true, + errored: false, + qaris: action.result.result + }; + default: + return state; + } +} + diff --git a/src/utils/schemas.js b/src/utils/schemas.js index 95d7767..c6e74ba 100644 --- a/src/utils/schemas.js +++ b/src/utils/schemas.js @@ -3,13 +3,15 @@ import { Schema } from 'normalizr'; const surahsSchema = new Schema('surahs'); const qarisSchema = new Schema('qaris'); const sectionsSchema = new Schema('sections'); +const relatedSchema = new Schema('related'); const filesSchema = new Schema('files', { idAttribute: 'surahId' }); const schemas = { surahsSchema, qarisSchema, sectionsSchema, - filesSchema + filesSchema, + relatedSchema }; export default schemas;