From b92e92e372ac0993eaf05be60409df777311d1d8 Mon Sep 17 00:00:00 2001 From: Mohamed El Mahallawy Date: Fri, 3 Mar 2017 14:28:44 -0800 Subject: [PATCH] Fixes #657 Recitations dropdown from API call (#664) --- src/components/ReciterDropdown/index.js | 223 ++++-------------------- src/redux/actions/options.js | 13 +- src/redux/constants/options.js | 4 + src/redux/modules/options.js | 27 ++- src/types/index.js | 1 + src/types/recitationType.js | 7 + 6 files changed, 79 insertions(+), 196 deletions(-) create mode 100644 src/types/recitationType.js diff --git a/src/components/ReciterDropdown/index.js b/src/components/ReciterDropdown/index.js index 3f11060ff..83ab5f0f8 100644 --- a/src/components/ReciterDropdown/index.js +++ b/src/components/ReciterDropdown/index.js @@ -1,217 +1,49 @@ import React, { Component, PropTypes } from 'react'; +import { connect } from 'react-redux'; import ButtonToolbar from 'react-bootstrap/lib/ButtonToolbar'; import DropdownButton from 'react-bootstrap/lib/DropdownButton'; import MenuItem from 'react-bootstrap/lib/MenuItem'; -const style = require('./style.scss'); +import Loader from 'components/Loader'; +import LocaleFormattedMessage from 'components/LocaleFormattedMessage'; -// To save API calls. -export const slugs = [ - { - reciter: { - slug: 'abdulbaset', - id: 1 - }, - name: { - english: 'AbdulBaset AbdulSamad (Mujawwad)', - arabic: 'عبد الباسط عبد الصمد (مجود)' - }, - style: { - slug: 'mujawwad', - id: 1 - }, - id: 1 - }, - { - reciter: { - slug: 'abdulbaset', - id: 1 - }, - name: { - english: 'AbdulBaset AbdulSamad (Murattal)', - arabic: 'عبد الباسط عبد الصمد (مرتل)' - }, - style: { - slug: 'murattal', - id: 2 - }, - id: 2 - }, - { - reciter: { - slug: 'sudais', - id: 2 - }, - name: { - english: 'Abdur-Rahman as-Sudais', - arabic: 'عبدالرحمن السديس' - }, - style: { - slug: null, - id: null - }, - id: 3 - }, - { - reciter: { - slug: 'shatri', - id: 3 - }, - name: { - english: 'Abu Bakr al-Shatri', - arabic: 'أبو بكر الشاطرى' - }, - style: { - slug: null, - id: null - }, - id: 4 - }, - { - reciter: { - slug: 'rifai', - id: 4 - }, - name: { - english: 'Hani ar-Rifai', - arabic: 'هاني الرفاعي' - }, - style: { - slug: null, - id: null - }, - id: 5 - }, - { - reciter: { - slug: 'alafasy', - id: 6 - }, - name: { - english: 'Mishari Rashid al-`Afasy', - arabic: 'مشاري راشد العفاسي' - }, - style: { - slug: null, - id: null - }, - id: 8 - }, - { - reciter: { - slug: 'minshawi', - id: 7 - }, - name: { - english: 'Mohamed Siddiq al-Minshawi (Mujawwad)', - arabic: 'محمد صديق المنشاوي (مجود)' - }, - style: { - slug: 'mujawwad', - id: 1 - }, - id: 9 - }, - { - reciter: { - slug: 'minshawi', - id: 7 - }, - name: { - english: 'Mohamed Siddiq al-Minshawi (Murattal)', - arabic: 'محمد صديق المنشاوي (مرتل)' - }, - style: { - slug: 'murattal', - id: 2 - }, - id: 10 - }, - { - reciter: { - slug: 'altablawi', - id: 9 - }, - name: { - english: 'Mohamed al-Tablawi', - arabic: 'محمد الطبلاوي' - }, - style: { - slug: null, - id: null - }, - id: 12 - }, - { - reciter: { - slug: 'alhusary', - id: 5 - }, - name: { - english: 'Mahmoud Khalil Al-Husary', - arabic: 'محمود خليل الحصري' - }, - style: { - slug: null, - id: null - }, - id: 7 - }, - { - reciter: { - slug: 'muallim', // i'm just making up values for slug, i dont think we need this at all - id: 5 - }, - name: { - english: 'Mahmoud Khalil Al-Husary (Muallim)', - arabic: 'محمود خليل الحصري' - }, - style: { - slug: 'muallim', - id: 3 - }, - id: 13 - }, - { - reciter: { - slug: 'shuraym', - id: 8 - }, - name: { - english: 'Sa`ud ash-Shuraym', - arabic: 'سعود الشريم' - }, - style: { - slug: null, - id: null - }, - id: 11 - } -]; +import { loadRecitations } from 'redux/actions/options'; +import { recitationType } from 'types'; + +const style = require('./style.scss'); -export default class ReciterDropdown extends Component { +class ReciterDropdown extends Component { static propTypes = { onOptionChange: PropTypes.func, audio: PropTypes.number, - className: PropTypes.string + className: PropTypes.string, + loadRecitations: PropTypes.func.isRequired, + recitations: PropTypes.arrayOf(recitationType) }; + componentDidMount() { + return this.props.loadRecitations(); + } + renderMenu() { - const { audio, onOptionChange } = this.props; + const { audio, onOptionChange, recitations } = this.props; - return slugs.map(slug => ( + return recitations.map(slug => ( onOptionChange({ audio: slug.id })} > - {slug.name.english} + {slug.reciterNameEng} {slug.style ? `(${slug.style})` : ''} )); } render() { - const { className, audio } = this.props; + const { className, audio, recitations } = this.props; + const title = recitations.length ? + recitations.find(slug => slug.id === audio).reciterNameEng : + ; return ( @@ -219,11 +51,16 @@ export default class ReciterDropdown extends Component { block id="reciter-dropdown" className={`${className} ${style.dropdown}`} - title={slugs.find(slug => slug.id === audio).name.english} + title={title} > - {this.renderMenu()} + {recitations.length ? this.renderMenu() : } ); } } + +export default connect(state => ({ + recitations: state.options.options.recitations, + loadingRecitations: state.options.loadingRecitations +}), { loadRecitations })(ReciterDropdown); diff --git a/src/redux/actions/options.js b/src/redux/actions/options.js index 443623cb1..098d6dc0c 100644 --- a/src/redux/actions/options.js +++ b/src/redux/actions/options.js @@ -1,5 +1,10 @@ import cookie from 'react-cookie'; -import { SET_OPTION } from 'redux/constants/options.js'; +import { + SET_OPTION, + LOAD_RECITERS, + LOAD_RECITERS_SUCCESS, + LOAD_RECITERS_FAIL +} from 'redux/constants/options.js'; export function isReadingMode(globalState) { return globalState.options.isReadingMode; @@ -7,6 +12,7 @@ export function isReadingMode(globalState) { export function setOption(payload) { const options = cookie.load('options') || {}; // protect against first timers. + Object.keys(payload).forEach((option) => { options[option] = payload[option]; }); cookie.save('options', JSON.stringify(options)); @@ -15,3 +21,8 @@ export function setOption(payload) { payload }; } + +export const loadRecitations = () => ({ + types: [LOAD_RECITERS, LOAD_RECITERS_SUCCESS, LOAD_RECITERS_FAIL], + promise: client => client.get('/api/v3/options/recitations') +}); diff --git a/src/redux/constants/options.js b/src/redux/constants/options.js index 339433c66..d7ac9605d 100644 --- a/src/redux/constants/options.js +++ b/src/redux/constants/options.js @@ -1,2 +1,6 @@ export const SET_OPTION = '@@quran/options/SET_OPTION'; export const TOGGLE_NIGHT_MODE = '@@quran/options/TOGGLE_NIGHT_MODE'; + +export const LOAD_RECITERS = '@@quran/verses/LOAD_RECITERS'; +export const LOAD_RECITERS_SUCCESS = '@@quran/verses/LOAD_RECITERS_SUCCESS'; +export const LOAD_RECITERS_FAIL = '@@quran/verses/LOAD_RECITERS_FAIL'; diff --git a/src/redux/modules/options.js b/src/redux/modules/options.js index e275ae80d..d08ae6b3d 100644 --- a/src/redux/modules/options.js +++ b/src/redux/modules/options.js @@ -1,13 +1,20 @@ - -import { SET_OPTION } from 'redux/constants/options.js'; +import { + SET_OPTION, + LOAD_RECITERS, + LOAD_RECITERS_SUCCESS +} from 'redux/constants/options.js'; const initialState = { isReadingMode: false, isShowingSurahInfo: false, + loadingRecitations: false, audio: 8, quran: 1, content: [19], tooltip: 'translation', + options: { + recitations: [] + }, fontSize: { arabic: 3.5, translation: 2 @@ -23,6 +30,22 @@ export default function reducer(state = initialState, action = {}) { ...payload }; } + case LOAD_RECITERS: { + return { + ...state, + loadingRecitations: true + }; + } + case LOAD_RECITERS_SUCCESS: { + return { + ...state, + loadingRecitations: false, + options: { + ...state.options, + recitations: action.result.recitations + } + }; + } default: return state; } diff --git a/src/types/index.js b/src/types/index.js index 1b0d1e2fc..17ccb50f1 100644 --- a/src/types/index.js +++ b/src/types/index.js @@ -6,3 +6,4 @@ 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'; diff --git a/src/types/recitationType.js b/src/types/recitationType.js new file mode 100644 index 000000000..a83c18252 --- /dev/null +++ b/src/types/recitationType.js @@ -0,0 +1,7 @@ +import { PropTypes } from 'react'; + +export default PropTypes.shape({ + id: PropTypes.number, + style: PropTypes.string, + reciter_name_eng: PropTypes.string +});