Commit 5808d534 authored by carlosribas's avatar carlosribas
Browse files

React code to show the gene page

parent 4e91341e
{
"presets": [
"@babel/preset-env",
"@babel/preset-react"
]
}
\ No newline at end of file
node_modules
package-lock.json
\ No newline at end of file
{
"name": "frontend",
"version": "1.0.0",
"description": "Front-end code for the RNAcentral website",
"main": "index.js",
"scripts": {
"clean": "rm -rf static/frontend/*",
"dev": "webpack --mode development --watch",
"build": "webpack --mode production",
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": ["RNA", "bioinformatics"],
"contributors": [
{
"name": "Anton I. Petrov",
"email": "apetrov@ebi.ac.uk"
},
{
"name": "Blake Sweeney",
"email": "bsweeney@ebi.ac.uk"
},
{
"name": "Carlos E. Ribas",
"email": "cribas@ebi.ac.uk"
}
],
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/RNAcentral/rnacentral-webcode/issues"
},
"homepage": "https://github.com/RNAcentral/rnacentral-webcode#readme",
"dependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-redux": "^7.2.4",
"redux": "^4.1.1",
"redux-devtools-extension": "^2.13.9",
"redux-thunk": "^2.3.0"
},
"devDependencies": {
"@babel/core": "^7.15.4",
"@babel/preset-env": "^7.15.4",
"@babel/preset-react": "^7.14.5",
"babel-loader": "^8.2.2",
"dotenv-webpack": "^7.0.3",
"webpack": "^5.51.2",
"webpack-cli": "^4.8.0"
}
}
import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import GenesContainer from './modules/gene/index.jsx';
import store from './store/configureStore';
class App extends Component {
render() {
let query = window.location.search.substring(1);
let value = query.split("=");
let locus_name = value[1];
return (
<Provider store={store}>
<GenesContainer
search={ locus_name }
/>
</Provider>
);
}
}
ReactDOM.render(<App />, document.querySelector('#app'));
\ No newline at end of file
import React from 'react';
import { connect } from 'react-redux';
class Results extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div key={`results-div`}>
<div className="col-12">
<p>Locus name: {this.props.locus_name}</p>
<p>Assembly: {this.props.assembly}</p>
<p>Chromosome: {this.props.chromosome}</p>
<p>Locus start: {this.props.locus_start}</p>
<p>Locus stop: {this.props.locus_stop}</p>
<p>Members:</p>
<ul>
{
this.props.members.map(member =>
<li key={member.urs_taxid}>{member.urs_taxid} - {member.membership_status}</li>
)
}
</ul>
</div>
</div>
)
}
}
function mapStateToProps(state) {
return {
locus_name: state.locus_name,
assembly: state.assembly,
chromosome:state.chromosome,
locus_start: state.locus_start,
locus_stop: state.locus_stop,
members: state.members
};
}
export default connect(
mapStateToProps,
)(Results);
export const RESULTS = 'RESULTS';
export const UPDATE_STATUS = 'UPDATE_STATUS';
\ No newline at end of file
import * as types from './gene.actionTypes';
import routes from '../../services/routes.jsx';
import store from '../../store/configureStore.js'
export function onSubmitGene(gene) {
let state = store.getState();
return function(dispatch) {
if (state.status === "notSubmitted") { dispatch({type: types.UPDATE_STATUS}) }
fetch(routes.fetchGene(gene), {
method: 'GET'
})
.then(function (response) {
if (response.ok) { return response.json() }
else { throw response }
})
.then(data => {
dispatch({ type: types.RESULTS, status: 'success', data: data })
})
.catch(error => dispatch({type: types.RESULTS, status: 'error'}));
}
}
let initialState = {
status: "notSubmitted",
locus_name: null,
assembly: null,
chromosome:null,
locus_start: null,
locus_stop: null,
members: [],
};
export default initialState;
import * as actions from "./gene.actionTypes";
import initialState from "./gene.initialState";
const geneReducer = function (state = initialState, action) {
switch (action.type) {
case actions.UPDATE_STATUS:
return Object.assign({}, state, {status: "running"});
case actions.RESULTS:
switch (action.status) {
case 'success':
return Object.assign({}, state, {
status: "success",
locus_name: action.data.locus_name,
assembly: action.data.assembly,
chromosome:action.data.chromosome,
locus_start: action.data.locus_start,
locus_stop: action.data.locus_stop,
members: [...action.data.members]
});
case 'error':
return Object.assign({}, state, {status: "error"});
default:
return state;
}
default:
return state;
}
};
export default geneReducer;
\ No newline at end of file
import React from 'react';
import {connect} from "react-redux";
import store from "../../store/configureStore";
import * as actionCreators from "./gene.actions";
import Results from "./components/Results/index.jsx";
class GeneSearch extends React.Component {
constructor(props) {
super(props);
}
searchGene(gene) {
store.dispatch(actionCreators.onSubmitGene(gene));
}
render() {
const gene = this.props.search ? this.props.search : null;
return (
<div>
<div className="col-12">
<h1>Genes</h1>
</div>
{
!gene ? <div className="col-12">
<p>You need to pass locus_name in the URL parameters</p>
</div> : this.props.status === "notSubmitted" ? this.searchGene(gene) : ""
}
{
gene && (this.props.status === "notSubmitted" || this.props.status === "running") && (
<div key={`running-div`}>
<div className="col-12">
<i className='fa fa-spinner fa-spin fa-2x'></i> Loading...
</div>
</div>
)
}
{
this.props.status === "success" && (
<Results />
)
}
{
this.props.status === "error" && (
<div key={`error-div`}>
<div className="col-12">
<div className="alert alert-danger">
<p className="mt-3">
There was an error. Let us know if the problem persists by raising an issue on <a href="https://github.com/RNAcentral/rnacentral-webcode/issues" target="_blank">GitHub</a>.
</p>
</div>
</div>
</div>
)
}
</div>
)
}
}
const mapStateToProps = (state) => ({
status: state.status,
locus_name: state.locus_name,
assembly: state.assembly,
chromosome:state.chromosome,
locus_start: state.locus_start,
locus_stop: state.locus_stop,
members: state.members
});
function mapDispatchToProps(dispatch) {
return {};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(GeneSearch);
let server = process.env.SERVER ? process.env.SERVER : 'http://localhost:8000';
module.exports = {
fetchGene: (gene) => `${server}/api/v1/genes/${gene}`,
};
import { createStore, applyMiddleware } from 'redux';
import thunk from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension';
import geneReducer from '../modules/gene/gene.reducer.js';
const store = createStore(
geneReducer,
composeWithDevTools(applyMiddleware(thunk))
);
export default store;
This diff is collapsed.
/*
object-assign
(c) Sindre Sorhus
@license MIT
*/
/** @license React v0.20.2
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
/** @license React v17.0.2
* react.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
<!--
Copyright [2009-2017] EMBL-European Bioinformatics Institute
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
{% extends "portal/base.html" %}
{% load staticfiles %}
{% block title %}Genes{% endblock %}
{% block content %}
<div>
<div id='app'></div>
<script src="{% static 'frontend/main.js' %}"></script>
</div>
{% endblock %}
const path = require('path');
const dotenv = require('dotenv-webpack');
const isProduction = process.argv[process.argv.indexOf('--mode') + 1] === 'production';
module.exports = function(env) {
// set variables, modifying the config for dev and prod
let environment;
if (isProduction) environment = 'production';
else environment = 'development';
return {
target: ['web', 'es5'],
mode: environment,
entry: path.join(__dirname, 'src', 'app.js'),
output: {
path: path.join(__dirname, 'static', 'frontend'),
filename: 'main.js'
},
resolve: {
modules: [path.join(__dirname, 'src'), path.join(__dirname, 'node_modules')]
},
plugins: [
new dotenv()
],
module: {
rules: [
{
test: /\.(js|jsx)$/,
exclude: /node_modules/,
use: {
loader: 'babel-loader',
}
}
]
},
};
};
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment