Commit d199d7ab authored by Florent Chehab's avatar Florent Chehab

Bug removed in Module

UniversityScholarship & Country scholarship ready
Moved to context provider for univ info
parent 62c55ee1
......@@ -114,14 +114,18 @@ class MyComponent extends Component {
loadPropsIfNeeded() {
this.propsThatNeedToBeFetch().map((propKey) => {
if (this.__apiAttr && this.__apiAttr[propKey]) {
this.props.fetchData[propKey](this.props[this.__apiAttr[propKey]]);
} else {
this.props.fetchData[propKey]();
}
this.performLoadProp(propKey);
})
}
performLoadProp(propKey) {
if (this.__apiAttr && this.__apiAttr[propKey]) {
this.props.fetchData[propKey](this.props[this.__apiAttr[propKey]]);
} else {
this.props.fetchData[propKey]();
}
}
allFetchedDataAreReady() {
return !this.fetchAbleProps.some((propKey) => {
if (!this.propIsUsable(propKey)) {
......
......@@ -3,13 +3,14 @@ import PropTypes from 'prop-types';
import Typography from '@material-ui/core/Typography';
import Paper from '@material-ui/core/Paper';
import MyComponent from '../MyComponent';
import {connect} from "react-redux";
import { connect } from "react-redux";
import Dialog from '@material-ui/core/Dialog';
import DialogActions from '@material-ui/core/DialogActions';
import DialogTitle from '@material-ui/core/DialogTitle';
import Button from '@material-ui/core/Button';
import UniversityTemplate from '../university/UniversityTemplate';
import UnivInfoProvider from '../university/shared/UnivInfoProvider';
import {
NavLink,
......@@ -61,9 +62,12 @@ function renderFirstTimeHere() {
)
}
function renderDefaultView(univId) {
return (
<UniversityTemplate univId={univId} />
<UnivInfoProvider univId={univId}>
<UniversityTemplate />
</UnivInfoProvider>
);
}
......
import React from 'react';
const UnivContext = React.createContext();
export default UnivContext;
\ No newline at end of file
......@@ -58,7 +58,7 @@ class UniversityTemplate extends React.Component {
};
render() {
const { classes, univId, width } = this.props;
const { classes, width } = this.props;
const { value } = this.state;
let scroll = true;
......@@ -91,12 +91,12 @@ class UniversityTemplate extends React.Component {
<Tab label="Autres" icon={<MoreHorizIcon />} />
</Tabs>
</AppBar>
<TabContainer visible={value === 0}> <GeneralInfoTab univId={univId} visible={value === 0} /> </TabContainer>
{/* {<TabContainer visible={value === 1}> <UniversityMoreTab univId={univId} visible={value === 1} /> </TabContainer>} */}
{/* {value === 2 && <TabContainer> <PreviousDeparturesTab univId={univId} /> </TabContainer>} */}
{<TabContainer visible={value === 3}> <ScholarshipsTab univId={univId} visible={value === 3} /> </TabContainer>}
{/* {value === 4 && <TabContainer> <CampusesCitiesTab univId={univId} /> </TabContainer>} */}
{/* {value === 5 && <TabContainer> <MoreTab univId={univId} /> </TabContainer>} */}
<TabContainer visible={value === 0}> <GeneralInfoTab visible={value === 0} /> </TabContainer>
{/* {<TabContainer visible={value === 1}> <UniversityMoreTab visible={value === 1} /> </TabContainer>} */}
{/* {value === 2 && <TabContainer> <PreviousDeparturesTab /> </TabContainer>} */}
{<TabContainer visible={value === 3}> <ScholarshipsTab visible={value === 3} /> </TabContainer>}
{/* {value === 4 && <TabContainer> <CampusesCitiesTab /> </TabContainer>} */}
{/* {value === 5 && <TabContainer> <MoreTab /> </TabContainer>} */}
</div>
</div>
......@@ -106,7 +106,6 @@ class UniversityTemplate extends React.Component {
UniversityTemplate.propTypes = {
classes: PropTypes.object.isRequired,
univId: PropTypes.string.isRequired,
};
export default compose(
......
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from '@material-ui/core/styles/withStyles';
import compose from 'recompose/compose';
import { connect } from "react-redux";
import ScholarshipsEditor from '../shared/ScholarshipsEditor';
import editorStyle from '../shared/editorStyle';
import getMapStateToPropsForEditor from '../shared/editorFunctions/getMapStateToPropsForEditor';
import getMapDispatchToPropsForEditor from '../shared/editorFunctions/getMapDispatchToPropsForEditor';
import {
countryScholarshipsElSaveData,
countryScholarshipsElSavingHasError
} from '../../../generated/actions';
const styles = theme => ({
...editorStyle(theme)
});
class CountryScholarshipsEditor extends ScholarshipsEditor {
renderLinkedField() {
return this.renderCountriesField();
}
}
CountryScholarshipsEditor.propTypes = {
modelData: PropTypes.object.isRequired,
};
export default compose(
withStyles(styles, { withTheme: true }),
connect(
getMapStateToPropsForEditor('countryScholarshipsEl'),
getMapDispatchToPropsForEditor(countryScholarshipsElSaveData, countryScholarshipsElSavingHasError)
)
)(CountryScholarshipsEditor);
\ No newline at end of file
......@@ -4,7 +4,7 @@ import withStyles from '@material-ui/core/styles/withStyles';
import compose from 'recompose/compose';
import { connect } from "react-redux";
import Editor from '../shared/Editor';
import ScholarshipsEditor from '../shared/ScholarshipsEditor';
import editorStyle from '../shared/editorStyle';
......@@ -20,64 +20,9 @@ const styles = theme => ({
...editorStyle(theme)
});
const frequencyOptions = [
{ value: 'w', label: "Il s'agit du montant hebdomadaire" },
{ value: 'm', label: "Il s'agit du montant mensuel" },
{ value: 's', label: "Il s'agit du montant semestriel" },
{ value: 'y', label: "Il s'agit du montant annuel" },
{ value: 'o', label: "Il s'agit d'un montant donné une seule fois" }
]
class UniversityScholarshipsEditor extends Editor {
formHasError() {
let messages = Array();
const formData = this.getDataFromFields();
const { amount_min, amount_max } = formData;
console.log(formData);
if (amount_min !== null && amount_max !== null && amount_max < amount_min) {
messages.push("La logique voudrait que la borne supérieure de la bourse soit... supérieure à la borne inférieure.")
}
return this.buildError(messages);
}
renderEditor() {
return (
<div>
{this.renderObjModerationLevelField()}
{this.renderTitleField()}
{this.renderUniversitiesField()}
{this.renderTextField({
required: true,
label: "Présentation succincte",
maxLength: 200,
fieldMapping: 'type',
})}
{this.renderCurrencyField({ label: "Devise", required: false, fieldMapping: 'currency' })}
{this.renderNumberField({
label: "Borne inférieure du montant de la bourse",
minValue: 0,
fieldMapping: 'amount_min',
})}
{this.renderNumberField({
label: "Borne supérieure du montant de la bourse",
minValue: 0,
fieldMapping: 'amount_max',
})}
{this.renderSelectField({
label: "Fréquence de la bourse",
options: frequencyOptions,
fieldMapping: 'frequency',
})}
{this.renderMarkdownField({
label: "Autres avantages",
maxLength: 500,
formManager: this,
fieldMapping: 'other_advantages',
})}
{this.renderCommentField()}
{this.renderUsefulLinksField()}
</div>
)
class UniversityScholarshipsEditor extends ScholarshipsEditor {
renderLinkedField() {
return this.renderUniversitiesField();
}
}
......@@ -85,7 +30,6 @@ UniversityScholarshipsEditor.propTypes = {
modelData: PropTypes.object.isRequired,
};
export default compose(
withStyles(styles, { withTheme: true }),
connect(
......
......@@ -72,7 +72,6 @@ class CountryDri extends Module {
{
countryDriItems.map((rawModelData) => (
<GenericModule
visible={this.props.visible}
buildTitle={(modelData) => modelData.title}
rawModelData={rawModelData}
parseRawModelData={parseRawModelData}
......
import React from 'react';
import PropTypes from 'prop-types';
import withStyles from '@material-ui/core/styles/withStyles';
import compose from 'recompose/compose';
import { connect } from "react-redux";
import __pick from 'lodash/pick';
import Module from '../shared/Module';
import GenericModule from '../shared/GenericModule';
import GenericGroupModule from '../shared/GenericGroupModule';
import Scholarship from '../shared/Scholarship';
import CountryScholarshipsEditor from '../editors/CountryScholarshipsEditor';
import {
countryScholarshipsFetchData,
countryScholarshipsInvalidated,
} from '../../../generated/actions';
const styles = theme => ({
});
function renderCore(rawModelData, classes, outsideData) {
const { comment, frequency, currency, type } = rawModelData;
const amountMin = rawModelData.amount_min,
amountMax = rawModelData.amount_max,
otherAdvantages = rawModelData.other_advantages;
return (
<Scholarship
currency={currency}
currencies={outsideData.currencies}
frequency={frequency}
type={type}
amountMin={amountMin}
amountMax={amountMax}
otherAdvantages={otherAdvantages}
comment={comment}
/>
)
}
function parseRawModelData(rawModelData) {
// reverse serialization
const modelData = __pick(rawModelData,
[
"id",
"title",
"type",
"currency",
"frequency",
"amount_min",
"amount_max",
// "importance_level",
"countries",
"comment",
"other_advantages",
"useful_links",
"obj_moderation_level",
]);
return modelData;
}
class CountryScholarships extends Module {
myRender() {
const countryScholarshipsItems = this.getFetchedData('countryScholarships');
const { countries, currencies, classes } = this.props;
const outsideData = {
countries,
currencies
}
return (
<GenericGroupModule
groupTitle={`Bourses liées au pays (${this.props.country.name})`}
endPoint={"countryScholarship"}
editor={CountryScholarshipsEditor}
invalidateGroup={this.props.invalidateData}
propsForEditor={{
modelData: { countries: [this.props.countryId], importance_level: '-', currency: 'EUR', obj_moderation_level: 0 },
parseRawModelData: parseRawModelData,
outsideData: outsideData,
__apiAttr: this.props.countryId,
}}
>
{
countryScholarshipsItems.map((rawModelData) => (
<GenericModule
buildTitle={(modelData) => modelData.title}
rawModelData={rawModelData}
parseRawModelData={parseRawModelData}
editor={CountryScholarshipsEditor}
renderCore={renderCore}
coreClasses={classes}
outsideData={outsideData}
moduleInGroupInfos={{ isInGroup: true, invalidateGroup: () => this.props.invalidateData() }}
__apiAttr={this.props.countryId}
/>
))
}
</GenericGroupModule >
)
}
__apiAttr = { countryScholarships: "countryId" };
}
CountryScholarships.propTypes = {
classes: PropTypes.object.isRequired,
theme: PropTypes.object.isRequired,
countryId: PropTypes.string.isRequired,
country: PropTypes.object.isRequired,
countries: PropTypes.object.isRequired,
currencies: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => {
return {
countryScholarships: state.countryScholarships,
};
};
const mapDispatchToProps = (dispatch) => {
return {
fetchData: {
countryScholarships: (countryId) => dispatch(countryScholarshipsFetchData(countryId)),
},
invalidateData: (resetObj = false) => dispatch(countryScholarshipsInvalidated(true, resetObj))
};
};
export default compose(
withStyles(styles, { withTheme: true }),
connect(mapStateToProps, mapDispatchToProps)
)(CountryScholarships);
\ No newline at end of file
......@@ -75,7 +75,6 @@ class UniversityDri extends Module {
{
univDriItems.map((rawModelData) => (
<GenericModule
visible={this.props.visible}
buildTitle={(modelData) => modelData.title}
rawModelData={rawModelData}
parseRawModelData={parseRawModelData}
......
......@@ -95,7 +95,6 @@ class UniversityGeneral extends Module {
return (
<GenericModule
visible={this.props.visible}
buildTitle={() => "Présentation"}
rawModelData={univInfos}
parseRawModelData={parseRawModelData}
......
......@@ -91,7 +91,6 @@ class UniversityScholarships extends Module {
{
univScholarshipsItems.map((rawModelData) => (
<GenericModule
visible={this.props.visible}
buildTitle={(modelData) => modelData.title}
rawModelData={rawModelData}
parseRawModelData={parseRawModelData}
......@@ -117,6 +116,7 @@ UniversityScholarships.propTypes = {
theme: PropTypes.object.isRequired,
univId: PropTypes.string.isRequired,
universities: PropTypes.object.isRequired,
currencies: PropTypes.object.isRequired,
};
const mapStateToProps = (state) => {
......
......@@ -12,7 +12,7 @@ class Module extends MyComponent {
myComponentDidUpdate() {
this.fetchAbleProps.map((propKey) => {
if (this.props[propKey].invalidated && !this.props[propKey].isLoading) {
this.props.fetchData[propKey](this.props.univId);
this.performLoadProp(propKey);
}
})
}
......
import React from 'react';
import PropTypes from 'prop-types';
import Editor from './Editor';
const frequencyOptions = [
{ value: 'w', label: "Il s'agit du montant hebdomadaire" },
{ value: 'm', label: "Il s'agit du montant mensuel" },
{ value: 's', label: "Il s'agit du montant semestriel" },
{ value: 'y', label: "Il s'agit du montant annuel" },
{ value: 'o', label: "Il s'agit d'un montant donné une seule fois" }
]
class ScholarshipEditor extends Editor {
formHasError() {
let messages = Array();
const formData = this.getDataFromFields();
const { amount_min, amount_max } = formData;
console.log(formData);
if (amount_min !== null && amount_max !== null && amount_max < amount_min) {
messages.push("La logique voudrait que la borne supérieure de la bourse soit... supérieure à la borne inférieure.")
}
return this.buildError(messages);
}
renderEditor() {
return (
<div>
{this.renderObjModerationLevelField()}
{this.renderTitleField()}
{this.renderLinkedField()}
{this.renderTextField({
required: true,
label: "Présentation succincte",
maxLength: 200,
fieldMapping: 'type',
})}
{this.renderCurrencyField({ label: "Devise", required: false, fieldMapping: 'currency' })}
{this.renderNumberField({
label: "Borne inférieure du montant de la bourse",
minValue: 0,
fieldMapping: 'amount_min',
})}
{this.renderNumberField({
label: "Borne supérieure du montant de la bourse",
minValue: 0,
fieldMapping: 'amount_max',
})}
{this.renderSelectField({
label: "Fréquence de la bourse",
options: frequencyOptions,
fieldMapping: 'frequency',
})}
{this.renderMarkdownField({
label: "Autres avantages",
maxLength: 500,
formManager: this,
fieldMapping: 'other_advantages',
})}
{this.renderCommentField()}
{this.renderUsefulLinksField()}
</div>
)
}
}
ScholarshipEditor.propTypes = {
modelData: PropTypes.object.isRequired,
};
export default ScholarshipEditor;
\ No newline at end of file
import React from 'react';
import PropTypes from 'prop-types';
import __pick from 'lodash/pick';
import UnivContext from '../../shared/UnivContext';
class UnivInfoConsumer extends React.PureComponent {
render() {
const { add } = this.props;
return (
<UnivContext.Consumer>
{
value => (
<this.props.renderAndAddPropsTo {...__pick(value, add)} univId={value.univId} />
)
}
</UnivContext.Consumer>
)
}
}
UnivInfoConsumer.defaultProps = {
add: [''],
}
UnivInfoConsumer.propTypes = {
add: PropTypes.arrayOf(PropTypes.string).isRequired,
};
export default UnivInfoConsumer;
\ No newline at end of file
......@@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
import compose from 'recompose/compose';
import { connect } from "react-redux";
import __pick from 'lodash/pick';
import UnivContext from '../../shared/UnivContext';
import MyComponent from '../../MyComponent';
......@@ -16,56 +16,26 @@ import {
} from '../../../generated/actions';
class InfoProvider extends MyComponent {
class UnivInfoProvider extends MyComponent {
myRender() {
const { city, country } = this.getUnivCityAndCountry(this.props.univId);
const universities = this.getFetchedData('universities');
const countries = this.getFetchedData('countries');
const currencies = this.getFetchedData('currencies');
const { univId } = this.props,
countryId = country.id,
cityId = city.id;
let propsToAdd = { univId: this.props.univId, visible: this.props.visible };
if (this.props.add) {
this.props.add.map(
(key) => {
switch (key) {
case 'universities':
propsToAdd[key] = universities;
break;
case 'countries':
propsToAdd[key] = countries;
break;
case 'currencies':
propsToAdd[key] = currencies;
break;
case 'city':
propsToAdd[key] = city;
break;
case 'country':
propsToAdd[key] = country;
break;
case 'cityId':
propsToAdd[key] = city.id;
break;
case 'countryId':
propsToAdd[key] = country.id;
break;
default:
throw Error('Not supported.')
}
}
)
}
return (<this.props.renderAndAddPropsTo {...propsToAdd} />)
return (
<UnivContext.Provider value={{ univId, countryId, cityId, city, country, universities, countries, currencies }}>
{this.props.children}
</UnivContext.Provider>
)
}
}
InfoProvider.propTypes = {
UnivInfoProvider.propTypes = {
univId: PropTypes.string.isRequired,
add: PropTypes.arrayOf(PropTypes.string).isRequired,
};
const mapStateToProps = (state) => {
......@@ -93,4 +63,4 @@ const mapDispatchToProps = (dispatch) => {
export default compose(
connect(mapStateToProps, mapDispatchToProps)
)(InfoProvider);
\ No newline at end of file
)(UnivInfoProvider);
\ No newline at end of file
......@@ -12,7 +12,7 @@ import UniversitySemestersDates from '../modules/UniversitySemestersDates';
import UniversityDri from '../modules/UniversityDri';
import CountryDri from '../modules/CountryDri';
import withWidth, { isWidthUp } from '@material-ui/core/withWidth';
import InfoProvider from '../shared/InfoProvider';
import UnivInfoConsumer from '../shared/UnivInfoConsumer';
const styles = theme => ({
root1: {
......@@ -40,22 +40,19 @@ class GeneralInfoTab extends MyComponent {
<div style={{ flexGrow: 8, paddingRight: 2 * theme.spacing.unit }}>
<Grid container direction='column' >
<Grid item xs style={{ paddingBottom: 2 * theme.spacing.unit }} >
<InfoProvider
<UnivInfoConsumer
add={['city', 'country']}
univId={this.props.univId}
renderAndAddPropsTo={UniversityGeneral}
/>
</Grid>
<Grid item xs>
<InfoProvider
<UnivInfoConsumer
add={['universities']}
univId={this.props.univId}
renderAndAddPropsTo={UniversityDri}
/>
</Grid>
<Grid item xs>
<InfoProvider
univId={this.props.univId}
<UnivInfoConsumer
add={['countries', 'countryId']}
renderAndAddPropsTo={CountryDri}
/>
......@@ -65,7 +62,9 @@ class GeneralInfoTab extends MyComponent {
<div style={{ flexGrow: 6 }} >
<Grid container direction='column' >
<Grid item xs style={{ paddingBottom: 2 * theme.spacing.unit }}>
<UniversitySemestersDates visible={this.props.visible} univId={this.props.univId} />
<UnivInfoConsumer
renderAndAddPropsTo={UniversitySemestersDates}
/>
</Grid>
<Grid item xs>
{/* <GenericModule visible={this.props.visible} title={"Offres de départs"} automaticData={true} /> */}
......@@ -82,31 +81,30 @@ class GeneralInfoTab extends MyComponent {
<Grid container spacing={16} >
<Grid item xs={12}>
<InfoProvider
<UnivInfoConsumer
add={['city', 'country']}
univId={this.props.univId}
renderAndAddPropsTo={UniversityGeneral}
/>
</Grid>
<Grid item xs={12}>
<InfoProvider
univId={this.props.univId}
<UnivInfoConsumer
add={['universities']}
renderAndAddPropsTo={UniversityDri}
/>
</Grid>
<Grid item xs={12}>
<InfoProvider
<UnivInfoConsumer
add={['countries', 'countryId']}
univId={this.props.univId}
renderAndAddPropsTo={CountryDri}
/>
</Grid>
<Grid item xs={12}>
<UniversitySemestersDates visible={this.props.visible} univId={this.props.univId} />
<UnivInfoConsumer
renderAndAddPropsTo={UniversitySemestersDates}
/>
</Grid>
<Grid item xs={12}>
{/* <GenericModule visible={this.props.visible} title={"Offres de départs"} automaticData={true} /> */}