Commit 580fd5d0 authored by Florent Chehab's avatar Florent Chehab

Front wip

parent 7a7776d9
{% load static %}
<!DOCTYPE html>
<html style="font-size:14">
<html style="font-size:13;">
<head>
<meta
......@@ -30,7 +30,7 @@
</head>
<body>
<div id="app" class="columns">
<div id="app">
<!-- React -->
</div>
</body>
......
......@@ -26,6 +26,8 @@ import {PageCgu, PageRgpd} from "../pages/PagesRgpdCgu";
import PageNotFound from "../pages/PageNotFound";
import PageEditPreviousExchanges from "../pages/PageEditExchangeFeedbacks";
import PageMyExchanges from "../pages/PageMyExchanges";
import NotifierImportantInformation from "./NotifierImportantInformation";
import FooterImportantInformation from "./FooterImportantInformation";
/**
* @class App
......@@ -35,26 +37,30 @@ import PageMyExchanges from "../pages/PageMyExchanges";
class App extends CustomComponentForAPI {
customRender() {
return (
<MainAppFrame>
<FullScreenDialog/>
<main>
<Switch>
<Route exact path={APP_ROUTES.base} component={PageHome}/>
<Route path={APP_ROUTES.search} component={PageSearch}/>
<Route path={APP_ROUTES.map} component={PageMap}/>
<Route path={APP_ROUTES.themeSettings} component={PageSettings}/>
<Route path={APP_ROUTES.listsWithParams} component={PageLists}/>
<Route path={APP_ROUTES.universityWithParams} component={PageUniversity}/>
<Route path={APP_ROUTES.myExchanges} component={PageMyExchanges}/>
<Route path={APP_ROUTES.editPreviousExchangeWithParams} component={PageEditPreviousExchanges}/>
<Route path={APP_ROUTES.userWithParams} component={PageUser}/>
<Route path={APP_ROUTES.aboutProject} component={PageAboutProject}/>
<Route path={APP_ROUTES.aboutRgpd} component={PageRgpd}/>
<Route path={APP_ROUTES.aboutCgu} component={PageCgu}/>
<Route component={PageNotFound}/>
</Switch>
</main>
</MainAppFrame>
<div style={{display: "flex", flexDirection: "column", justifyItems: "flex-end", minHeight: "100vh"}}>
<MainAppFrame>
<FullScreenDialog/>
<NotifierImportantInformation/>
<main>
<Switch>
<Route exact path={APP_ROUTES.base} component={PageHome}/>
<Route path={APP_ROUTES.search} component={PageSearch}/>
<Route path={APP_ROUTES.map} component={PageMap}/>
<Route path={APP_ROUTES.themeSettings} component={PageSettings}/>
<Route path={APP_ROUTES.listsWithParams} component={PageLists}/>
<Route path={APP_ROUTES.universityWithParams} component={PageUniversity}/>
<Route path={APP_ROUTES.myExchanges} component={PageMyExchanges}/>
<Route path={APP_ROUTES.editPreviousExchangeWithParams} component={PageEditPreviousExchanges}/>
<Route path={APP_ROUTES.userWithParams} component={PageUser}/>
<Route path={APP_ROUTES.aboutProject} component={PageAboutProject}/>
<Route path={APP_ROUTES.aboutRgpd} component={PageRgpd}/>
<Route path={APP_ROUTES.aboutCgu} component={PageCgu}/>
<Route component={PageNotFound}/>
</Switch>
</main>
</MainAppFrame>
<FooterImportantInformation/>
</div>
);
}
}
......
import React from "react";
import Divider from "@material-ui/core/Divider";
import {makeStyles} from "@material-ui/styles";
import PropTypes from "prop-types";
import InformationList from "./InformationList";
import {withRouter} from "react-router-dom";
import {APP_ROUTES} from "../../config/appRoutes";
const useStyles = makeStyles(theme => ({
divider: {
marginTop: theme.spacing(4),
marginBottom: theme.spacing(0),
paddingBottom: theme.spacing(2),
color: theme.palette.text.secondary
}
}));
function FooterImportantInformation(props) {
const classes = useStyles();
// Don't display it on the home page
if (props.location.pathname === APP_ROUTES.base) {
return <></>;
}
return (
<footer>
<Divider className={classes.divider}/>
<InformationList includeVariants={["warning", "error"]}/>
</footer>
);
}
FooterImportantInformation.propTypes = {
location: PropTypes.shape({
pathname: PropTypes.string.isRequired,
}).isRequired,
};
export default withRouter(FooterImportantInformation);
import React from "react";
import {connect} from "react-redux";
import CustomComponentForAPI from "../common/CustomComponentForAPI";
import {compose} from "recompose";
import {withErrorBoundary} from "../common/ErrorBoundary";
import ErrorIcon from "@material-ui/icons/Error";
import StartIcon from "@material-ui/icons/StarTwoTone";
import InfoIcon from "@material-ui/icons/Info";
import WarningIcon from "@material-ui/icons/Warning";
import getActions from "../../redux/api/getActions";
import {withSnackbar} from "notistack";
import {RequestParams} from "../../redux/api/RequestParams";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemIcon from "@material-ui/core/ListItemIcon";
import ListItemText from "@material-ui/core/ListItemText";
import {withStyles} from "@material-ui/styles";
import PropTypes from "prop-types";
import DateFnsUtils from "@date-io/date-fns";
import format from "date-fns/format";
import parseISO from "date-fns/parseISO";
import frLocale from "date-fns/locale/fr";
/**
* Class to customize the header of the date selection box
*
* @class LocalizedUtils
* @extends {DateFnsUtils}
*/
class LocalizedUtils extends DateFnsUtils {
getDateText(date) {
return format(date, "d MMM yyyy, HH:mm", {locale: frLocale});
}
}
const INFORMATION_ICONS = {
success: <StartIcon/>,
info: <InfoIcon/>,
error: <ErrorIcon/>,
warning: <WarningIcon/>,
};
/**
* Class to render notifications for important stuff
*
* @class InformationList
* @extends {CustomComponentForAPI}
* @extends React.Component
*/
class InformationList extends CustomComponentForAPI {
dateUtil = new LocalizedUtils();
customRender() {
const informationList = this.getLatestReadData("information")
.filter(({variant}) => this.props.includeVariants.includes(variant));
informationList.sort((a, b) => -a.start.localeCompare(b.start));
return (
<List aria-label="List of information">
{
informationList.map(
el =>
<ListItem key={el.id}>
<ListItemIcon>
{INFORMATION_ICONS[el.variant]}
</ListItemIcon>
<ListItemText primary={el.message} secondary={this.dateUtil.getDateText(parseISO(el.start))}/>
</ListItem>
)
}
</List>
);
}
}
InformationList.propTypes = {
classes: PropTypes.object.isRequired,
includeVariants: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired,
};
InformationList.defaultProps = {
includeVariants: ["warning", "error", "info", "success"]
};
const mapStateToProps = (state) => {
return {
information: state.api.informationAll,
};
};
const mapDispatchToProps = (dispatch) => {
return {
api: {
information: () => dispatch(getActions("information").readAll(RequestParams.Builder.withQueryParam("now", "true").build())),
},
};
};
const styles = theme => ({});
export default compose(
withStyles(styles),
withSnackbar,
connect(mapStateToProps, mapDispatchToProps),
withErrorBoundary(),
)(InformationList);
import React from "react";
import {connect} from "react-redux";
import CustomComponentForAPI from "../common/CustomComponentForAPI";
import {compose} from "recompose";
import {withErrorBoundary} from "../common/ErrorBoundary";
import getActions from "../../redux/api/getActions";
import {withSnackbar} from "notistack";
import Notifier from "../common/Notifier";
import {RequestParams} from "../../redux/api/RequestParams";
/**
* Class to create notifications for important stuff on start up
*
* @class NotifierImportantInformation
* @extends {CustomComponentForAPI}
* @extends React.Component
*/
class NotifierImportantInformation extends CustomComponentForAPI {
customRender() {
const informationList = this.getLatestReadData("information"),
importantInformationList = informationList.filter(({variant}) => variant !== "info"),
hasImportantInformation = importantInformationList.length > 0;
if (hasImportantInformation) {
return (
<>
{importantInformationList.map(
el =>
<Notifier key={el.id}
message={el.message}
options={{variant: el.variant, autoHideDuration: 5000}}/>)}
</>
);
}
return <></>;
}
}
NotifierImportantInformation.propTypes = {};
const mapStateToProps = (state) => {
return {
information: state.api.informationAll,
};
};
const mapDispatchToProps = (dispatch) => {
return {
api: {
information: () => dispatch(getActions("information").readAll(RequestParams.Builder.withQueryParam("now", "true").build())),
},
};
};
export default compose(
withSnackbar,
connect(mapStateToProps, mapDispatchToProps),
withErrorBoundary(),
)(NotifierImportantInformation);
......@@ -4,30 +4,16 @@ import {withErrorBoundary} from "../common/ErrorBoundary";
import Typography from "@material-ui/core/Typography";
import Markdown from "../common/markdown/Markdown";
import {withPaddedPaper} from "./shared";
import InformationList from "../app/InformationList";
const source = `
**Ce service est à l'heure actuelle au stade de version _alpha_ afin de montrer certaines fonctionnalités. Les données seront vraisemblablement remises à zéro lors du passage à la phase _beta_ (quand toutes les fonctionnalités seront en place).**
Si vous trouvez des bugs ou si vous avez des suggestions, merci de les signaler [ici](https://gitlab.utc.fr/chehabfl/outgoing_rex/issues) ou par mail à l'adresse [florent.chehab@etu.utc.fr](mailto:florent.chehab@etu.utc.fr).
Pour rendre plus parlantes certaines fonctionnalités liées à la modération (grandement paramétrable) des informations, durant cette phase _alpha_ vous pouvez rejoindre les différents groupes d'accès tout seul :
- Pour rejoindre le groupe des modérateurs, cliquez [ici](/role_change/moderator/)
- Pour rejoindre le groupe d'accès « DRI », cliquez [ici](/role_change/dri/)
- Pour rejoindre le groupe _classique_, cliquez [ici](/role_change/normal/)
## Amélioration / Contribution
Les données actuellement présente sur la plateforme sont extraites d'un document récapitulant les destinations offertes aux GI il y a quelques semestre de cela ; et elles sont complétés par mes ajouts personnels (voir en particulier pour l'EPFL).
## Fonctionnalités manquantes
Voici les fonctionnalités qui seront rajoutées « prochainement » :
- Possibilité de filtrer les universités sur la page avec la carte ou celle avec la recherche. Les critères seront (ou devraient être) : destinations disponibles à tel semestre, destinations où sont partis des étudiants de telles branches/filières, destinations ouvertes à des étudiants de telles branches/filières, niveau de langue requis, etc.
- Possibilité de faire des listes commentées avec des universités et de les partager (ou non).
- Ajout des autres modules sur les pages des universités.
- Gestion des retours des étudiants sur leurs départs.
- Meilleure compatibilité avec les mobiles.
NB : les images de couverture sur les pages des universités seront aussi différentes ! (actuellement cet élément n'est pas _connecté_ au serveur)
--------
......@@ -39,15 +25,6 @@ Les objectifs de ce service sont :
- Regrouper les informations sur les départs à l'étranger réalisés par les étudiants de l'UTC ;
- Les renders accessibles et commensurables.
Âge des données de l'UTC :
| **Feature** | **Support** |
| ------ | ----------- |
| Ancien départs | ✔ |
| Départs possibles | ✔ |
| Informatio sur les universités | ✔ |
## Autre fun feature
You can format money: \`:100CHF:\` => :100CHF:
......@@ -66,6 +43,14 @@ function PageHome() {
Bienvenue sur <em><b>REX-DRI</b></em> !
</Typography>
<Markdown source={source} headingOffset={2} />
<Typography variant="h4">
Informations dynamiques
</Typography>
<InformationList/>
<Typography variant="h4">
Status des données importées
</Typography>
</>
);
}
......
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