Commit 58094660 authored by Florent Chehab's avatar Florent Chehab

fixes(=>v0.9.1)

* increase UWSGI buffer size
* Fixed feedback invalidation on edit
* cleaner scholarships presentation
* Fixed missing arg in cron
* Fixed typos
* lighter empty feedbacks
* cleaner notifications

Closes #141 #140
parent 1e5f9d9f
Pipeline #42831 passed with stages
in 6 minutes and 26 seconds
......@@ -40,7 +40,7 @@ def update_utc_ent(num):
@timer(60 * 60, target="spooler") # run it every hour
@harakiri(60)
def update_extra_denormalization():
def update_extra_denormalization(num):
update_denormalized_univ_major_minor()
update_denormalized_univ_field()
......
......@@ -28,7 +28,7 @@ class NotifierImportantInformation extends CustomComponentForAPI {
el =>
<Notifier key={el.id}
message={el.message}
options={{variant: el.variant, autoHideDuration: 5000}}/>)}
options={{variant: el.variant, autoHideDuration: null}}/>)}
</>
);
}
......
......@@ -33,10 +33,10 @@ class TextField extends Field {
messages.push("Ce champ est requis mais il est vide.");
}
if (this.props.maxLength && value !== null && value.length > this.props.maxLength) {
messages.push("L'URL est trop long.");
messages.push("L'URL est trop longue.");
}
if (this.props.isUrl && value != "" && !isUrl(value)) {
messages.push("L'URL entrer n'est pas reconnu.");
messages.push("L'URL entrée n'est pas reconnue.");
}
if (this.props.isUrl && value != "" && this.props.urlExtensions.length > 0) {
if (!stringHasExtension(value, this.props.urlExtensions)) {
......
......@@ -50,13 +50,13 @@ class UsefulLinksField extends Field {
if (hasEmpty) { messages.push("Les deux champs url et description doivent être saisis."); }
const hasInvalidUrl = usefulLinks.some(el => !isUrl(el.url));
if (hasInvalidUrl) { messages.push("Un url n'est pas reconnu dans le formulaire."); }
if (hasInvalidUrl) { messages.push("Une URL n'est pas reconnu dans le formulaire."); }
const hasTooLongUrlOrDesc = usefulLinks.some(el =>
(el.url && el.url.length > this.props.urlMaxLength)
|| (el.description && el.description.length > this.props.descriptionMaxLength)
);
if (hasTooLongUrlOrDesc) { messages.push("Un url ou une description est trop longue."); }
if (hasTooLongUrlOrDesc) { messages.push("Une URL ou une description est trop longue."); }
return new CustomError(messages);
}
......
......@@ -15,7 +15,7 @@ function renderCore(rawModelData, classes, outsideData) {
<>
{
comment.length === 0 ?
<Typography><em>Aucune information n'est disponible... contribuez ! 😉</em></Typography>
<Typography variant={"caption"}><em>Aucune information n'est disponible... contribuez ! 😉</em></Typography>
:
<TruncatedMarkdown source={comment}/>
}
......
......@@ -94,11 +94,11 @@ export function CourseFeedbackCore(props) {
languageName ?
<Typography>Cours enseigné en {LanguagesHelper.getLanguageName(languageCode)}.</Typography>
:
<Typography>La langue dans lequel ce cours est enseigné n'est pas connue.</Typography>
<></>
}
{
untouched ?
<Typography><em>Aucun avis saisi.</em></Typography>
<></>
:
<>
<GridLine>
......
......@@ -96,7 +96,11 @@ const mapDispatchToProps = (dispatch) => {
api: {
courseFeedbacks: (params) => dispatch(getActions("courseFeedbacks").readAll(params))
},
invalidateData: () => dispatch(getActions("courseFeedbacks").invalidateAll())
invalidateData: () => {
dispatch(getActions("courseFeedbacks").invalidateAll());
// also invalidate all to make sure all the site pages are consistent
dispatch(getActions("exchangeFeedbacks").invalidateAll());
}
};
};
......
......@@ -43,6 +43,8 @@ class EditModuleGeneralFeedback extends CustomComponentForAPI {
editor={GeneralFeedbackEditor}
renderCore={renderCore}
coreClasses={classes}
// small hack to invalidate data
moduleInGroupInfos={{isInGroup: true, invalidateGroup: () => this.props.invalidateData()}}
/>
);
}
......@@ -64,7 +66,11 @@ const mapDispatchToProps = (dispatch) => {
api: {
exchangeFeedback: (params) => dispatch(getActions("exchangeFeedbacks").readOne(params))
},
invalidateData: () => dispatch(getActions("exchangeFeedbacks").invalidateOne())
invalidateData: () => {
dispatch(getActions("exchangeFeedbacks").invalidateOne());
// also invalidate all to make sure all the site pages are consistent
dispatch(getActions("exchangeFeedbacks").invalidateAll());
}
};
};
......
import React, {Component} from "react";
import PropTypes from "prop-types";
import withStyles from "@material-ui/core/styles/withStyles";
import compose from "recompose/compose";
import React from "react";
import Grid from "@material-ui/core/Grid";
......@@ -11,45 +8,26 @@ import CountryScholarships from "../modules/CountryScholarships";
/**
* Tab on the university page containing information related to scholarship
*
* @class ScholarshipsTab
* @extends {Component}
*/
class ScholarshipsTab extends Component {
function ScholarshipsTab() {
render() {
const { classes } = this.props;
return (
<div className={classes.root}>
<Grid container spacing={2} >
<Grid item xs={12}>
<UniversityScholarships/>
</Grid>
<Grid item xs={12}>
<CountryScholarships/>
</Grid>
return (
<>
<Grid container spacing={3}>
<Grid item md={6} xs={12}>
<UniversityScholarships/>
</Grid>
<Grid item md={6} xs={12}>
<CountryScholarships/>
</Grid>
</div>
);
}
</Grid>
</>
);
}
ScholarshipsTab.propTypes = {
classes: PropTypes.object.isRequired,
};
const styles = {
root: {
display: "flex",
width: "90%",
marginLeft: "auto",
marginRight: "auto"
},
};
export default compose(
withStyles(styles),
)(ScholarshipsTab);
ScholarshipsTab.propTypes = {};
export default ScholarshipsTab;
......@@ -17,7 +17,7 @@ const deleteMessage = `
# Attention
* Cette action entrainera la suppression de toute vos données sous licence « REX-DRI Private »
(login UTC, adresses mails, pseudos, listes privée, réglages personnels, etc.),
(login UTC, adresses mails, pseudos, listes privées, réglages personnels, etc.),
* Afin de satisfaire les exigences de la licence « REX-DRI BY », votre nom et prénom seront conservés,
* Pour toute demande supplémentaire, merci de contacter le SIMDE.
* La suppression de votre compte sera effective **sous 48h**.
......@@ -26,7 +26,7 @@ const deleteMessage = `
# Rappel
* Cette action sera de toute manière automatiquement réalisée passer 5 ans d'inactivité de votre compte.
* Cette action sera de toute manière automatiquement réalisée après 5 ans d'inactivité de votre compte.
*Si vous souhaitez définitivement supprimer votre compte, cliquez sur le bouton ci-dessous.*
`;
......
......@@ -164,7 +164,7 @@ class UserInfo extends CustomComponentForAPI {
</>
:
<Typography variant="caption">
Aucune addresse email secondaire n'est disponible.
Aucune adresse email secondaire n'est disponible.
</Typography>
}
......
......@@ -4,39 +4,86 @@ import {Provider} from "react-redux";
import {BrowserRouter as Router} from "react-router-dom";
import {SnackbarProvider} from "notistack"; // provider to easily handle notifications across the app
import Button from "@material-ui/core/Button";
import green from "@material-ui/core/colors/green";
import amber from "@material-ui/core/colors/amber";
import store from "../redux/store";
import App from "../components/app/App";
import ThemeProvider from "../components/common/theme/ThemeProvider";
import CssBaseline from "@material-ui/core/CssBaseline";
import {makeStyles} from "@material-ui/styles";
/**
* Get the correct style for a color of notistack (not enough contrast some times with default settings)
* @param color
* @param theme
*/
function getStyle(color, theme) {
return {
backgroundColor: color,
color: theme.palette.getContrastText(color),
};
}
const useStylesNotiStack = makeStyles(theme => ({
base: {
...theme.typography.body2
},
variantSuccess: {
...getStyle(green[600], theme),
},
variantError: {
...getStyle(theme.palette.error.dark, theme),
},
variantInfo: {
...getStyle("#2979ff", theme),
},
variantWarning: {
...getStyle(amber[700], theme),
},
}));
function SubEntry() {
// to ba able to use the theme from here
const classesNotistack = useStylesNotiStack();
return (
<SnackbarProvider
maxSnack={3}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
action={[
<Button key={0} color="inherit" size="small">
{"Fermer"}
</Button>
]}
classes={{...classesNotistack}}
>
<>
<CssBaseline/>
<App/>
</>
</SnackbarProvider>
);
}
function MainReactEntry() {
return (
<Provider store={store}>
{/* <React.StrictMode> */}
<ThemeProvider>
<Router>
<SubEntry/>
</Router>
</ThemeProvider>
{/* </React.StrictMode> */}
</Provider>
);
}
const MainReactEntry = () => (
<Provider store={store}>
{/* <React.StrictMode> */}
<ThemeProvider>
<Router>
<SnackbarProvider
maxSnack={3}
anchorOrigin={{
vertical: "top",
horizontal: "right",
}}
action={[
<Button key={0} color="secondary" size="small">
{"Fermer"}
</Button>
]}
>
<>
<CssBaseline/>
<App/>
</>
</SnackbarProvider>
</Router>
</ThemeProvider>
{/* </React.StrictMode> */}
</Provider>
);
const wrapper = document.getElementById("app");
......
......@@ -28,6 +28,9 @@ max-worker-lifetime = 600 # reload workers at least every 10 minutes
# daemonize = /var/log/uwsgi/rex-dri.log # background the process & log TODO not working
pidfile = /tmp/project-master.pid # create a pidfile
# Some users had too many cookies
buffer-size = 6144
# Cron setup
spooler = /usr/src/spooler
; load the task.py module
......
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