Commit c9ef0b19 authored by Maxym Borodenko's avatar Maxym Borodenko
Browse files

Do not save descriptorList on every blur event

parent 9b594b83
......@@ -6,12 +6,15 @@ import { Page } from 'model/common.model';
import {log} from 'utilities/debug';
import { addFilterCode } from 'actions/filterCode';
import {cleanFilters} from 'utilities';
import * as _ from 'lodash';
import {
GET_DESCRIPTORLIST, RECEIVE_DESCRIPTORLIST,
CREATE_DESCRIPTORLIST,
LIST_DESCRIPTORLISTS, RECEIVE_DESCRIPTORLISTS,
} from 'constants/descriptors';
import {navigateTo} from './navigation';
import steps from 'ui/pages/descriptorlist/descriptorlist-stepper/steps';
const receiveDescriptorList = (descriptorList: DescriptorList) => ({
type: RECEIVE_DESCRIPTORLIST,
......@@ -147,14 +150,24 @@ export const editDescriptorList = (uuid: string) => (dispatch, getState) => {
// Save the descriptor list
export const saveDescriptorList = (descriptorList: DescriptorList) => (dispatch, getState) => {
const needToRedirect: boolean = !(descriptorList.version && descriptorList.uuid);
if (_.isEqual({...getState().descriptorList.currentDescriptorList}, {...descriptorList})) {
return;
}
log('Saving descriptor list', descriptorList);
const createOrSave = descriptorList.version ? DescriptorListService.updateDescriptorList : DescriptorListService.createDescriptorList;
return createOrSave(getState().login.access_token, descriptorList)
// when response is back
.then((descriptorList) => {
.then((saved) => {
// receive the updated descriptor list
dispatch(receiveDescriptorList(descriptorList));
dispatch(receiveDescriptorList(saved));
if (needToRedirect) {
const path = steps.find((e) => e.id === 2).link;
dispatch(navigateTo(`/descriptorlists/${saved.uuid}/${path}`));
}
}).catch((error) => {
log(`Error saving descriptor list`, error, descriptorList);
});
......
......@@ -5,7 +5,7 @@ import StepNavigation from 'ui/common/stepper/StepNavigation';
import ProgressMenu from 'ui/common/stepper/progress-menu';
import Loading from 'ui/common/Loading';
function DatasetNavigator({children, location, stillLoading, steps, disabled, disabledNext, gotoStep, onDelete, onPublish}) {
function NavigationWrapper({children, location, stillLoading, steps, disabled, disabledNext, gotoStep, onDelete, onPublish}) {
return (
<Grid container spacing={ 0 }>
<Grid item xs={ 12 } md={ 9 } xl={ 10 } className="back-gray p-20">
......@@ -28,4 +28,4 @@ function DatasetNavigator({children, location, stillLoading, steps, disabled, di
);
}
export default DatasetNavigator;
export default NavigationWrapper;
......@@ -6,7 +6,7 @@ import {Dataset, AccessionIdentifier} from 'model/dataset.model';
import {updateDatasetAccessionIdentifiers} from 'actions/dataset';
import ListOfAccesion from './ListOfAccesion';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
interface IAccessionsListStep extends React.ClassAttributes<any> {
dataset: Dataset;
......@@ -34,17 +34,17 @@ class AccessionsListStep extends React.Component<IAccessionsListStep, any> {
}
public render() {
const {dataset, stillLoading, onDelete, onPublish} = this.props;
const {dataset, stillLoading, onDelete, onPublish, location} = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading } disabledNext={ false }
<NavigationWrapper location={ location } stillLoading={ stillLoading } disabledNext={ false }
disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<ListOfAccesion
accessionIdentifiers={ dataset.accessionIdentifiers }
onAccessionsUpdated={ this.updateAccessionIdentifiers }
/>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -11,7 +11,7 @@ import {Partner} from 'model/partner.model';
import {Crop} from 'model/crop.model';
import {submit, isInvalid} from 'redux-form';
import {DATASET_BASIC_INFO_FORM} from 'constants/datasets';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
import steps from '../../steps';
interface IDatasetProps extends React.ClassAttributes<any> {
......@@ -54,14 +54,14 @@ class BasicInfoStep extends React.Component<IDatasetProps, any> {
const {myPartners, dataset, location, stillLoading, onDelete, onPublish, isInvalidForm} = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading } disabledNext={ isInvalidForm }
<NavigationWrapper location={ location } stillLoading={ stillLoading } disabledNext={ isInvalidForm }
disabled={ !(dataset && dataset.uuid) } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<BasicInfoForm
initialValues={ dataset }
partners={ myPartners }
/>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -7,7 +7,7 @@ import { createDatasetCreator, deleteCreatorRequest, updateCreatorRequest } from
import { Creator } from 'model/creator.model';
import { Dataset } from 'model/dataset.model';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
import {getFormValues} from 'redux-form';
import { DATASET_CREATOR_FORM} from 'constants/datasets';
import * as _ from 'lodash';
......@@ -54,7 +54,7 @@ class CreatorsStep extends React.Component<ICreatorsStepProps, any> {
const { dataset, deleteCreatorRequest, location, onDelete, onPublish, stillLoading} = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading }
<NavigationWrapper location={ location } stillLoading={ stillLoading }
disabledNext={ false } disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<DatasetCreatorForm
......@@ -63,7 +63,7 @@ class CreatorsStep extends React.Component<ICreatorsStepProps, any> {
createDatasetCreator={ this.create }
deleteCreatorRequest={ deleteCreatorRequest }
/>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -9,7 +9,7 @@ import {uploadRepositoryFileRequest, updateRepositoryFileRequest, deleteReposito
import FilesForm from './FilesForm';
import {RepositoryFile} from 'model/repositoryFile.model';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
interface IFilesStepProps extends React.ClassAttributes<any> {
dataset: Dataset;
......@@ -34,7 +34,7 @@ class FilesStep extends React.Component<IFilesStepProps, any> {
const { dataset, location, onDelete, onPublish, stillLoading } = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading }
<NavigationWrapper location={ location } stillLoading={ stillLoading }
disabledNext={ false } disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<FilesForm
......@@ -44,7 +44,7 @@ class FilesStep extends React.Component<IFilesStepProps, any> {
updateRepositoryFile={ updateRepositoryFileRequest }
deleteRepositoryFile={ deleteRepositoryFileRequest }
/>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -8,7 +8,7 @@ import {setDescriptorsToDatasetRequest} from 'actions/dataset';
import DescriptorOrder from 'ui/common/reorderable/DescriptorOrder';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
import {Dataset} from 'model/dataset.model';
interface IReorderTraitsStep extends React.ClassAttributes<any> {
......@@ -45,14 +45,14 @@ class ReorderTraitsStep extends React.Component<IReorderTraitsStep, any> {
}
public render() {
const { dataset, stillLoading, onDelete, onPublish } = this.props;
const { dataset, stillLoading, onDelete, onPublish, location } = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading }
<NavigationWrapper location={ location } stillLoading={ stillLoading }
disabledNext={ false } disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<DescriptorOrder onRef={ this.onRef } descriptors={ dataset.descriptors } />
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -4,7 +4,7 @@ import {bindActionCreators} from 'redux';
import DatasetDisplay from 'ui/pages/dataset/c/DatasetDisplay';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
class ReviewAndPublishStep extends React.Component<any, any> {
......@@ -13,16 +13,16 @@ class ReviewAndPublishStep extends React.Component<any, any> {
}
public render() {
const { dataset, stillLoading, onDelete, onPublish } = this.props;
const { dataset, stillLoading, onDelete, onPublish, location } = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading } disabledNext={ false }
<NavigationWrapper location={ location } stillLoading={ stillLoading } disabledNext={ false }
disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<div className="even-row p-10">
<DatasetDisplay dataset={ dataset } />
</div>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -9,7 +9,7 @@ import {createLocationRequest, deleteLocationRequest, updateLocationRequest} fro
import TimingAndLocationForm from './TimingAndLocationForm';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
import {getFormValues, change} from 'redux-form';
import {TIMING_AND_LOCATION_FORM} from 'constants/datasets';
import * as _ from 'lodash';
......@@ -57,10 +57,10 @@ class TimingAndLocationStep extends React.Component<ITimingAndLocationStepProps,
}
public render() {
const {dataset, deleteLocationRequest, stillLoading, onPublish, onDelete} = this.props;
const {dataset, deleteLocationRequest, stillLoading, onPublish, onDelete, location} = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading }
<NavigationWrapper location={ location } stillLoading={ stillLoading }
disabledNext={ false } disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<TimingAndLocationForm
......@@ -70,7 +70,7 @@ class TimingAndLocationStep extends React.Component<ITimingAndLocationStepProps,
deleteLocation={ deleteLocationRequest }
changeFieldValue={ this.changeFieldValue }
/>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -13,7 +13,7 @@ import DescriptorPicker from 'ui/catalog/descriptor/DescriptorPicker';
import {listCrops} from 'actions/crop';
import {Pagination} from 'model/common.model';
import steps from '../../steps';
import DatasetNavigator from '../../DatasetNavigator';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
class Traits extends React.Component<any, any> {
......@@ -51,7 +51,7 @@ class Traits extends React.Component<any, any> {
const { stillLoading, onDelete, onPublish } = this.props;
return (
<DatasetNavigator location={ location } stillLoading={ stillLoading } disabledNext={ false }
<NavigationWrapper location={ location } stillLoading={ stillLoading } disabledNext={ false }
disabled={ false } steps={ steps }
gotoStep={ this.gotoStep } onDelete={ onDelete } onPublish={ onPublish }>
<DescriptorPicker
......@@ -66,7 +66,7 @@ class Traits extends React.Component<any, any> {
listCrops={ listCrops }
classes={ {} }
/>
</DatasetNavigator>
</NavigationWrapper>
);
}
}
......
......@@ -7,13 +7,10 @@ import { MarkdownField } from 'ui/catalog/markdown';
import Authorize from 'ui/common/authorized/Authorize';
import SelectPartner from 'ui/catalog/partner/SelectPartner';
import Validators from 'utilities/Validators';
import remoteSubmit from 'ui/pages/descriptorlist/descriptorlist-stepper/steps/basic-info/RemoteSubmit';
class DescriptorListForm extends React.Component<any, any> {
protected save = () => {
setTimeout(this.props.handleSubmit);
}
public render() {
const {error, handleSubmit, initialValues, partners} = this.props;
return (
......@@ -26,7 +23,6 @@ class DescriptorListForm extends React.Component<any, any> {
editable={ !(initialValues.uuid && initialValues.version) }
component={ SelectPartner } partners={ partners }
validate={ [Validators.required] }
onBlur={ this.save }
/>
<Authorize role="ROLE_ADMINISTRATOR">
......@@ -46,7 +42,6 @@ class DescriptorListForm extends React.Component<any, any> {
label="UUID"
placeholder="ihope-youk-noww-hatyouredoing"
component={ TextField }
onBlur={ this.save }
/>
</div>
}
......@@ -56,7 +51,6 @@ class DescriptorListForm extends React.Component<any, any> {
label="Crop code"
placeholder="maize"
component={ TextField }
onBlur={ this.save }
/>
<Field required
name="title"
......@@ -65,7 +59,6 @@ class DescriptorListForm extends React.Component<any, any> {
basicMarkdown
component={ MarkdownField }
validate={ [Validators.required] }
onBlur={ this.save }
/>
<Field required
disabled={ initialValues.uuid }
......@@ -74,33 +67,28 @@ class DescriptorListForm extends React.Component<any, any> {
placeholder="1.0"
component={ TextField }
validate={ [Validators.required] }
onBlur={ this.save }
/>
<Field name="description"
label="Description"
placeholder="Full description of the descriptor list"
component={ MarkdownField }
onBlur={ this.save }
/>
<Field name="url"
label="URL to definition"
placeholder="https://"
component={ TextField }
validate={ [Validators.url] }
onBlur={ this.save }
/>
<Field name="publisher"
label="Publisher"
placeholder=""
component={ TextField }
onBlur={ this.save }
/>
<Field name="bibliographicCitation"
label="Bibliographic citation"
placeholder=""
component={ TextField }
multiline
onBlur={ this.save }
/>
<div>{ error && <strong>{ error }</strong> }</div>
......@@ -112,4 +100,5 @@ class DescriptorListForm extends React.Component<any, any> {
export default reduxForm({
enableReinitialize: true, // https://redux-form.com/7.1.0/examples/initializefromstate/
form: DESCRIPTORLIST_FORM,
onSubmit: remoteSubmit,
})(DescriptorListForm);
......@@ -9,49 +9,14 @@ import confirm from 'utilities/confirmAlert';
import { setPageTitle } from 'actions/pageTitle';
import { loadDescriptorList, deleteDescriptorList, publishDescriptorList} from 'actions/descriptorList';
import { navigateTo } from 'actions/navigation';
import StepNavigation from 'ui/common/stepper/StepNavigation';
import TopSection from 'ui/common/stepper/TopSection';
import BottomSection from 'ui/common/stepper/BottomSection';
import ProgressMenu from 'ui/common/stepper/progress-menu';
import { DescriptorList } from 'model/descriptor.model';
import renderRoutes from 'ui/renderRoutes';
import Loading from 'ui/common/Loading';
import {loadMyPartners} from 'actions/partner';
import {Partner} from 'model/partner.model';
const steps = [
{
id: 1,
name: 'Basic information',
link: 'edit',
active: false,
},
{
id: 2,
name: 'Select descriptors',
link: 'edit/select-descriptors',
active: false,
},
{
id: 3,
name: 'Import descriptors',
link: 'edit/import-descriptors',
active: false,
},
{
id: 4,
name: 'Reorder descriptors',
link: 'edit/reorder-descriptors',
active: false,
},
{
id: 5,
name: 'Review and publish',
link: 'edit/review-and-publish',
active: false,
},
];
import steps from './steps';
interface IDescriptorListProps extends React.ClassAttributes<any> {
loadDescriptorList: any;
......@@ -86,10 +51,6 @@ class DescriptorListStepper extends React.Component<IDescriptorListProps, any> {
setPageTitle(pageTitle);
}
private onRef = (that) => {
this.setState({ childrenRef: that });
}
public componentWillMount() {
const {uuid, descriptorList, loadDescriptorList, myPartners, loadMyPartners} = this.props;
......@@ -102,17 +63,11 @@ class DescriptorListStepper extends React.Component<IDescriptorListProps, any> {
}
}
protected gotoStep = (id) => () => {
protected gotoStep = (id) => {
const {descriptorList, uuid, navigateTo} = this.props;
const path = steps.find((e) => e.id === id).link;
if (uuid || (descriptorList && descriptorList.uuid)) {
navigateTo(`/descriptorlists/${descriptorList ? descriptorList.uuid : uuid}/${path}`);
steps.forEach((i) => i.active = false);
steps[id - 1].active = true;
if (this.state.childrenRef && this.state.childrenRef.onSave) {
this.state.childrenRef.onSave();
}
} else {
// no navigation!
}
......@@ -126,7 +81,7 @@ class DescriptorListStepper extends React.Component<IDescriptorListProps, any> {
confirmLabel: 'Delete',
abortLabel: 'Cancel',
}).then(() => {
deleteDescriptorList(descriptorList).then(() => navigateTo(`/dashboard`));
deleteDescriptorList(descriptorList).then(() => navigateTo(`/dashboard/descriptorlists`));
}).catch(() => {
// don't delete
});
......@@ -148,30 +103,15 @@ class DescriptorListStepper extends React.Component<IDescriptorListProps, any> {
}
public render() {
const {uuid, pageTitle, location, descriptorList, route, match} = this.props;
const {uuid, pageTitle, descriptorList, route, match} = this.props;
const stillLoading: boolean = (! descriptorList || (uuid && (descriptorList.uuid !== uuid)));
return (
<Grid container spacing={ 0 }>
<TopSection pageTitle={ pageTitle } subTitle="Publish your descriptor list" />
<Grid item xs={ 12 } md={ 9 } xl={ 10 } className="back-gray p-20">
<Grid container spacing={ 0 } className="back-white">
<StepNavigation disabled={ !(descriptorList && descriptorList.uuid) }
disabledNext={ !(descriptorList && descriptorList.uuid) } onGotoStep={ this.gotoStep } onDelete={ this.onDelete } steps={ steps } location={ location } showStepName bottomDivider onPublish={ this.onPublish } />
<Grid item xs={ 12 }>
{ stillLoading && uuid ? <Loading /> :
<div>
{ renderRoutes(route.routes, match.path, { onRef : this.onRef }) }
</div>
}
</Grid>
<StepNavigation disabled={ !(descriptorList && descriptorList.uuid) }
disabledNext={ !(descriptorList && descriptorList.uuid) } onGotoStep={ this.gotoStep } onDelete={ this.onDelete } steps={ steps } location={ location } topDivider onPublish={ this.onPublish } />
</Grid>
</Grid>
<Grid item xs={ 12 } md={ 3 } xl={ 2 }>
<ProgressMenu disabled={ !(descriptorList && descriptorList.uuid) } onGotoStep={ this.gotoStep } steps={ steps } location={ location } />
</Grid>
{
renderRoutes(route.routes, match.path, { stillLoading, onGotoStep: this.gotoStep, onDelete: this.onDelete, onPublish: this.onPublish })
}
<BottomSection/>
</Grid>
);
......
const steps = [
{
id: 1,
name: 'Basic information',
link: 'edit',
},
{
id: 2,
name: 'Select descriptors',
link: 'edit/select-descriptors',
},
{
id: 3,
name: 'Import descriptors',
link: 'edit/import-descriptors',
},
{
id: 4,
name: 'Reorder descriptors',
link: 'edit/reorder-descriptors',
},
{
id: 5,
name: 'Review and publish',
link: 'edit/review-and-publish',
},
];
export default steps;
import {saveDescriptorList} from 'actions/descriptorList';
import {DescriptorList} from 'model/descriptor.model';
export default function remoteSubmit(values: DescriptorList, dispatch) {
dispatch(saveDescriptorList(values));
}
import * as React from 'react';
import {bindActionCreators} from 'redux';
import {connect} from 'react-redux';
import * as _ from 'lodash';
import DescriptorListForm from 'ui/pages/descriptorlist/c/DescriptorListForm';
import {DescriptorList} from 'model/descriptor.model';
import {loadDescriptorList, saveDescriptorList} from 'actions/descriptorList';
import {loadMyPartners} from 'actions/partner';
import {Partner} from 'model/partner.model';
import {log} from 'utilities/debug';
import {submit, isInvalid} from 'redux-form';
import NavigationWrapper from 'ui/common/stepper/NavigationWrapper';
import {DESCRIPTORLIST_FORM} from 'constants/descriptors';
import steps from '../../steps';
interface IDescriptorListProps extends React.ClassAttributes<any> {
uuid: string;
......@@ -17,6 +19,13 @@ interface IDescriptorListProps extends React.ClassAttributes<any> {
saveDescriptorList: any;
loadMyPartners: any;
myPartners: Partner[];
stillLoading: boolean;
onDelete: () => void;
onPublish: () => void;
onGotoStep: (id: number) => () => void;
location: any;
isInvalidForm: boolean;
submit: any;
}
class BasicInfoStep extends React.Component<IDescriptorListProps, any> {
......@@ -27,21 +36,19 @@ class BasicInfoStep extends React.Component<IDescriptorListProps, any> {
public componentWillMount() {
const {myPartners, loadMyPartners} = this.props;
if (!myPartners) {
if (! myPartners || myPartners.length === 0) {
loadMyPartners();
}
}
protected handleSubmit = (values: DescriptorList) => {