-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #76 from NDLANO/NDLANO/Issue#474-Lydvelger-som-ege…
…n-pakke Ndlano/issue#474 lydvelger som egen pakke
- Loading branch information
Showing
15 changed files
with
809 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
# ndla-audio-search | ||
|
||
A simple library for selecting NDLA audio files. | ||
|
||
## Installation | ||
|
||
```sh | ||
$ npm install ndla-audio-search | ||
``` | ||
|
||
## Usage | ||
|
||
### Get audio with the audio selector | ||
|
||
To use the `AudioSearch` component, some functions for handling search and fetching audios are needed. In addition, some translations are needed. | ||
```js | ||
import AudioSearch from 'ndla-audio-search'; | ||
|
||
const searchAudios = queryObject => { | ||
// Return new Promise of audio objects | ||
}; | ||
|
||
const fetchAudio = id => { | ||
// Return new Promise of a single audio object | ||
}; | ||
|
||
const onError = err => { | ||
// Handle error | ||
}; | ||
|
||
const audioSelect = audio => { | ||
// Handle audio selection | ||
}; | ||
|
||
const translations = { | ||
searchPlaceholder: /* Translated string */, | ||
searchButtonTitle: /* Translated string */, | ||
useAudio: /* Translated string */, | ||
noResults: /* Translated string */, | ||
}; | ||
|
||
|
||
<AudioSearch | ||
translations={translations} | ||
fetchAudio={fetchAudio} | ||
searchAudios={searchAudios} | ||
onAudioSelect={audioSelect} | ||
onError={onError} | ||
queryObject={defaultQueryObject} | ||
/> | ||
``` | ||
|
||
A `queryObject` must look like this: | ||
```js | ||
{ | ||
query: /* Query string */, | ||
page: /* Page number */, | ||
pageSize: /* Page size (elements per page) */, | ||
locale: /* The search language; usually provided by the front-end */, | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
{ | ||
"name": "ndla-audio-search", | ||
"version": "0.1.1-0", | ||
"description": "A simple library for searching for audio files from NDLA", | ||
"license": "GPL-3.0", | ||
"main": "lib/index.js", | ||
"module": "es/index.js", | ||
"jsnext:main": "es/index.js", | ||
"scripts": { | ||
"build": "npm run build:commonjs && npm run build:es", | ||
"build:commonjs": "$(cd ..; npm bin)/cross-env BABEL_ENV=commonjs $(cd ..; npm bin)/babel src --out-dir lib --ignore __tests__", | ||
"build:es": "$(cd ..; npm bin)/cross-env BABEL_ENV=es $(cd ..; npm bin)/babel src --out-dir es --ignore __tests__", | ||
"clean": "$(cd ..; npm bin)/rimraf lib es", | ||
"test": "$(cd ..; npm bin)/jest", | ||
"prepublish": "npm run clean && npm run build" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "https://github.com/NDLANO/frontend-packages.git/ndla-ui/" | ||
}, | ||
"keywords": [ | ||
"ndla" | ||
], | ||
"author": "[email protected]", | ||
"files": [ | ||
], | ||
"devDependencies": { | ||
"ndla-article-scripts": "^0.0.3", | ||
"ndla-licenses": "^0.0.7", | ||
"ndla-ui": "^0.7.4", | ||
"ndla-util": "^0.1.3", | ||
"react-bem-helper": "^1.2.0" | ||
}, | ||
"peerDependencies": { | ||
"classnames": "^2.2.5", | ||
"ndla-article-scripts": "^0.0.3", | ||
"ndla-licenses": "^0.0.7", | ||
"ndla-ui": "^0.7.4", | ||
"ndla-util": "^0.1.3", | ||
"react": "^15.0.0", | ||
"react-bem-helper": "^1.2.0", | ||
"react-dom": "^15.0.0" | ||
}, | ||
"dependencies": { | ||
"defined": "1.0.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
/** | ||
* Copyright (c) 2017-present, NDLA. | ||
* | ||
* This source code is licensed under the GPLv3 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
*/ | ||
|
||
/* eslint jsx-a11y/media-has-caption: 0 */ | ||
|
||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import BEMHelper from 'react-bem-helper'; | ||
|
||
const classes = new BEMHelper({ | ||
name: 'audio-bar', | ||
prefix: 'c-', | ||
}); | ||
|
||
class AudioBar extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
audioSource: undefined, | ||
audioType: undefined, | ||
}; | ||
|
||
this.loadAudio = this.loadAudio.bind(this); | ||
} | ||
|
||
loadAudio() { | ||
this.props | ||
.fetchAudio(this.props.audio.id) | ||
.then(result => { | ||
this.setState({ | ||
audioSource: result.audioFile.url, | ||
audioType: result.audioFile.mimeType, | ||
}); | ||
}) | ||
.catch(err => { | ||
this.props.onError(err); | ||
}); | ||
} | ||
|
||
render() { | ||
const { audioSource, audioType } = this.state; | ||
return ( | ||
<div {...classes()}> | ||
<audio controls autoPlay onPlay={!audioSource && this.loadAudio}> | ||
{audioSource | ||
? <source src={audioSource} type={audioType} /> | ||
: undefined} | ||
</audio> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
AudioBar.propTypes = { | ||
audio: PropTypes.shape({ | ||
id: PropTypes.number.isRequired, | ||
}), | ||
fetchAudio: PropTypes.func.isRequired, | ||
onError: PropTypes.func.isRequired, | ||
}; | ||
|
||
export default AudioBar; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,126 @@ | ||
/** | ||
* Copyright (c) 2017-present, NDLA. | ||
* | ||
* This source code is licensed under the GPLv3 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
*/ | ||
|
||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Pager } from 'ndla-ui'; | ||
import BEMHelper from 'react-bem-helper'; | ||
|
||
import AudioSearchForm from './AudioSearchForm'; | ||
import AudioSearchList from './AudioSearchList'; | ||
|
||
const classes = new BEMHelper({ | ||
name: 'audio-search', | ||
prefix: 'c-', | ||
}); | ||
|
||
class AudioSearch extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
queryObject: props.queryObject, | ||
audios: [], | ||
lastPage: 0, | ||
totalCount: 0, | ||
searching: false, | ||
}; | ||
|
||
this.submitAudioSearchQuery = this.submitAudioSearchQuery.bind(this); | ||
this.searchAudios = this.searchAudios.bind(this); | ||
} | ||
|
||
componentDidMount() { | ||
this.searchAudios(this.state.queryObject); | ||
} | ||
|
||
submitAudioSearchQuery(queryObject) { | ||
this.searchAudios({ | ||
query: queryObject.query, | ||
page: 1, | ||
pageSize: queryObject.pageSize, | ||
locale: queryObject.locale, | ||
}); | ||
} | ||
|
||
searchAudios(queryObject) { | ||
this.setState({ searching: true }); | ||
this.props | ||
.searchAudios(queryObject) | ||
.then(result => { | ||
this.setState({ | ||
queryObject: { | ||
query: queryObject.query, | ||
page: queryObject.page, | ||
pageSize: result.pageSize, | ||
locale: queryObject.locale, | ||
}, | ||
audios: result.results, | ||
totalCount: result.totalCount, | ||
lastPage: Math.ceil(result.totalCount / result.pageSize), | ||
searching: false, | ||
}); | ||
}) | ||
.catch(err => { | ||
this.props.onError(err); | ||
this.setState({ searching: false }); | ||
}); | ||
} | ||
|
||
render() { | ||
const { fetchAudio, onError, translations } = this.props; | ||
const { queryObject, audios, lastPage, searching } = this.state; | ||
const { page, locale } = queryObject; | ||
|
||
return ( | ||
<div {...classes()}> | ||
<AudioSearchForm | ||
onSearchQuerySubmit={this.submitAudioSearchQuery} | ||
queryObject={queryObject} | ||
searching={searching} | ||
translations={translations} | ||
/> | ||
<AudioSearchList | ||
audios={audios} | ||
searching={searching} | ||
locale={locale} | ||
translations={translations} | ||
onError={onError} | ||
fetchAudio={fetchAudio} | ||
/> | ||
<Pager | ||
page={page ? parseInt(page, 10) : 1} | ||
pathname="" | ||
lastPage={lastPage} | ||
query={queryObject} | ||
onClick={this.searchAudios} | ||
pageItemComponentClass="button" | ||
/> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
AudioSearch.propTypes = { | ||
queryObject: PropTypes.shape({ | ||
query: PropTypes.string, | ||
page: PropTypes.number.isRequired, | ||
pageSize: PropTypes.number.isRequired, | ||
locale: PropTypes.string.isRequired, | ||
}), | ||
fetchAudio: PropTypes.func.isRequired, | ||
searchAudios: PropTypes.func.isRequired, | ||
onError: PropTypes.func.isRequired, | ||
translations: PropTypes.shape({ | ||
searchPlaceholder: PropTypes.string.isRequired, | ||
searchButtonTitle: PropTypes.string.isRequired, | ||
useAudio: PropTypes.string.isRequired, | ||
noResults: PropTypes.string.isRequired, | ||
}), | ||
}; | ||
|
||
export default AudioSearch; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
/** | ||
* Copyright (c) 2017-present, NDLA. | ||
* | ||
* This source code is licensed under the GPLv3 license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
* | ||
*/ | ||
|
||
import React, { Component } from 'react'; | ||
import PropTypes from 'prop-types'; | ||
import { Button } from 'ndla-ui'; | ||
import BEMHelper from 'react-bem-helper'; | ||
|
||
const classes = new BEMHelper({ | ||
name: 'audio-search', | ||
prefix: 'c-', | ||
}); | ||
|
||
class AudioSearchForm extends Component { | ||
constructor(props) { | ||
super(props); | ||
this.state = { | ||
queryObject: props.queryObject, | ||
}; | ||
this.onKeyPress = this.onKeyPress.bind(this); | ||
this.handleQueryChange = this.handleQueryChange.bind(this); | ||
this.handleSubmit = this.handleSubmit.bind(this); | ||
} | ||
|
||
onKeyPress(evt) { | ||
if (evt.key === 'Enter') { | ||
this.handleSubmit(evt); | ||
} | ||
} | ||
|
||
handleQueryChange(evt) { | ||
this.setState({ | ||
queryObject: { | ||
query: evt.target.value, | ||
page: this.state.queryObject.page, | ||
pageSize: this.state.queryObject.pageSize, | ||
locale: this.state.queryObject.locale, | ||
}, | ||
}); | ||
} | ||
|
||
handleSubmit(evt) { | ||
evt.preventDefault(); | ||
this.props.onSearchQuerySubmit(this.state.queryObject); | ||
} | ||
|
||
render() { | ||
const { searching, translations } = this.props; | ||
|
||
return ( | ||
<div {...classes('form')}> | ||
<input | ||
{...classes('form-query')} | ||
type="text" | ||
onChange={this.handleQueryChange} | ||
onKeyPress={this.onKeyPress} | ||
value={this.state.queryObject.query} | ||
placeholder={translations.searchPlaceholder} | ||
/> | ||
<Button | ||
{...classes('form-button')} | ||
onClick={this.handleSubmit} | ||
loading={searching}> | ||
{translations.searchButtonTitle} | ||
</Button> | ||
</div> | ||
); | ||
} | ||
} | ||
|
||
AudioSearchForm.propTypes = { | ||
queryObject: PropTypes.shape({ | ||
query: PropTypes.string, | ||
page: PropTypes.number.isRequired, | ||
pageSize: PropTypes.number.isRequired, | ||
locale: PropTypes.string.isRequired, | ||
}), | ||
translations: PropTypes.shape({ | ||
searchPlaceholder: PropTypes.string.isRequired, | ||
searchButtonTitle: PropTypes.string.isRequired, | ||
}), | ||
searching: PropTypes.bool.isRequired, | ||
onSearchQuerySubmit: PropTypes.func.isRequired, | ||
}; | ||
|
||
export default AudioSearchForm; |
Oops, something went wrong.