Skip to content

Commit 22de1d0

Browse files
committed
Initial commit.
1 parent 51fa10b commit 22de1d0

File tree

10 files changed

+325
-1
lines changed

10 files changed

+325
-1
lines changed

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/coverage
2+
/demo/dist
3+
/es
4+
/lib
5+
/node_modules
6+
/umd
7+
npm-debug.log*

.travis.yml

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
sudo: false
2+
3+
language: node_js
4+
node_js:
5+
- 4
6+
7+
cache:
8+
directories:
9+
- node_modules
10+
11+
before_install:
12+
- npm install codecov.io coveralls
13+
14+
after_success:
15+
- cat ./coverage/lcov.info | ./node_modules/codecov.io/bin/codecov.io.js
16+
- cat ./coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js
17+
18+
branches:
19+
only:
20+
- master

CONTRIBUTING.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## Prerequisites
2+
3+
[Node.js](http://nodejs.org/) >= v4 must be installed.
4+
5+
## Installation
6+
7+
- Running `npm install` in the components's root directory will install everything you need for development.
8+
9+
## Demo Development Server
10+
11+
- `npm start` will run a development server with the component's demo app at [http://localhost:3000](http://localhost:3000) with hot module reloading.
12+
13+
## Running Tests
14+
15+
- `npm test` will run the tests once.
16+
17+
- `npm run test:coverage` will run the tests and produce a coverage report in `coverage/`.
18+
19+
- `npm run test:watch` will run the tests on every change.
20+
21+
## Building
22+
23+
- `npm run build` will build the component for publishing to npm and also bundle the demo app.
24+
25+
- `npm run clean` will delete built resources.

README.md

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,18 @@
11
# react-sequence-viewer
2-
A React implementation of the BioJS sequence-viewer component
2+
3+
[![Travis][build-badge]][build]
4+
[![npm package][npm-badge]][npm]
5+
[![Coveralls][coveralls-badge]][coveralls]
6+
7+
8+
A [React](https://facebook.github.io/react/) wrapper around the [BioJS](https://biojs.net/) [sequence-viewer](https://github.com/calipho-sib/sequence-viewer)
9+
component.
10+
11+
[build-badge]: https://img.shields.io/travis/user/repo/master.png?style=flat-square
12+
[build]: https://travis-ci.org/user/repo
13+
14+
[npm-badge]: https://img.shields.io/npm/v/npm-package.png?style=flat-square
15+
[npm]: https://www.npmjs.org/package/npm-package
16+
17+
[coveralls-badge]: https://img.shields.io/coveralls/user/repo/master.png?style=flat-square
18+
[coveralls]: https://coveralls.io/github/user/repo

demo/src/index.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import React from 'react'
2+
import {render} from 'react-dom'
3+
4+
import Component from '../../src'
5+
6+
//const seq = 'MALWMRLLPLLALLALWGPGPGAGSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN';
7+
const seq = 'MALWMRLLPLLALLALWGPDPAAAFVNQHLCGSHLVEALYLVCGERGFFYTPKTRREAEDLQVGQVELGGGPGAGSLQPLALEGSLQKRGIVEQCCTSICSLYQLENYCN';
8+
9+
const onClick = (e) => {
10+
console.log("Region clicked");
11+
}
12+
13+
const mouseClick = (e) => {
14+
console.log("Mouse Region clicked");
15+
console.log(e.detail);
16+
}
17+
const subPart = (e) => {
18+
console.log("Subpart");
19+
console.log(e.detail);
20+
}
21+
//Coverage list
22+
const exampleSequenceCoverage = [
23+
{start: 0, end: 25, color: "black", underscore: false, bgcolor: "#ffd891"},
24+
{start: 25, end: 47, color: "#ff0000", underscore: false, tooltip: "this is a tooltip"},
25+
{start: 47, end: 54, color: "#ff0000", underscore: true},
26+
{start: 54, end: 55, color: "#ff0000", underscore: false},
27+
{start: 55, end: 56, color: "black", underscore: false},
28+
{start: 56, end: 89, color: "#69CC33", underscore: false, onclick:onClick},
29+
{start: 89, end: 90, color: "black", underscore: false},
30+
{start: 90, end: 110, color: "#ff0000", underscore: false}
31+
];
32+
33+
//Define Legend and color codes
34+
const exampleLegend = [
35+
{name: "Mature Protein", color: "#ff0000", underscore: false},
36+
{name: "Proteotypic peptide", color: "#69CC33", underscore: false},
37+
{name: "Synthetic peptide",color: "#fff",underscore: true}
38+
];
39+
40+
let Demo = React.createClass({
41+
render() {
42+
return <div>
43+
<h1>react-sequence-viewer Demo</h1>
44+
<Component onSubpartSelected={subPart} onMouseSelection={mouseClick} legend={exampleLegend} coverage={exampleSequenceCoverage} id="blah" sequence={seq} showLineNumbers={true} toolbar={true} search={true} badge={false} title="" />
45+
</div>
46+
}
47+
})
48+
49+
render(<Demo/>, document.querySelector('#demo'))

nwb.config.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
var path = require('path');
2+
3+
module.exports = {
4+
type: 'react-component',
5+
npm: {
6+
esModules: true,
7+
umd: {
8+
global: 'ReactSequenceViewer',
9+
externals: {
10+
react: 'React'
11+
}
12+
}
13+
},
14+
// Override require('handlebars') in sequence-viewer.js
15+
// Without this, the sequence-viewer package will require
16+
// the main Handlebar.js bundle, which causes problems with webpack.
17+
//
18+
// To avoid these problems, you can also import the Handlebars.js
19+
// runtime only package, but that requires the use of external templates
20+
// and a webpack loader to precompile them. The sequence-viewer component
21+
// uses inline Handlebars.js templates currently.
22+
webpack: {
23+
aliases: {
24+
'handlebars': path.resolve("node_modules/handlebars/dist/handlebars.min.js"),
25+
'jQuery': path.resolve("node_modules/jquery/dist/jquery.min.js")
26+
}
27+
}
28+
};
29+

package.json

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
{
2+
"name": "react-sequence-viewer",
3+
"version": "1.0.0",
4+
"description": "A React wrapper around the BioJS sequence-viewer component",
5+
"main": "lib/index.js",
6+
"jsnext:main": "es/index.js",
7+
"module": "es/index.js",
8+
"files": [
9+
"css",
10+
"es",
11+
"lib",
12+
"umd"
13+
],
14+
"scripts": {
15+
"build": "nwb build-react-component",
16+
"clean": "nwb clean-module && npm clean-demo",
17+
"start": "nwb serve-react-demo",
18+
"test": "nwb test",
19+
"test:coverage": "nwb test --coverage",
20+
"test:watch": "nwb test --server"
21+
},
22+
"dependencies": {
23+
"bootstrap": "^3.3.7",
24+
"sequence-viewer": "^0.2.18"
25+
},
26+
"peerDependencies": {
27+
"react": "15.x"
28+
},
29+
"devDependencies": {
30+
"nwb": "0.12.x",
31+
"react": "^15.3.1",
32+
"react-dom": "^15.3.1"
33+
},
34+
"author": "Josh Goodman",
35+
"homepage": "",
36+
"license": "MIT",
37+
"repository": "https://github.com/FlyBase/react-sequence-viewer",
38+
"keywords": [
39+
"react-component",
40+
"BioJS",
41+
"sequence-viewer",
42+
"FASTA",
43+
"sequence"
44+
]
45+
}

src/index.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
import React, {PropTypes, Component} from 'react';
2+
3+
import Bootstrap from 'bootstrap/dist/css/bootstrap.min.css';
4+
// See nwb.config.js for some webpack magic that allows this to work.
5+
import Sequence from 'sequence-viewer';
6+
7+
export default class ReactSequenceViewer extends Component {
8+
constructor(props) {
9+
super(props);
10+
this.handleChange = this.handleChange.bind(this);
11+
12+
// Initialize the sequence-viewer object.
13+
this._seqObj = new Sequence(this.props.sequence);
14+
this._div = null;
15+
}
16+
17+
// Function to call the render function of sequence-viewer.
18+
// You can override existing props by passing an object with key value
19+
// pairs to override existing props.
20+
// e.g.
21+
// callRender({toolbar: false})
22+
// would override the existing toolbar setting.
23+
callRender(newProps = {}) {
24+
// Read in div from private variable.
25+
const div = this._div;
26+
//Render div if it is not null.
27+
if (div != null) {
28+
this._seqObj.render('#' + div.id,{...this.props,...newProps});
29+
this._seqObj.coverage(this.props.coverage);
30+
this._seqObj.addLegend(this.props.legend);
31+
}
32+
}
33+
34+
// When the component mounts, add a change listenver to the document
35+
// and call render. We attach the change listener here becuase
36+
// jQuery events don't see to bubble up through React properly.
37+
// Thus, when a user toggles the charsPerLine drop down menu.
38+
// the event is handled by jQuery, but not seen by React when the
39+
// listener is attached at the component div level.
40+
// Attaching it to the document seems to work.
41+
componentDidMount() {
42+
document.addEventListener('change', this.handleChange);
43+
this.callRender();
44+
this._seqObj.onSubpartSelected(this.props.onSubpartSelected);
45+
this._seqObj.onMouseSelection(this.props.onMouseSelection);
46+
}
47+
48+
// Remove the event listener when the component is unmounted.
49+
componentWillUnmount() {
50+
document.removeEventListener('change', this.handleChange);
51+
}
52+
53+
// Function called when the user changes the charsPerLine setting via the toolbar.
54+
handleChange(e) {
55+
const elem = e.target;
56+
// Check that the event was triggered by the right <select> button.
57+
if ((" " + elem.className + " " ).indexOf( " " + this.props.seqLenClass + " " ) > -1) {
58+
// Call render and override the charsPerLine setting with whatever the user specified.
59+
this.callRender({charsPerLine: elem.value});
60+
}
61+
}
62+
63+
// Render a div with the sequence-viwer widget in it.
64+
render() {
65+
const { id, sequence, className } = this.props;
66+
// Create the container div and store a reference to it once it is mounted
67+
// in the DOM. The componentDidMount function above will then get called
68+
// and render the widget.
69+
return (
70+
<div className={className}>
71+
<div id={this.props.id} ref={(div) => this._div = div}></div>
72+
</div>
73+
);
74+
}
75+
}
76+
77+
ReactSequenceViewer.propTypes = {
78+
coverage: PropTypes.arrayOf(
79+
PropTypes.shape({
80+
start: PropTypes.number.isRequired,
81+
end: PropTypes.number.isRequired,
82+
color : PropTypes.string,
83+
bgcolor : PropTypes.string,
84+
underscore : PropTypes.bool,
85+
tooltip : PropTypes.string,
86+
onclick : PropTypes.func,
87+
})),
88+
legend: PropTypes.arrayOf(
89+
PropTypes.shape({
90+
name: PropTypes.string,
91+
color: PropTypes.string,
92+
underscore: PropTypes.bool,
93+
})),
94+
seqLenClass: PropTypes.string,
95+
onMouseSelection: PropTypes.func,
96+
onSubpartSelected: PropTypes.func,
97+
};
98+
99+
ReactSequenceViewer.defaultProps = {
100+
coverage: [],
101+
legend: [],
102+
seqLenClass: "CPLChoice",
103+
onMouseSelection: (elem) => {},
104+
onSubpartSelected: (elem) => {},
105+
}

tests/.eslintrc

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
{
2+
"env": {
3+
"mocha": true
4+
}
5+
}

tests/index-test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import expect from 'expect'
2+
import React from 'react'
3+
import {render, unmountComponentAtNode} from 'react-dom'
4+
5+
import Component from 'src/'
6+
7+
describe('Component', () => {
8+
let node
9+
10+
beforeEach(() => {
11+
node = document.createElement('div')
12+
})
13+
14+
afterEach(() => {
15+
unmountComponentAtNode(node)
16+
})
17+
18+
it('displays a welcome message', () => {
19+
render(<Component/>, node, () => {
20+
expect(node.innerHTML).toContain('Welcome to React components')
21+
})
22+
})
23+
})

0 commit comments

Comments
 (0)