Commit cbeac847 authored by Matija Obreza's avatar Matija Obreza
Browse files

Import descriptors from Excel into Descriptor List

parent 406b8d57
......@@ -138,6 +138,15 @@ export const addDescriptorToDescriptorList = (descriptorList: DescriptorList, de
});
};
// Add a descriptor to the descriptor list
export const addDescriptorsToDescriptorList = (descriptorList: DescriptorList, descriptorUuids: string[]) => (dispatch, getState) => {
return DescriptorListService.addDescriptor(getState().login.access_token, descriptorList, descriptorUuids)
.then((descriptorList) => {
// receive updates
dispatch(receiveDescriptorList(descriptorList));
});
};
// Remove a descriptor to the descriptor list
export const removeDescriptorFromDescriptorList = (descriptorList: DescriptorList, descriptor: Descriptor) => (dispatch, getState) => {
return DescriptorListService.removeDescriptor(getState().login.access_token, descriptorList, [ descriptor.uuid ])
......
......@@ -65,6 +65,15 @@ export const editDescriptor = (uuid: string) => (dispatch, getState) => {
.then((descriptor) => dispatch(push(`/descriptors/${descriptor.uuid}/edit`)));
};
// This method only saves the descriptor
export const importDescriptor = (descriptor: Descriptor) => (dispatch, getState) => {
log('Importing descriptor', descriptor);
const createOrSave = descriptor.version && descriptor.uuid ? DescriptorService.updateDescriptor : DescriptorService.createDescriptor;
return createOrSave(getState().login.access_token, descriptor);
};
export const saveDescriptor = (descriptor: Descriptor) => (dispatch, getState) => {
log('Saving descriptor', descriptor);
const createOrSave = descriptor.version && descriptor.uuid ? DescriptorService.updateDescriptor : DescriptorService.createDescriptor;
......
......@@ -67,7 +67,7 @@ function DescriptorLink({
{ children || descriptor.title }
</Link>
);
} else if (descriptor.published || descriptor._permissions.write) {
} else if (descriptor.published || (descriptor._permissions && descriptor._permissions.write)) {
return (
<Link to={ `/descriptors/${descriptor.uuid}` }>
{ children || descriptor.title }
......
......@@ -200,7 +200,7 @@ const DescriptorCard = ({complete = true, compact, descriptor, classes, classNam
{ (displayPref.vocabulary && descriptor.terms) && (
<Grid item xs={ 12 }>
{ descriptor.terms.map((term: VocabularyTerm) => (
<div key={ term.code }>{ term.code } &rarr; { term.title }</div>
<div key={ term.code }>{ term.code } &rarr; <b>{ term.title }</b> { term.description }</div>
)) }
</Grid>
) }
......
......@@ -2,16 +2,17 @@
import * as React from 'react';
import {connect} from 'react-redux';
import {bindActionCreators} from 'redux';
import { Link } from 'react-router';
import {log} from 'utilities/debug';
import {Page, Pagination} from 'model/common.model';
import {listCrops} from 'actions/crop';
import {loadMyPartners} from 'actions/partner';
import {Partner} from 'model/partner.model';
import {loadDescriptors} from 'actions/descriptors';
import {loadDescriptorList, saveDescriptorList, publishDescriptorList, addDescriptorToDescriptorList, removeDescriptorFromDescriptorList} from 'actions/descriptorList';
import {loadDescriptors, importDescriptor} from 'actions/descriptors';
import {loadDescriptorList, saveDescriptorList, publishDescriptorList, addDescriptorsToDescriptorList, addDescriptorToDescriptorList, removeDescriptorFromDescriptorList} from 'actions/descriptorList';
import {DescriptorList, Descriptor, IDescriptorFilter} from 'model/descriptor.model';
import DescriptorListForm from './c/DescriptorListForm';
......@@ -20,7 +21,8 @@ import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import Grid from 'material-ui/Grid';
import Paper from 'material-ui/Paper';
import {listCrops} from 'actions/crop';
import Button from 'material-ui/Button';
import DescriptorUpload from './c/DescriptorUpload';
interface IDescriptorListEditPageProps extends React.ClassAttributes<any> {
classes: any;
......@@ -31,6 +33,8 @@ interface IDescriptorListEditPageProps extends React.ClassAttributes<any> {
loadDescriptorList: any;
saveDescriptorList: any;
publishDescriptorList: any;
importDescriptor: any;
addDescriptorsToDescriptorList: any;
addDescriptorToDescriptorList: any;
removeDescriptorFromDescriptorList: any;
......@@ -54,10 +58,15 @@ class DescriptorListEditPage extends React.Component<IDescriptorListEditPageProp
loadMyPartners,
];
public constructor(props: any) {
super(props);
this.state = { uploader: false, csvDescriptors: '', uploadedDescriptors: null };
}
public componentWillMount() {
const {uuid, descriptorList, loadDescriptorList, myPartners, loadMyPartners} = this.props;
if (!myPartners || myPartners.length === 0) {
if (!myPartners) {
loadMyPartners();
}
......@@ -76,7 +85,7 @@ class DescriptorListEditPage extends React.Component<IDescriptorListEditPageProp
public onSave = (descriptorList) => {
const {saveDescriptorList} = this.props;
console.log('Saving ', descriptorList);
saveDescriptorList(descriptorList);
}
......@@ -100,6 +109,36 @@ class DescriptorListEditPage extends React.Component<IDescriptorListEditPageProp
removeDescriptorFromDescriptorList(descriptorList, descriptor);
}
public addDescriptors = () => {
log(`Openinig upload descriptors form`);
this.setState({ ...this.state, uploader: true });
}
public importDescriptors = async (d: Descriptor[]) => {
const {descriptorList, importDescriptor, addDescriptorsToDescriptorList} = this.props;
const imported: string[] = [];
if (d && d.length > 0) {
for (const descriptor of d) {
console.log('Importing', descriptor);
descriptor.owner = descriptorList.owner;
const r = importDescriptor(descriptor)
.then((saved) => {
log('Imported', saved);
imported.push(saved.uuid);
})
.catch((error) => {
log(`Descriptor import error`, error);
});
await r;
}
}
log('After importing', imported);
addDescriptorsToDescriptorList(descriptorList, imported);
this.setState({ ...this.state, uploader: false });
}
public render() {
const {myPartners, loadDescriptors, pagination, matchingDescriptors, listCrops, router} = this.props;
let { descriptorList } = this.props;
......@@ -113,15 +152,28 @@ class DescriptorListEditPage extends React.Component<IDescriptorListEditPageProp
<ContentHeaderWithButton title="Edit descriptor list information" buttonName="BACK TO DASHBOARD" buttonUrl="/dashboard/descriptorlists" />
<Grid container className="back-gray p-20">
<Grid item xs={ 12 }>
<Grid item xs={ 12 } className="mb-20">
<Paper className="p-20">
<DescriptorListForm initialValues={ descriptorList }
onPublish={ this.onPublish } onSubmit={ this.onSave } partners={ myPartners } />
onSubmit={ this.onSave } partners={ myPartners }
buttons={ (
<span>
<Link to="/dashboard/descriptorlists"><Button type="button">Back to dashboard</Button></Link>
{ descriptorList && descriptorList.uuid && <Button onClick={ this.addDescriptors }>Add descriptors from Excel</Button> }
{ descriptorList && descriptorList.id > 0 && ! descriptorList.published && <Button type="button" onClick={ this.onPublish }>Approve and Publish</Button> }
</span>
) } />
</Paper>
</Grid>
{ descriptorList.uuid && (
<Grid item xs={ 12 }>
{ this.state.uploader ? (
<Grid item xs={ 12 } className="mb-20">
<DescriptorUpload onImport={ this.importDescriptors } />
</Grid>
) : descriptorList.uuid && (
<Grid item xs={ 12 } className="mb-20">
<DescriptorPicker
loadDescriptors={ loadDescriptors }
matchingDescriptors={ matchingDescriptors }
......@@ -160,6 +212,8 @@ const mapDispatchToProps = (dispatch) => bindActionCreators({
saveDescriptorList,
publishDescriptorList,
loadDescriptors,
importDescriptor,
addDescriptorsToDescriptorList,
addDescriptorToDescriptorList,
removeDescriptorFromDescriptorList,
loadMyPartners,
......
import * as React from 'react';
import {Field, reduxForm} from 'redux-form';
import Button from 'material-ui/Button';
import { DESCRIPTORLIST_FORM } from 'constants/descriptors';
import { Link } from 'react-router';
import { TextField } from 'ui/common/text-field';
import { MarkdownField } from 'ui/common/markdown';
import SelectPartner from 'ui/catalog/partner/SelectPartner';
const DescriptorListForm = ({error, handleSubmit, initialValues, onPublish, partners}) => {
import Button from 'material-ui/Button';
const DescriptorListForm = ({error, handleSubmit, initialValues, buttons, partners}) => {
return (
<form onSubmit={ handleSubmit }>
......@@ -20,15 +20,14 @@ const DescriptorListForm = ({error, handleSubmit, initialValues, onPublish, part
component={ SelectPartner } partners={ partners } />
<Field name="crop" label="Crop code" placeholder="maize" component={ TextField } />
<Field required name="title" label="Descriptor list title" placeholder="Descriptors for" basicMarkdown component={ MarkdownField } />
<Field required disabled={ initialValues.uuid } name="versionTag" label="Version tag" placeholder="1.0" component={ TextField } />
<Field name="description" label="Description" placeholder="Full description of the descriptor list" component={ MarkdownField } />
<Field required name="versionTag" label="Version tag" placeholder="1.0" component={ TextField } />
<Field required name="publisher" label="Publisher" placeholder="" component={ TextField } />
<Field required name="bibliographicCitation" label="Bibliographic citation" placeholder="" component={ TextField } multiline />
<div>{ error && <strong>{ error }</strong> }</div>
<Button raised type="submit" >Save changes</Button>
<Link to="/dashboard/descriptorlists"><Button type="button">Back to dashboard</Button></Link>
{ initialValues && initialValues.id > 0 && ! initialValues.published && <Button type="button" onClick={ onPublish }>Approve and Publish</Button> }
<Button raised type="submit">Save changes</Button>
{ buttons && buttons }
</form>
);
};
......
import * as React from 'react';
// import {connect} from 'react-redux';
// import {bindActionCreators} from 'redux';
import {log} from 'utilities/debug';
import { CSV, ICsvConfiguration } from 'utilities/CSV';
import { Descriptor } from 'model/descriptor.model';
import { VocabularyTerm } from 'model/vocabulary.model';
import ContentHeaderWithButton from 'ui/common/heading/ContentHeaderWithButton';
import DescriptorCard from 'ui/catalog/descriptor/DescriptorCard';
import Grid from 'material-ui/Grid';
import Paper from 'material-ui/Paper';
import Button from 'material-ui/Button';
import FormControl from 'material-ui/Form/FormControl';
import Input from 'material-ui/Input';
import InputLabel from 'material-ui/Input/InputLabel';
interface IDescriptorUpload extends React.ClassAttributes<any> {
className?: any;
onImport: (descriptors: Descriptor[]) => any;
}
// Page to edit a descriptor list
class DescriptorUpload extends React.Component<IDescriptorUpload, any> {
public constructor(props: any) {
super(props);
this.state = { uploader: false, csvDescriptors: '', uploadedDescriptors: null };
}
private makeTerms = (codes, titles, descriptions) => {
const terms: VocabularyTerm[] = [];
if (! codes) {
return terms;
}
const c: string[] = codes.split(/\n/g);
const t: string[] = titles.split(/\n/g);
const d: string[] = descriptions.split(/\n/g);
// console.log(c, t, d);
for (let i = 0; i < c.length; i++) {
const term: VocabularyTerm = new VocabularyTerm();
term.code = c[i].trim();
term.title = t.length >= i ? t[i].trim() : c[i].trim();
term.description = d.length >= i ? d[i].trim() : null;
terms.push(term);
}
return terms;
}
public parseCsvDescriptor = (e) => {
const csvText: string = e.target.value;
// log('CSV text', csvText);
const config: ICsvConfiguration = CSV.detectConfiguration(csvText);
log('CSV config', config);
const newDescriptors: Descriptor[] = [];
CSV.parse(csvText, config, {
headers: [
'crop', 'versionTag', 'title', 'category', '_keyDescriptor', 'description', 'dataType',
'integerOnly', 'minValue', 'maxValue', 'vocabularyId', 'code', 'code_title', 'code_description',
'published', 'columnName', 'uom', 'headingNumber'] })
.on('json', (jsonObj) => {
if (jsonObj.minValue) { jsonObj.minValue = +jsonObj.minValue; }
if (jsonObj.maxValue) { jsonObj.maxValue = +jsonObj.maxValue; }
if (jsonObj.integerOnly) { jsonObj.integerOnly = jsonObj.integerOnly === 'TRUE' ? true : false; }
if (jsonObj._keyDescriptor) {
jsonObj.key = jsonObj._keyDescriptor === 'TRUE' ? true : false;
delete jsonObj._keyDescriptor;
}
if (jsonObj.code) {
jsonObj.terms = this.makeTerms(jsonObj.code, jsonObj.code_title, jsonObj.code_description);
delete jsonObj.code;
delete jsonObj.code_title;
delete jsonObj.code_description;
}
const d: Descriptor = new Descriptor(jsonObj);
newDescriptors.push(d);
// log(d);
}).on('end', () => {
log('All CSV parsed');
this.setState({ ...this.state, uploader: true, uploadedDescriptors: newDescriptors });
// this.props.onAccessionsUpdated(newIdentifiers);
});
}
public clickImport = (e) => {
// log('Sending', this.state.uploadedDescriptors);
if (this.state.uploadedDescriptors && this.state.uploadedDescriptors.length > 0) {
this.props.onImport(this.state.uploadedDescriptors);
} else {
log('Nothing to import');
}
}
public render() {
return (
<div>
<Paper className={ `${this.props.className} p-20 mb-20` }>
<FormControl fullWidth>
<InputLabel>Descriptor definitions</InputLabel>
<Input multiline placeholder="Paste descriptor data here (tab separated)" onBlur={ this.parseCsvDescriptor }/>
</FormControl>
</Paper>
{ this.state.uploadedDescriptors ? (
<div>
<ContentHeaderWithButton title="Uploaded descriptor definitions" buttons={
<Button raised onClick={ this.clickImport }>Import descriptors</Button>
} />
<Grid container spacing={ 24 }>
{ this.state.uploadedDescriptors.map((d, index) => (
<Grid item key={ index } xs={ 12 } md={ 6 } xl={ 4 }>
<DescriptorCard descriptor={ d } />
</Grid>
)) }
</Grid>
</div>
) : (
<div>No descriptors uploaded.</div>
) }
</div>
);
}
}
//
// const mapStateToProps = (state, ownProps) => ({
// descriptorList: ownProps.descriptorList,
// });
//
// const mapDispatchToProps = (dispatch) => bindActionCreators({
// addDescriptorToDescriptorList,
// removeDescriptorFromDescriptorList,
// }, dispatch);
//
// export default connect(mapStateToProps, mapDispatchToProps)(DescriptorListEditPage);
export default DescriptorUpload;
Supports Markdown
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