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

Commit

Permalink
Browse files Browse the repository at this point in the history
…ontend into fixxing-audio

* 'fixxing-audio' of https://github.com/quran/quran.com-frontend:
  Fixed tests
  Fixed repeat audio
  Fixed tests
  Sort translation languages list in alphabetical order
  Fixes /issues/79
  Remove unneeded
  New reload module and cache busting
  Tests passing
  Fixed audio loading

Conflicts:
	package.json
  • Loading branch information
reshadn committed Oct 16, 2015
2 parents 14717c4 + e8a46e4 commit 7182e2a
Show file tree
Hide file tree
Showing 16 changed files with 300 additions and 177 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ node_modules
/node_modules
test-results.xml
npm-debug.log
webpack-stats.json
10 changes: 8 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
"scripts": {
"test": "npm run lint && ./node_modules/karma/bin/karma start --browsers PhantomJS --single-run",
"test:watch": "./node_modules/karma/bin/karma start",
"dev": "NODE_ENV=developement node webpack-dev-server.js & PORT=3001 NODE_ENV=developement nodemon start.js -e js,jsx",
"lint": "eslint ./src/scripts/**/*.js",
"start": "NODE_PATH=\"./src\" node ./start",
"build": "node ./node_modules/webpack/bin/webpack.js --verbose --colors --display-error-details --config webpack.prod.config.js",
"watch-client": "node ./node_modules/webpack/bin/webpack.js --history-api-fallback --verbose --colors --display-error-details --config webpack.watch.config.js && node ./node_modules/webpack-dev-server/bin/webpack-dev-server.js --config webpack.watch.config.js --colors",
"watch": "node ./node_modules/concurrently/src/main.js --kill-others \"npm run watch-client\" \"npm run start\"",
"validate": "npm ls"
},
"engines": {
Expand Down Expand Up @@ -71,17 +70,20 @@
"url": "^0.11.0",
"url-loader": "~0.5.5",
"webpack": "^1.10.3",
"webpack-isomorphic-tools": "^0.9.1",
"winston": "^1.0.1"
},
"devDependencies": {
"autoprefixer-loader": "^3.1.0",
"babel-core": "5.8.24",
"babel-eslint": "^4.1.1",
"babel-loader": "5.3.2",
"babel-plugin-react-transform": "^1.1.1",
"babel-plugin-typecheck": "1.2.0",
"babel-runtime": "5.8.24",
"bundle-loader": "~0.5.0",
"chai": "^3.0.0",
"clean-webpack-plugin": "^0.1.3",
"del": "^2.0.2",
"eslint": "^1.4.1",
"eslint-loader": "^1.0.0",
Expand All @@ -108,10 +110,14 @@
"karma-webpack": "^1.6.0",
"mocha": "^2.2.5",
"nightwatch": "^0.8.1",
"nodemon": "^1.7.1",
"path": "^0.11.14",
"phantomjs-polyfill": "0.0.1",
"raw-loader": "^0.5.1",
"react-hot-loader": "^1.2.7",
"react-transform-catch-errors": "^1.0.0",
"react-transform-hmr": "^1.0.1",
"redbox-react": "^1.1.1",
"sinon": "^1.15.3",
"sinon-chai": "^2.8.0",
"style-loader": "~0.12.2",
Expand Down
9 changes: 6 additions & 3 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ server.get(/^\/(images|fonts)\/.*/, function(req, res) {
})
;
server.use((req, res, next) => {
if (process.env.NODE_ENV === 'development') {
webpack_isomorphic_tools.refresh()
}

let context = app.createContext();

Expand Down Expand Up @@ -80,15 +83,15 @@ server.use((req, res, next) => {

debug('Exposing context state');
const exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';
const webserver = process.env.NODE_ENV === "production" ? "" : "//localhost:8080";
const webserver = process.env.NODE_ENV === "production" ? "" : "//localhost:3001";

debug('Rendering Application component into html');
const html = React.renderToStaticMarkup(htmlComponent({
context: context.getComponentContext(),
state: exposed,
assets: webpack_isomorphic_tools.assets(),
markup: React.renderToString(createElementWithContext(context)),
fontFaces: Fonts.createFontFacesArray(context.getComponentContext().getStore('AyahsStore').getAyahs()),
hotModuleUrl: `${webserver}/`
fontFaces: Fonts.createFontFacesArray(context.getComponentContext().getStore('AyahsStore').getAyahs())
}));

debug('Sending markup');
Expand Down
8 changes: 6 additions & 2 deletions src/scripts/components/Html.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ class Html extends React.Component {
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1" />
<link rel="apple-touch-icon" href="/images/apple-touch-icon.png"/>
<link rel="apple-touch-icon-precomposed" href="/images/apple-touch-icon-precomposed.png" />
<link rel="stylesheet" href={this.props.hotModuleUrl + 'build/main.css'} />
{Object.keys(this.props.assets.styles).map((style, i) =>
<link href={this.props.assets.styles[style]} key={i} media="screen, projection"
rel="stylesheet" type="text/css"/>)}
{this.props.fontFaces.map(function(font) {
return (
<style type="text/css" dangerouslySetInnerHTML={{__html: font}} />
Expand All @@ -36,7 +38,9 @@ class Html extends React.Component {
<div id="app" dangerouslySetInnerHTML={{__html: this.props.markup}}></div>
</body>
<script dangerouslySetInnerHTML={{__html: this.props.state}}></script>
<script src={this.props.hotModuleUrl + 'build/main.js'}></script>
{Object.keys(this.props.assets.javascript).map((script, i) =>
<script src={this.props.assets.javascript[script]} key={i}/>
)}
</html>
);
}
Expand Down
15 changes: 14 additions & 1 deletion src/scripts/components/audioplayer/Audioplayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,11 @@ class Audioplayer extends React.Component {
}
return this.setupAudio();
}
}

if (prevProps.currentAyah.surah_id !== this.props.currentAyah.surah_id) {
return this.setupAudio();
}
}

if (!prevProps.currentAyah) {
// When navigating from the index page, there is no ayah set and therefore,
Expand All @@ -62,6 +65,16 @@ class Audioplayer extends React.Component {
}
}

// TODO: Revisit this later.
// shouldComponentUpdate(nextProps, nextState) {
// }

componentWillUnmount() {
this.pause();
this.props.currentAudio.src = null;
this.props.currentAudio = null;
}

changeAyah(ayah_num, shouldPlay) {
this.context.executeAction(AudioplayerActions.changeAyah, {
ayah_num: ayah_num,
Expand Down
32 changes: 22 additions & 10 deletions src/scripts/components/header/ContentDropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,16 +85,27 @@ class ContentDropdown extends React.Component {

renderContent(type) {
var condition;
return this.state.options.map((option) => {
if (type === 'en') {
condition = option.language === 'en' && (option.type === 'translation' || option.type === 'transliteration');
} else if (type === '!en') {
condition = option.language !== 'en' && option.type === 'translation';
}
if (condition) {
return this.returnList(option);
}
});
return this.state.options
// Sort all options to ensure translation languages are in alphabetical order
.sort((a, b) => {
return (a.slug < b.slug) ? -1 : (a.slug > b.slug) ? 1 : 0;
})
.map((option) => {
switch(type) {
case 'en':
condition = option.language === 'en' && option.type === 'translation';
break;
case '!en':
condition = option.language !== 'en' && option.type === 'translation';
break;
case 'transliteration':
condition = option.language === 'en' && option.type === 'transliteration';
break;
}
if (condition) {
return this.returnList(option);
}
});
}

render() {
Expand All @@ -103,6 +114,7 @@ class ContentDropdown extends React.Component {
<HeaderDropdown linkContent='Translations' linkIcon='ss-icon ss-globe' className={className}>
<li role="presentation" className="dropdown-header">English</li>
{this.renderContent('en')}
{this.renderContent('transliteration')}
<li role="presentation" className="dropdown-header languages">Other Languages</li>
{this.renderContent('!en')}

Expand Down
15 changes: 9 additions & 6 deletions src/scripts/stores/AudioplayerStore.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import BaseStore from 'fluxible/addons/BaseStore';
import debug from 'utils/Debug';

class AudioplayerStore extends BaseStore {
constructor(dispatcher) {
Expand Down Expand Up @@ -47,29 +48,31 @@ class AudioplayerStore extends BaseStore {

AudioplayerStore.handlers = {
audioplayerAyahChange(payload) {
console.log('Audioplayer reached');
debug('Audioplayer reached');

this.currentAyah = this.dispatcher.getStore('AyahsStore').getAyahs().find((ayah) => {
return ayah.ayah_num === payload.ayah_num;
});

this.currentAudio = this.currentAyah.scopedAudio;
this.shouldPlay = payload.shouldPlay;
if (this.currentAyah) {
this.currentAudio = this.currentAyah.scopedAudio;
this.shouldPlay = payload.shouldPlay;

this.emitChange();
this.emitChange();
}
},

ayahsReceived() {
this.dispatcher.waitFor('AyahsStore', () => {
if (!this.currentAyah) {
if (this.currentAyah !== this.dispatcher.getStore('AyahsStore').getAyahs()[0]) {
this.shouldPlay = false;
this.currentAyah = this.dispatcher.getStore('AyahsStore').getAyahs()[0];

if (this.currentAyah) {
this.currentAudio = this.currentAyah.scopedAudio;
}
this.emitChange();
}
this.emitChange();
});
}
};
Expand Down
21 changes: 20 additions & 1 deletion start.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,23 @@ if (process.env.NODE_ENV !== "production") {
}
}

module.exports = require('./server');
var Webpack_isomorphic_tools = require('webpack-isomorphic-tools')

// this must be equal to your Webpack configuration "context" parameter
var project_base_path = require('path').resolve(__dirname, './')

// this global variable will be used later in express middleware
global.webpack_isomorphic_tools = new Webpack_isomorphic_tools(require('./webpack-isomorphic-tools-configuration'))
// enter development mode if needed
// (for example, based on a Webpack DefinePlugin variable)
.development(process.env.NODE_ENV === 'development')
// initializes a server-side instance of webpack-isomorphic-tools
// (the first parameter is the base path for your project)
.server(project_base_path, function()
{
// webpack-isomorphic-tools is all set now.
// here goes all your web application code:
require('./server')
})

// module.exports = require('./server');
20 changes: 11 additions & 9 deletions tests/client/actions/AudioplayerActions.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import {createMockActionContext} from 'fluxible/utils';
import React from 'react';
import ReactTestUtils from 'react/lib/ReactTestUtils';
import Immutable from 'immutable';
import Keen from 'keen-js';

import AyahsStore from 'stores/AyahsStore';
import { RouteStore } from 'fluxible-router';
Expand Down Expand Up @@ -32,43 +33,44 @@ describe('AudioplayerActions', function() {
}

sinon.stub(actionContext, 'executeAction');

});

it('should dispatch to next ayah', function() {
AudioplayerActions.changeAyah(actionContext, {ayah: 2, shouldPlay: false}, function() {
AudioplayerActions.changeAyah(actionContext, {ayah_num: 2, shouldPlay: false}, function() {
return;
});
expect(actionContext.dispatchCalls.length).to.equal(1);
expect(actionContext.dispatchCalls[0].name).to.equal('audioplayerAyahChange');
expect(actionContext.dispatchCalls[0].payload).to.eql({ayah: 2, shouldPlay: false});
expect(actionContext.dispatchCalls[0].payload).to.eql({ayah_num: 2, shouldPlay: false});
});

it('should dispatch to next ayah and call for additional ayahs', function() {
AudioplayerActions.changeAyah(actionContext, {ayah: 7, shouldPlay: false}, function() {
AudioplayerActions.changeAyah(actionContext, {ayah_num: 7, shouldPlay: false}, function() {
return;
});

expect(actionContext.dispatchCalls.length).to.equal(1);
expect(actionContext.dispatchCalls[0].name).to.equal('audioplayerAyahChange');
expect(actionContext.dispatchCalls[0].payload).to.eql({ayah: 7, shouldPlay: false});
expect(actionContext.dispatchCalls[0].payload).to.eql({ayah_num: 7, shouldPlay: false});
expect(actionContext.executeAction).to.have.been.called;
expect(actionContext.executeAction.args[0][1].from).to.eql(11);
expect(actionContext.executeAction.args[0][1].to).to.eql(20);
});

it('should dispatch to next ayah and call for additional ayahs when already called', function() {
actionContext.getStore('AyahsStore').ayahs = getAyahs.slice(0, 20);
actionContext.getStore('AyahsStore').ayahs = getAyahs.slice(0, 10);

AudioplayerActions.changeAyah(actionContext, {ayah: 17, shouldPlay: false}, function() {
AudioplayerActions.changeAyah(actionContext, {ayah_num: 7, shouldPlay: false}, function() {
return;
});

expect(actionContext.dispatchCalls.length).to.equal(1);
expect(actionContext.dispatchCalls[0].name).to.equal('audioplayerAyahChange');
expect(actionContext.dispatchCalls[0].payload).to.eql({ayah: 17, shouldPlay: false});
expect(actionContext.dispatchCalls[0].payload).to.eql({ayah_num: 7, shouldPlay: false});
expect(actionContext.executeAction).to.have.been.called;
expect(actionContext.executeAction.args[0][1].from).to.eql(21);
expect(actionContext.executeAction.args[0][1].to).to.eql(30);
expect(actionContext.executeAction.args[0][1].from).to.eql(11);
expect(actionContext.executeAction.args[0][1].to).to.eql(20);
});

});
4 changes: 2 additions & 2 deletions tests/client/stores/UserStore.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ describe('UserStore', function() {
});

it('should have version number', function() {
expect(storeInstance.version).to.eql('1.0.0');
expect(storeInstance.version).to.eql('1.0.1');
});

it('should save last visit', function() {
Expand All @@ -39,6 +39,6 @@ describe('UserStore', function() {
expect(storeInstance.getContentOptions()).to.eql([18, 19]);
expect(storeInstance.getAudioOptions()).to.eql(1);
expect(storeInstance.getQuranOptions()).to.eql(1);
expect(storeInstance.version).to.eql('1.0.0');
expect(storeInstance.version).to.eql('1.0.1');
});
});
2 changes: 1 addition & 1 deletion tests/fixtures/getAyahs.js

Large diffs are not rendered by default.

30 changes: 30 additions & 0 deletions webpack-dev-server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
var webpack = require('webpack');
var WebpackDevServer = require('webpack-dev-server');
var config = require('./webpack.config');

new WebpackDevServer(webpack(config), {
publicPath: config.output.publicPath,
hot: true,
historyApiFallback: true,
quiet: false,
noInfo: false,
stats: {
assets: true,
colors: true,
version: true,
hash: true,
timings: true,
chunks: true,
chunkModules: false
},
verbose: true,
cache: true,
inline: true,
debug: true,
headers: {"Access-Control-Allow-Origin": "*"},
proxy: {
'*': { target: 'http://localhost:3001' }
}
}).listen(3002, function () {
console.log('Webpack Dev Server listening on port 3002');
});
Loading

0 comments on commit 7182e2a

Please sign in to comment.