Commit a90a0588 authored by Viacheslav Pavlov's avatar Viacheslav Pavlov
Browse files

User actions: My List

parent fa4ce526
import {MY_LIST_ACCESSION_ADD, MY_LIST_ACCESSION_INIT, MY_LIST_ACCESSION_REMOVE} from 'constants/user';
const initAccessions = (accessions: string[]) => ({
type: MY_LIST_ACCESSION_INIT,
payload: accessions,
});
const addAccession = (accUUID: string) => ({
type: MY_LIST_ACCESSION_ADD,
payload: accUUID,
});
const removeAccession = (accUUID: string) => ({
type: MY_LIST_ACCESSION_REMOVE,
payload: accUUID,
});
export const addAccessionToMyList = (accUUID: string) => (dispatch, getState) => {
const myList = getState().user.myList;
if (!myList.accessions.includes(accUUID)) {
dispatch(addAccession(accUUID));
window.localStorage.setItem('myList', JSON.stringify(getState().user.myList));
} else {
console.log(`Can't add accession ${accUUID}. Already in myList`);
}
};
export const removeAccessionFromMyList = (accUUID: string) => (dispatch, getState) => {
const myList = getState().user.myList;
if (myList.accessions.includes(accUUID)) {
dispatch(removeAccession(accUUID));
window.localStorage.setItem('myList', JSON.stringify(getState().user.myList));
} else {
console.log(`Can't remove accession ${accUUID}. Not in myList`);
}
};
export const initMyList = (myList: any) => (dispatch) => {
if (myList.accessions) {
return dispatch(initAccessions(myList.accessions));
}
return dispatch(initAccessions([]));
};
export const MY_LIST_ACCESSION_INIT = 'MY_LIST_ACCESSION_INIT';
export const MY_LIST_ACCESSION_ADD = 'MY_LIST_ACCESSION_ADD';
export const MY_LIST_ACCESSION_REMOVE = 'MY_LIST_ACCESSION_REMOVE';
......@@ -11,6 +11,7 @@ import filterCode from './filterCode';
import subsets from './subsets';
import accessions from './accessions';
import applicationConfig from './applicationConfig';
import user from './user';
const rootReducer = combineReducers({
login,
......@@ -25,6 +26,7 @@ const rootReducer = combineReducers({
subsets,
accessions,
applicationConfig,
user,
});
export default rootReducer;
import {MY_LIST_ACCESSION_ADD, MY_LIST_ACCESSION_INIT, MY_LIST_ACCESSION_REMOVE} from 'constants/user';
import update from 'immutability-helper';
const INITIAL_STATE: {
myList: any;
} = {
myList: {
count: 0,
accessions: [],
},
};
export default function user(state = INITIAL_STATE, action: { type?: string, payload?: any } = {type: '', payload: {}}) {
switch (action.type) {
case MY_LIST_ACCESSION_INIT: {
return update(state, {
myList: {
count: {$set: action.payload.length},
accessions: {$push: action.payload},
},
});
}
case MY_LIST_ACCESSION_ADD: {
return update(state, {
myList: {
count: {$apply: (oldCount) => oldCount + 1},
accessions: {$push: [action.payload]},
},
});
}
case MY_LIST_ACCESSION_REMOVE: {
const index = state.myList.accessions.indexOf(action.payload);
return update(state, {
myList: {
count: {$apply: (oldCount) => oldCount - 1},
accessions: {$splice: [[index, 1]]},
},
});
}
default:
return state;
}
}
......@@ -3,6 +3,7 @@ import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {updateHistory} from 'actions/history';
import {initMyList} from 'actions/user';
import { withRouter } from 'react-router-dom';
......@@ -20,6 +21,7 @@ interface IAppProps extends React.ClassAttributes<any> {
route: any;
location: any;
updateHistory: (path: string) => void;
initMyList: (myList: any) => void;
}
class App extends React.Component<IAppProps, any> {
......@@ -27,7 +29,13 @@ class App extends React.Component<IAppProps, any> {
public constructor(props: any) {
super(props);
}
public componentWillMount() {
const { initMyList } = this.props;
const myList = JSON.parse(window.localStorage.getItem('myList'));
if (myList) {
initMyList(myList);
}
}
public componentWillReceiveProps(nextProps) {
const {updateHistory} = this.props;
if (this.props.location !== null && nextProps.location !== null) {
......@@ -54,6 +62,7 @@ const mapStateToProps = (state) => ({
const mapDispatchToProps = (dispatch) => bindActionCreators({
updateHistory,
initMyList,
}, dispatch);
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));
......@@ -5,6 +5,7 @@ import { translate } from 'react-i18next';
// Actions
import { loadAccession } from 'actions/accessions';
import {addAccessionToMyList, removeAccessionFromMyList} from 'actions/user';
// Models
import Accession from 'model/Accession';
......@@ -20,6 +21,7 @@ import DOI from 'ui/common/DOI';
import { ExternalLink } from 'ui/common/Links';
import SciName from 'ui/genesys/SciName';
import { ScrollToTopOnMount } from 'ui/common/page/scrollers';
import ReduxCheckbox from 'ui/common/checkbox';
interface IBrowsePageProps extends React.ClassAttributes<any> {
t: any;
......@@ -28,6 +30,9 @@ interface IBrowsePageProps extends React.ClassAttributes<any> {
accession: Accession;
error: any;
loadAccession: any;
accessions: any;
addAccessionToMyList: any;
removeAccessionFromMyList: any;
}
class BrowsePage extends React.Component<IBrowsePageProps, any> {
......@@ -53,8 +58,18 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
}
}
private onCheckboxChange = (event, checked) => {
const {accession, addAccessionToMyList, removeAccessionFromMyList} = this.props;
if (checked) {
addAccessionToMyList(accession.uuid);
} else {
removeAccessionFromMyList(accession.uuid);
}
}
public render() {
const { t, error, accession, uuid, doi } = this.props;
const { t, error, accession, uuid, doi, accessions } = this.props;
const isChecked = accession && accessions && accessions.includes(accession.uuid);
const theDoi = `10.${doi}`;
const stillLoading: boolean = ! error && (! accession
|| (doi && accession && accession.doi !== theDoi)
......@@ -70,7 +85,25 @@ class BrowsePage extends React.Component<IBrowsePageProps, any> {
{ accession &&
<PageContents>
<MainSection title={ `Accession: ${accession.accessionNumber}` }>
<MainSection title={
<div>
Accession: { accession.accessionNumber }
<div className="float-right">
<ReduxCheckbox
label={
<b>
{ isChecked ? `Remove ${accession.accessionNumber} from my list` : `Add ${accession.accessionNumber} to my list` }
</b>
}
input={ {
value: isChecked,
onChange: this.onCheckboxChange,
} }
/>
</div>
</div>
}
>
<Properties>
{ accession.doi && <PropertiesItem title="DOI"><DOI noPrefix value={ accession.doi } /></PropertiesItem> }
<PropertiesItem title="Accession number">{ accession.accessionNumber }</PropertiesItem>
......@@ -194,9 +227,12 @@ const mapStateToProps = (state, ownProps) => ({
error: state.accessions.accessionError,
uuid: ownProps.match.params.uuid,
doi: ownProps.match.params.doi,
accessions: state.user.myList.accessions,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
addAccessionToMyList,
removeAccessionFromMyList,
loadAccession,
}, dispatch);
......
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