Skip to content
This repository was archived by the owner on Jun 28, 2021. It is now read-only.

Fixes #657 Recitations dropdown from API call #664

Merged
merged 2 commits into from
Mar 3, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
223 changes: 30 additions & 193 deletions src/components/ReciterDropdown/index.js
Original file line number Diff line number Diff line change
@@ -1,229 +1,66 @@
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 => (
<MenuItem
key={slug.name.english}
key={slug.id}
active={slug.id === audio}
onClick={() => onOptionChange({ audio: slug.id })}
>
{slug.name.english}
{slug.reciterNameEng} {slug.style ? `(${slug.style})` : ''}
</MenuItem>
));
}

render() {
const { className, audio } = this.props;
const { className, audio, recitations } = this.props;
const title = recitations.length ?
recitations.find(slug => slug.id === audio).reciterNameEng :
<LocaleFormattedMessage id="setting.reciters.title" default="Reciters" />;

return (
<ButtonToolbar>
<DropdownButton
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() : <Loader />}
</DropdownButton>
</ButtonToolbar>
);
}
}

export default connect(state => ({
recitations: state.options.options.recitations,
loadingRecitations: state.options.loadingRecitations
}), { loadRecitations })(ReciterDropdown);
13 changes: 12 additions & 1 deletion src/redux/actions/options.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,18 @@
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;
}

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));

Expand All @@ -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')
});
4 changes: 4 additions & 0 deletions src/redux/constants/options.js
Original file line number Diff line number Diff line change
@@ -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';
27 changes: 25 additions & 2 deletions src/redux/modules/options.js
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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;
}
Expand Down
1 change: 1 addition & 0 deletions src/types/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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';
7 changes: 7 additions & 0 deletions src/types/recitationType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PropTypes } from 'react';

export default PropTypes.shape({
id: PropTypes.number,
style: PropTypes.string,
reciter_name_eng: PropTypes.string
});