Commit d5c8707d authored by Viacheslav Pavlov's avatar Viacheslav Pavlov Committed by Matija Obreza

Added owner picker to subset basic info step

- Subset filters include Partner
- Fixed SSR for subset basic info edit page
parent 59290a2d
......@@ -1997,13 +1997,14 @@
}
},
"f": {
"partner": "Data provider",
"filterTitle": "Filter subsets",
"textSearch": "Text search",
"title": "Title",
"titlePlaceholder": "International",
"description": "Description",
"descriptionPlaceholder": "Subset description",
"institute": "Institute",
"institute": "FAO WIEWS Institute code",
"institutePlaceholder": "MEX002",
"crop": "Crop"
},
......@@ -2074,7 +2075,11 @@
"crops": "Crops",
"rights": "Rights",
"creationDate": "Creation date",
"source": "Source"
"source": "Source",
"partner": {
"label": "Select Data provider",
"placeholder": "Data provider"
}
},
"creators": {
"stepName": "Subset creators",
......@@ -2116,6 +2121,7 @@
}
}
}
,"user": {
"public": {
"c": {
......
......@@ -5,9 +5,9 @@ const sitemap = (req, res) => {
axios({
method: 'get',
url: `${config.apiUrl}${req.path}`,
}).then(response => {
}).then((response) => {
return res.set('Content-Type', 'text/xml').send(response.data);
}).catch(error => {
}).catch((error) => {
res.status(error.status).end(error.data);
});
};
......
import * as React from 'react';
import {withStyles} from '@material-ui/core/styles';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import {translate} from 'react-i18next';
import {loadPartnerInstitutes} from 'partners/actions/editor';
import {log} from 'utilities/debug';
import FaoInstitute from 'model/genesys/FaoInstitute';
import Partner from 'model/genesys/Partner';
import FormControl from 'ui/common/forms/FormControl';
import Markdown from 'ui/common/markdown';
import Input from '@material-ui/core/Input';
import Select from '@material-ui/core/Select';
import MenuItem from '@material-ui/core/MenuItem';
const styles = (theme) => ({
root: {
color: '#000',
},
select: {
width: '100%',
},
code: {
minWidth: '6em',
maxWidth: '6em',
marginRight: '0.5em',
overflow: 'hidden' as 'hidden',
},
fullName: {
whiteSpace: 'normal' as 'normal',
},
menuItem: {
height: 'auto' as 'auto',
},
});
interface ISelectInstituteProps extends React.ClassAttributes<any> {
classes: any;
input: any;
label: string;
editable?: boolean;
required?: boolean;
loading: boolean;
meta?: any;
owner: Partner;
loadPartnerInstitutes: any;
institutes: FaoInstitute[];
allowNull?: boolean; // add blank option (null) to selection
multiple?: boolean; // allow multiple
t: any;
}
class SelectInstitute extends React.Component<ISelectInstituteProps, any> {
public handleChange = ({target: {value}}) => {
const {institutes, editable, input, multiple} = this.props;
value = value === '' ? null : value;
log(`Institute selection editable=${editable} value=${value}`, value);
const inst = institutes.find((p) => p.code === value);
if (editable === undefined || editable) {
if (multiple) {
input.onChange(inst ? [inst.code] : null);
} else {
input.onChange(inst.code);
}
}
}
public componentWillReceiveProps(nextProps) {
const {owner: prevOwner} = this.props;
const {loadPartnerInstitutes, owner, loading, editable} = nextProps;
if (owner && (!prevOwner || prevOwner.uuid !== owner.uuid) && !loading && editable) {
loadPartnerInstitutes(owner.uuid);
}
}
public render() {
const {institutes, classes, input, label, owner, editable, required, meta, allowNull, multiple, t} = this.props;
const allowsEdit = editable === undefined || editable;
const val = input && input.value ?
(multiple ? input.value[0] : input.value) : null;
if (!allowsEdit) {
return (
<FormControl fullWidth label={ t(label) }>
<Input value={ val } className={ classes.input } disabled/>
</FormControl>
);
}
return (
<FormControl disabled={ !owner } fullWidth required={ required } meta={ meta } label={ t(label) }>
{ institutes &&
<Select autoWidth error={ meta.touched && meta.error } className={ classes.select } value={ val || '' } onChange={ this.handleChange } input={ <Input/> }>
{ allowNull && <MenuItem key="noInstitute" value=""><em>{ t('partners.public.c.select.select') }</em></MenuItem> }
{ institutes && institutes.sort((a, b) => a.code.localeCompare(b.code)).map((inst) => (
<MenuItem className={ classes.menuItem } key={ inst.code } value={ inst.code }>
<span className={ classes.code }>{ `${inst.code} ` }</span>
<Markdown className={ classes.fullName } source={ inst.fullName }/>
</MenuItem>
)) }
</Select>
}
</FormControl>
);
}
}
const mapStateToProps = (state, ownProps) => ({
institutes: state.partner.dashboard.partnerInstitutes && state.partner.dashboard.partnerInstitutes.data && state.partner.dashboard.partnerInstitutes.data.content || undefined,
loading: state.partner.dashboard.partnerInstitutes ? state.partner.dashboard.partnerInstitutes.loading : false,
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
loadPartnerInstitutes,
}, dispatch);
export default translate()(connect(mapStateToProps, mapDispatchToProps)(withStyles(styles)(SelectInstitute)));
......@@ -9,6 +9,7 @@ import Crop from 'model/genesys/Crop';
import {AccessionRef} from 'model/accession/AccessionRef';
import { SortDirection } from 'model/Page';
import { Permissions, IUserPermissions } from 'model/acl/ACL';
import Partner from 'model/genesys/Partner';
class Subset implements IUserPermissions {
public static clazz: string = 'org.genesys2.server.model.impl.Subset';
......@@ -26,6 +27,7 @@ class Subset implements IUserPermissions {
public lastModifiedBy: number;
public lastModifiedDate: Date;
public state: PublishState;
public owner: Partner;
public publisher: string;
public title: string;
public uuid: string;
......
......@@ -37,7 +37,7 @@ const apiCreateSubsetCreator = createApiCaller(SubsetService.createSubsetCreator
const apiUpdateSubsetCreator = createApiCaller(SubsetService.updateSubsetCreator, UPDATE_SUBSET_CREATOR);
const apiDeleteSubsetCreator = createApiCaller(SubsetService.deleteSubsetCreator, REMOVE_CREATOR_FROM_SUBSET);
const apiCreateSubset = createApiCaller(SubsetService.createSubsetCreator, DASHBOARD_RECEIVE_SUBSET);
const apiCreateSubset = createApiCaller(SubsetService.create, DASHBOARD_RECEIVE_SUBSET);
const apiUpdateSubset = createApiCaller(SubsetService.update, DASHBOARD_RECEIVE_SUBSET);
// Accession Identifiers step
......@@ -121,7 +121,7 @@ export const remoteSubmit = (values: Subset, dispatch) => {
export const saveSubset = (subset: Subset) => (dispatch) => {
if (!subset.uuid) {
subset.publisher = subset.wiewsCode;
subset.publisher = subset.owner.name;
return dispatch(apiCreateSubset(subset))
.then((subset) => dispatch(gotoNextStep(subset)));
}
......
......@@ -43,7 +43,7 @@ const dashboardRoutes = [
{
path: '/',
component: Loadable({
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "subsets" */'subsets/ui/dashboard//subset-stepper/steps/basic-info'),
loader: () => import(/* webpackMode:"lazy", webpackChunkName: "subsets" */'subsets/ui/dashboard/subset-stepper/steps/basic-info'),
}),
exact: true,
},
......
......@@ -14,13 +14,14 @@
}
},
"f": {
"partner": "Data provider",
"filterTitle": "Filter subsets",
"textSearch": "Text search",
"title": "Title",
"titlePlaceholder": "International",
"description": "Description",
"descriptionPlaceholder": "Subset description",
"institute": "Institute",
"institute": "FAO WIEWS Institute code",
"institutePlaceholder": "MEX002",
"crop": "Crop"
},
......@@ -91,7 +92,11 @@
"crops": "Crops",
"rights": "Rights",
"creationDate": "Creation date",
"source": "Source"
"source": "Source",
"partner": {
"label": "Select Data provider",
"placeholder": "Data provider"
}
},
"creators": {
"stepName": "Subset creators",
......@@ -132,4 +137,4 @@
}
}
}
}
\ No newline at end of file
}
......@@ -8,15 +8,19 @@ import CollapsibleComponentSearch from 'ui/common/filter/CollapsibleComponentSea
import StringFilter from 'ui/common/filter/StringFilter';
import StringArrFilter from 'ui/common/filter/StringArrFilter';
import CropFilter from 'crop/ui/c/CropFilter';
import PartnerFilter from 'partners/ui/c/PartnerFilter';
const SubsetFilters = ({handleSubmit, initialValues, initialize, t, ...other}) => {
// console.log('SubsetFilters', initialValues);
return (
<FiltersBlock title={ t('subsets.public.f.filterTitle') } handleSubmit={ handleSubmit } initialize={ initialize } { ...other }>
<CollapsibleComponentSearch title={ t('subsets.public.f.partner') }>
<StringArrFilter name="institutes" label={ t('subsets.public.f.institute') } placeholder={ t('subsets.public.f.institutePlaceholder') }/>
<PartnerFilter name="owner" label="subsets.public.f.partner"/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('subsets.public.f.textSearch') }>
<StringFilter name="title" searchType="contains" label={ t('subsets.public.f.title') } placeholder={ t('subsets.public.f.titlePlaceholder') }/>
<StringFilter name="description" searchType="contains" label={ t('subsets.public.f.description') } placeholder={ t('subsets.public.f.descriptionPlaceholder') }/>
<StringArrFilter name="institutes" label={ t('subsets.public.f.institute') } placeholder={ t('subsets.public.f.institutePlaceholder') }/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('subsets.public.f.crop') }>
<CropFilter />
......
......@@ -9,6 +9,7 @@ import CropFilter from 'crop/ui/c/CropFilter';
import StringFilter from 'ui/common/filter/StringFilter';
import StringArrFilter from 'ui/common/filter/StringArrFilter';
import StatusFilter from 'ui/catalog/dashboard/c/StatusFilter';
import PartnerFilter from 'partners/ui/c/PartnerFilter';
const SubsetFilters = ({handleSubmit, initialValues, initialize, t, ...other}) => {
return (
......@@ -16,10 +17,13 @@ const SubsetFilters = ({handleSubmit, initialValues, initialize, t, ...other}) =
<CollapsibleComponentSearch title={ t('common:label.status') }>
<StatusFilter/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('subsets.public.f.partner') }>
<PartnerFilter name="owner" label="subsets.public.f.partner"/>
<StringArrFilter name="institutes" label={ t('subsets.public.f.institute') } placeholder={ t('subsets.public.f.institutePlaceholder') }/>
</CollapsibleComponentSearch>
<CollapsibleComponentSearch title={ t('subsets.dashboard.f.textSearch') }>
<StringFilter name="title" searchType="contains" label={ t('subsets.dashboard.f.title') } placeholder={ t('subsets.dashboard.f.titlePlaceholder') }/>
<StringFilter name="description" searchType="contains" label={ t('subsets.dashboard.f.description') } placeholder={ t('subsets.dashboard.f.descriptionPlaceholder') }/>
<StringArrFilter name="institutes" label={ t('subsets.dashboard.f.institute') } placeholder={ t('subsets.dashboard.f.institutePlaceholder') }/>
<StringFilter name="dateCreated" searchType="contains" label={ t('subsets.dashboard.f.dateCreated') }/>
<StringArrFilter name="publisher" label={ t('subsets.dashboard.f.publisher') } placeholder={ t('subsets.dashboard.f.publisherPlaceholder') }/>
</CollapsibleComponentSearch>
......
......@@ -9,11 +9,14 @@ import Crop from 'model/genesys/Crop';
import {TextField} from 'ui/common/text-field';
import {MarkdownFieldWithAttach} from 'ui/common/markdown/MarkdownFieldWithAttach';
import CheckboxSelection from 'ui/common/forms/CheckboxSelection';
import SelectInstitute from 'institutes/ui/с/SelectInstitute';
import SelectPartner from 'partners/ui/c/SelectPartner';
interface ILoginContainerProps extends React.ClassAttributes<any> {
handleSubmit: () => void;
initialValues: any;
classes: any;
currentValues: any;
crops: Crop[];
uuid: string;
t: any;
......@@ -23,24 +26,36 @@ class BasicInfoStep extends React.Component<ILoginContainerProps, any> {
public render() {
const { crops, handleSubmit, t } = this.props;
const {crops, handleSubmit, initialValues, currentValues, t} = this.props;
return (
<form onSubmit={ handleSubmit } className="p-20 m-20 even-row">
<Field
required
name="title"
component={ TextField }
label={ t('subsets.dashboard.p.stepper.basicInfo.subsetTitle') }
placeholder="some title"
name="owner"
component={ SelectPartner }
onlyMine
value={ initialValues.institute ? initialValues.institute.owner : initialValues.owner }
label="subsets.dashboard.p.stepper.basicInfo.partner.label"
placeholder={ t('subsets.dashboard.p.stepper.basicInfo.paplaceholder') }
editable={ !(initialValues.uuid && initialValues.version) }
validate={ [Validators.required] }
/>
<Field
required
name="wiewsCode"
component={ TextField }
component={ SelectInstitute }
owner={ currentValues && currentValues.owner }
label={ t('subsets.dashboard.p.stepper.basicInfo.instituteCode') }
placeholder="NGA039"
editable={ !(initialValues.uuid && initialValues.version) }
validate={ currentValues && currentValues.owner && [Validators.required] }
/>
<Field
required
name="title"
component={ TextField }
label={ t('subsets.dashboard.p.stepper.basicInfo.subsetTitle') }
placeholder="some title"
validate={ [Validators.required] }
/>
<Field
......
import * as React from 'react';
import { translate } from 'react-i18next';
import {bindActionCreators} from 'redux';
import {isInvalid, isDirty, submit} from 'redux-form';
import {isInvalid, isDirty, submit, getFormValues} from 'redux-form';
import {connect} from 'react-redux';
// constants
import {SUBSET_FORM} from 'subsets/constants';
......@@ -15,13 +15,21 @@ interface ISubsetProps extends React.ClassAttributes<any> {
isInvalidForm: boolean;
isFormDirty: boolean;
submit: any;
values: any;
crops: Crop[];
t: any;
}
class BasicInfoStep extends StepperTemplate<ISubsetProps> {
protected renderContent = () => (<BasicInfoForm initialValues={ this.props.item } t={ this.props.t } crops={ this.props.crops }/>);
protected renderContent = () => (
<BasicInfoForm
initialValues={ this.props.item && {...this.props.item, owner: this.props.item && this.props.item.institute ? this.props.item.institute.owner : this.props.item.owner} }
t={ this.props.t }
crops={ this.props.crops }
currentValues={ this.props.values }
/>
)
protected gotoStep = (id) => {
const { onGotoStep, submit, isFormDirty } = this.props;
......@@ -46,6 +54,7 @@ const mapStateToProps = (state, ownProps) => ({
crops: state.crop.public.list ? state.crop.public.list.data : undefined,
isInvalidForm: isInvalid(SUBSET_FORM)(state),
isFormDirty: isDirty(SUBSET_FORM)(state),
values: getFormValues(SUBSET_FORM)(state),
});
const mapDispatchToProps = (dispatch) => bindActionCreators({
......
......@@ -2,6 +2,7 @@ import * as React from 'react';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import {translate} from 'react-i18next';
import 'babel-polyfill';
import { uploadMarkdownAttachment } from 'actions/repository';
......
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