Commit 96b98dec authored by Matija Obreza's avatar Matija Obreza
Browse files

Merge branch '171-admin-requests' into 'master'

Admin: Requests

Closes #171

See merge request genesys-pgr/genesys-ui!172
parents f5d0bf16 8dba63ac
...@@ -115,6 +115,12 @@ ...@@ -115,6 +115,12 @@
"email": "E-mail address", "email": "E-mail address",
"uuid": "UUID" "uuid": "UUID"
}, },
"requests": {
"email": "E-mail address",
"uuid": "UUID",
"state": "State",
"pid": "PID"
},
"dataset": { "dataset": {
"_text": "Keywords", "_text": "Keywords",
"accessionIdentifier": { "accessionIdentifier": {
...@@ -1583,6 +1589,10 @@ ...@@ -1583,6 +1589,10 @@
} }
}, },
"admin": { "admin": {
"f": {
"title": "Filter requests",
"pid": "PID"
},
"p": { "p": {
"browse": { "browse": {
"title": "{{totalElements, number}} requests for PGR material" "title": "{{totalElements, number}} requests for PGR material"
...@@ -1602,8 +1612,9 @@ ...@@ -1602,8 +1612,9 @@
} }
}, },
"common": { "common": {
"modelMame": "Request", "modelName": "Request",
"modelMame_plural": "Requests", "modelName_plural": "Requests",
"emailAddress": "E-mail address",
"preacceptSMTA": "Preaccept SMTA", "preacceptSMTA": "Preaccept SMTA",
"stateLabel": "State", "stateLabel": "State",
"state": { "state": {
...@@ -1621,6 +1632,10 @@ ...@@ -1621,6 +1632,10 @@
"0": "Other (please elaborate in Notes field)", "0": "Other (please elaborate in Notes field)",
"1": "Research for food and agriculture" "1": "Research for food and agriculture"
} }
},
"sort": {
"lastModifiedDateAsc": "Last modified date (old to new)",
"lastModifiedDateDesc": "Last modified date (new to old)"
} }
} }
,"subsets": { ,"subsets": {
......
...@@ -24,6 +24,17 @@ class MaterialRequest { ...@@ -24,6 +24,17 @@ class MaterialRequest {
direction: 'DESC', direction: 'DESC',
}; };
public static STATE: { [key: number]: string; } = {
0: 'requests.common.state.0',
1: 'requests.common.state.1',
2: 'requests.common.state.2',
};
public static SORT_OPTIONS = {
lastModifiedDate: { property: 'lastModifiedDate', label: 'requests.sort.lastModifiedDateAsc', direction: 'ASC' },
lastModifiedDateD: { property: 'lastModifiedDate', label: 'requests.sort.lastModifiedDateDesc', direction: 'DESC' },
email: { property: 'email', label: 'requests.common.emailAddress', direction: 'ASC' },
};
} }
export default MaterialRequest; export default MaterialRequest;
...@@ -3,11 +3,17 @@ import * as _ from 'lodash'; ...@@ -3,11 +3,17 @@ import * as _ from 'lodash';
// constants // constants
import {ADMIN_APPEND_MATERIAL_REQUESTS, ADMIN_RECEIVE_MATERIAL_REQUEST, ADMIN_RECEIVE_MATERIAL_REQUESTS} from 'requests/constants'; import {ADMIN_APPEND_MATERIAL_REQUESTS, ADMIN_RECEIVE_MATERIAL_REQUEST, ADMIN_RECEIVE_MATERIAL_REQUESTS} from 'requests/constants';
// actions
import navigateTo from 'actions/navigation';
// services
import RequestService from 'service/genesys/RequestService';
// models // models
import MaterialRequest from 'model/request/MaterialRequest'; import MaterialRequest from 'model/request/MaterialRequest';
import FilteredPage from 'model/FilteredPage'; import FilteredPage, { IPageRequest } from 'model/FilteredPage';
import RequestService from 'service/genesys/RequestService';
import Page from 'model/Page'; import Page from 'model/Page';
import MaterialRequestFilter from 'model/request/MaterialRequestFilter';
const receiveRequests = (paged: FilteredPage<MaterialRequest>, error = null) => ({ const receiveRequests = (paged: FilteredPage<MaterialRequest>, error = null) => ({
...@@ -94,3 +100,23 @@ export const sendValidationEmailAction = (uuid: string) => (dispatch) => { ...@@ -94,3 +100,23 @@ export const sendValidationEmailAction = (uuid: string) => (dispatch) => {
dispatch(receiveRequest(null, error)); dispatch(receiveRequest(null, error));
}); });
}; };
export const applyFilters = (filters: string | MaterialRequestFilter, page: IPageRequest = { page: 0 }) => (dispatch) => {
return RequestService.list(filters, page)
.then((paged) => {
if (paged.number === 0) {
dispatch(receiveRequests(paged));
} else {
dispatch(appendRequests(paged));
}
dispatch(updateRoute(paged));
}).catch((error) => {
console.log(`API error`, error);
dispatch(receiveRequests(null, error));
});
};
export const updateRoute = (paged: FilteredPage<MaterialRequest>) => (dispatch) => {
dispatch(navigateTo(paged.filterCode ? `/admin/requests/${paged.filterCode}` : '/admin/requests'));
};
...@@ -8,3 +8,5 @@ export const REQUEST_INFO_FORM = 'requests/form/REQUEST_INFO_FORM'; ...@@ -8,3 +8,5 @@ export const REQUEST_INFO_FORM = 'requests/form/REQUEST_INFO_FORM';
export const ADMIN_RECEIVE_MATERIAL_REQUESTS = 'requests/admin/RECEIVE_MATERIAL_REQUESTS'; export const ADMIN_RECEIVE_MATERIAL_REQUESTS = 'requests/admin/RECEIVE_MATERIAL_REQUESTS';
export const ADMIN_APPEND_MATERIAL_REQUESTS = 'requests/admin/APPEND_MATERIAL_REQUESTS'; export const ADMIN_APPEND_MATERIAL_REQUESTS = 'requests/admin/APPEND_MATERIAL_REQUESTS';
export const ADMIN_RECEIVE_MATERIAL_REQUEST = 'requests/admin/RECEIVE_MATERIAL_REQUEST'; export const ADMIN_RECEIVE_MATERIAL_REQUEST = 'requests/admin/RECEIVE_MATERIAL_REQUEST';
export const REQUEST_FILTER_FORM = 'Form/request/admin/REQUEST_FILTER_FORM';
...@@ -21,6 +21,17 @@ const publicRoutes = [ ...@@ -21,6 +21,17 @@ const publicRoutes = [
]; ];
const adminRoutes = [ const adminRoutes = [
{
path: '/requests/:filterCode(v.+)?',
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "requests" */'requests/ui/admin/BrowsePage'),
loading: Loading,
}),
exact: true,
extraProps: {
title: 'Requests',
},
},
{ {
path: '/requests', path: '/requests',
component: Loadable({ component: Loadable({
......
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
} }
}, },
"admin": { "admin": {
"f": {
"title": "Filter requests",
"pid": "PID"
},
"p": { "p": {
"browse": { "browse": {
"title": "{{totalElements, number}} requests for PGR material" "title": "{{totalElements, number}} requests for PGR material"
...@@ -43,8 +47,9 @@ ...@@ -43,8 +47,9 @@
} }
}, },
"common": { "common": {
"modelMame": "Request", "modelName": "Request",
"modelMame_plural": "Requests", "modelName_plural": "Requests",
"emailAddress": "E-mail address",
"preacceptSMTA": "Preaccept SMTA", "preacceptSMTA": "Preaccept SMTA",
"stateLabel": "State", "stateLabel": "State",
"state": { "state": {
...@@ -62,5 +67,9 @@ ...@@ -62,5 +67,9 @@
"0": "Other (please elaborate in Notes field)", "0": "Other (please elaborate in Notes field)",
"1": "Research for food and agriculture" "1": "Research for food and agriculture"
} }
},
"sort": {
"lastModifiedDateAsc": "Last modified date (old to new)",
"lastModifiedDateDesc": "Last modified date (new to old)"
} }
} }
\ No newline at end of file
...@@ -2,12 +2,14 @@ import * as React from 'react'; ...@@ -2,12 +2,14 @@ import * as React from 'react';
import { translate } from 'react-i18next'; import { translate } from 'react-i18next';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { bindActionCreators } from 'redux'; import { bindActionCreators } from 'redux';
import { parse } from 'query-string';
// Actions // Actions
import { loadMoreRequests } from 'requests/actions/admin'; import { applyFilters, updateRoute, loadMoreRequests } from 'requests/actions/admin';
// Models // Models
import MaterialRequest from 'model/request/MaterialRequest'; import MaterialRequest from 'model/request/MaterialRequest';
import FilteredPage from 'model/FilteredPage';
// UI // UI
import BrowsePageTemplate from 'ui/pages/_base/BrowsePage'; import BrowsePageTemplate from 'ui/pages/_base/BrowsePage';
...@@ -15,51 +17,77 @@ import { PageContents } from 'ui/layout/PageLayout'; ...@@ -15,51 +17,77 @@ import { PageContents } from 'ui/layout/PageLayout';
import Loading from 'ui/common/Loading'; import Loading from 'ui/common/Loading';
import PagedLoader from 'ui/common/PagedLoader'; import PagedLoader from 'ui/common/PagedLoader';
import RequestCard from 'requests/ui/admin/c/RequestCard'; import RequestCard from 'requests/ui/admin/c/RequestCard';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton'; import PrettyFilters from 'ui/common/filter/PrettyFilters';
import ContentLayout from 'ui/layout/ContentLayout';
import MaterialRequestFilter from 'requests/ui/admin/c/MaterialRequestFilter';
import Grid from '@material-ui/core/Grid';
import PaginationComponent from 'ui/common/pagination';
class BrowsePage extends BrowsePageTemplate<any> { class BrowsePage extends BrowsePageTemplate<any> {
protected static needs = [ protected static needs = [
({ }) => loadMoreRequests(), ({ search, params: { filterCode } }) => {
const qs = parse(search || '');
return applyFilters(filterCode || '', FilteredPage.fromQueryString(qs));
},
]; ];
public componentWillMount() { public componentWillMount() {
const { paged, loadMoreData } = this.props; const { paged, applyFilters, filterCode } = this.props;
if (!paged) { if (!paged) {
loadMoreData(); applyFilters(filterCode);
} }
} }
public render() { public render() {
const { paged, t, loadMoreData} = this.props; const { paged, loadMoreData} = this.props;
const renderRequest = (r: MaterialRequest, index: number) => { const renderRequest = (r: MaterialRequest, index: number) => {
return <RequestCard key={ r.uuid } index={ index } request={ r } />; return <RequestCard key={ r.uuid } index={ index } request={ r } />;
}; };
return ( return (
<div> <ContentLayout left={
<ContentHeaderWithButton title={ t('requests.admin.p.browse.title', {totalElements: paged ? paged.totalElements : '-' }) }/> <MaterialRequestFilter initialValues={ paged && paged.filter || {} } onSubmit={ this.myApplyFilters }/>
<PageContents className="pt-1rem container-spacing-horizontal"> } customHeaderHeight>
{ ! paged ? <Loading /> : <Grid container spacing={ 0 }>
<PagedLoader <Grid item xs={ 12 }>
paged={ paged } <PaginationComponent
loadMore={ loadMoreData } pageObj={ paged }
roughItemHeight={ 80 } onSortChange={ this.onSortChange }
itemRenderer={ renderRequest } /> displayName="requests.common.modelName"
} sortOptions={ MaterialRequest.SORT_OPTIONS }
</PageContents> />
</div> <PrettyFilters
prefix="requests"
filterObj={ paged && paged.filter || {} }
onSubmit={ this.myApplyFilters }
/>
<PageContents className="pt-1rem container-spacing-horizontal">
{ ! paged ? <Loading /> :
<PagedLoader
paged={ paged }
loadMore={ loadMoreData }
roughItemHeight={ 80 }
itemRenderer={ renderRequest } />
}
</PageContents>
</Grid>
</Grid>
</ContentLayout>
); );
} }
} }
const mapStateToProps = (state) => ({ const mapStateToProps = (state, ownProps) => ({
paged: state.requests.admin.paged || undefined, paged: state.requests.admin.paged || undefined,
filterCode: ownProps.match.params.filterCode,
}); });
const mapDispatchToProps = (dispatch) => bindActionCreators({ const mapDispatchToProps = (dispatch) => bindActionCreators({
applyFilters,
loadMoreData: loadMoreRequests, loadMoreData: loadMoreRequests,
updateRoute,
}, dispatch); }, dispatch);
......
import * as React from 'react';
import { reduxForm } from 'redux-form';
import { REQUEST_FILTER_FORM } from 'requests/constants';
import FiltersBlock from 'ui/common/filter/FiltersBlock';
import CollapsibleComponentSearch from 'ui/common/filter/CollapsibleComponentSearch';
import StringFilter from 'ui/common/filter/StringFilter';
import StringArrFilter from 'ui/common/filter/StringArrFilter';
import StatusFilter from 'ui/catalog/dashboard/c/StatusFilter'; // move
const MaterialRequestFilters = ({handleSubmit, initialValues, initialize, ...other}) => {
return (
<FiltersBlock title="requests.admin.f.title" handleSubmit={ handleSubmit } initialize={ initialize } { ...other }>
<CollapsibleComponentSearch title="common:f.textSearch">
<StringFilter name="email" searchType="contains" label="requests.common.emailAddress" placeholder="name@domain.com"/>
<StringArrFilter name="uuid" label="common:label.UUID" placeholder="ihope-youk-noww-hatyouredoing"/>
<StringArrFilter name="pid" label="requests.admin.f.pid" placeholder="ihope-youk-noww-hatyouredoing"/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title="common:label.status">
<StatusFilter isMaterialRequestFilter/>
</CollapsibleComponentSearch>
</FiltersBlock>
);
};
export default reduxForm({
enableReinitialize: true,
form: REQUEST_FILTER_FORM,
})(MaterialRequestFilters);
...@@ -114,6 +114,12 @@ ...@@ -114,6 +114,12 @@
"email": "E-mail address", "email": "E-mail address",
"uuid": "UUID" "uuid": "UUID"
}, },
"requests": {
"email": "E-mail address",
"uuid": "UUID",
"state": "State",
"pid": "PID"
},
"dataset": { "dataset": {
"_text": "Keywords", "_text": "Keywords",
"accessionIdentifier": { "accessionIdentifier": {
......
...@@ -4,13 +4,24 @@ import { translate } from 'react-i18next'; ...@@ -4,13 +4,24 @@ import { translate } from 'react-i18next';
import StringArrFilter from 'ui/common/filter/StringArrFilter'; import StringArrFilter from 'ui/common/filter/StringArrFilter';
import { PublishState } from 'model/common.model'; import { PublishState } from 'model/common.model';
class StatusFilter extends React.Component<any, any> { interface IStatusFilter {
isMaterialRequestFilter?: true;
}
class StatusFilter extends React.Component<IStatusFilter, any> {
private options: object = {}; private options: object = {};
public componentWillMount() { public componentWillMount() {
this.options[PublishState.DRAFT] = 'status.inProgress'; const isMaterialRequestFilter = this.props;
this.options[PublishState.REVIEWING] = 'status.inReview'; if (isMaterialRequestFilter) {
this.options[PublishState.PUBLISHED] = 'status.published'; this.options[0] = 'requests.common.state.0';
this.options[1] = 'requests.common.state.1';
this.options[2] = 'requests.common.state.2';
} else {
this.options[PublishState.DRAFT] = 'status.inProgress';
this.options[PublishState.REVIEWING] = 'status.inReview';
this.options[PublishState.PUBLISHED] = 'status.published';
}
} }
public render() { public render() {
...@@ -21,3 +32,4 @@ class StatusFilter extends React.Component<any, any> { ...@@ -21,3 +32,4 @@ class StatusFilter extends React.Component<any, any> {
} }
export default translate()(StatusFilter); export default translate()(StatusFilter);
...@@ -12,6 +12,7 @@ import * as _ from 'lodash'; ...@@ -12,6 +12,7 @@ import * as _ from 'lodash';
import { cleanFilters } from 'utilities'; import { cleanFilters } from 'utilities';
import Accession from 'model/accession/Accession'; import Accession from 'model/accession/Accession';
import {User} from 'model/user/User'; import {User} from 'model/user/User';
import MaterialRequest from 'model/request/MaterialRequest';
import PrettyDate from 'ui/common/time/PrettyDate'; import PrettyDate from 'ui/common/time/PrettyDate';
/** /**
...@@ -192,6 +193,7 @@ const mapStateToProps = (state, ownProps) => ({ ...@@ -192,6 +193,7 @@ const mapStateToProps = (state, ownProps) => ({
true: 'Yes', true: 'Yes',
false: 'No', false: 'No',
}, },
state: MaterialRequest.STATE,
}, },
labels: state.uuidDecoder.labels, labels: state.uuidDecoder.labels,
}); });
......
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