Commit a42e8bd3 authored by Florent Chehab's avatar Florent Chehab

done

parent 4ccf5a3b
Pipeline #42348 failed with stages
in 4 minutes and 23 seconds
......@@ -53,6 +53,7 @@ from backend_app.serializers import (
)
from backend_app.settings.defaults import OBJ_MODERATION_PERMISSIONS
from base_app.models import UserViewset, User, SiteInformationViewSet
from external_data.models import ExternalDataUpdateInfo
class CourseViewSet(BaseModelViewSet):
......@@ -168,6 +169,33 @@ class AppModerationStatusViewSet(ViewSet):
)
class LatestUpdateExternalDataViewSet(ViewSet):
"""
Viewset to fetch the latest update dates of the external data
"""
# Since AppModerationStatusViewSet doesn't inherit from BaseModelViewSet
# We need to link here the correct permissions
permission_classes = (ReadOnly,)
end_point_route = "externalDataUpdateInfo"
def list(self, request):
objects = (
ExternalDataUpdateInfo.objects.all()
.order_by("source", "-timestamp")
.distinct("source")
)
return Response(
list(
map(
lambda obj: dict(timestamp=obj.timestamp, source=obj.source),
objects,
)
)
)
class LogFrontendErrorsViewSet(ViewSet):
"""
Viewset to handle the logging of errors coming from the frontend.
......@@ -290,6 +318,7 @@ class RecommendationListChangeFollowerViewSet(ViewSet):
ALL_API_VIEW_VIEWSETS = [
AppModerationStatusViewSet,
LatestUpdateExternalDataViewSet,
LogFrontendErrorsViewSet,
BannedUserViewSet,
RecommendationListChangeFollowerViewSet,
......
from datetime import datetime
from typing import List
from django.utils import timezone
from django.contrib.auth.models import AbstractUser
from django.core.exceptions import ValidationError
......@@ -166,7 +167,7 @@ class SiteInformationViewSet(BaseModelViewSet):
def get_queryset(self):
get = self.request.GET
if "now" in get.keys():
now = datetime.now()
now = timezone.now()
return SiteInformation.objects.filter(
Q(start__lte=now) & (Q(end__isnull=True) | Q(end__gte=now))
)
......
import React from "react";
import {connect} from "react-redux";
import CustomComponentForAPI from "../common/CustomComponentForAPI";
import {compose} from "recompose";
import getActions from "../../redux/api/getActions";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListItemText from "@material-ui/core/ListItemText";
import {toDateFr} from "../../utils/dateToFr";
import Typography from "@material-ui/core/Typography";
function getLabel(source) {
if (source === "fixer") return "Données concernant les taux de change (Fixer)";
return "Donnée externe non connue";
}
/**
* Class to render notifications for important stuff
*
* @class ExternalDataUpdateInfo
* @extends {CustomComponentForAPI}
* @extends React.Component
*/
class ExternalDataUpdateInfo extends CustomComponentForAPI {
customRender() {
const updateList = this.getLatestReadData("updates");
updateList.sort((a, b) => a.source.localeCompare(b.source));
if (updateList.length > 0) {
return (
<List aria-label="List of updates">
{
updateList.map(
el =>
<ListItem key={el.source}>
<ListItemText primary={getLabel(el.source)} secondary={toDateFr(el.timestamp)}/>
</ListItem>
)
}
</List>
);
} else {
return <Typography variant={"caption"} display={"block"}>Aucune mise-à-jour ne semble avoir été
réalisée.</Typography>;
}
}
}
ExternalDataUpdateInfo.propTypes = {};
ExternalDataUpdateInfo.defaultProps = {};
const mapStateToProps = (state) => {
return {
updates: state.api.externalDataUpdateInfoAll,
};
};
const mapDispatchToProps = (dispatch) => {
return {
api: {
updates: () => dispatch(getActions("externalDataUpdateInfo").readAll()),
},
};
};
export default compose(
connect(mapStateToProps, mapDispatchToProps),
)(ExternalDataUpdateInfo);
......@@ -16,24 +16,9 @@ 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";
import {toDateFr} from "../../utils/dateToFr";
/**
* 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/>,
......@@ -50,7 +35,6 @@ const INFORMATION_ICONS = {
* @extends React.Component
*/
class InformationList extends CustomComponentForAPI {
dateUtil = new LocalizedUtils();
customRender() {
const informationList = this.getLatestReadData("information")
......@@ -67,7 +51,7 @@ class InformationList extends CustomComponentForAPI {
<ListItemIcon>
{INFORMATION_ICONS[el.variant]}
</ListItemIcon>
<ListItemText primary={el.message} secondary={this.dateUtil.getDateText(parseISO(el.start))}/>
<ListItemText primary={el.message} secondary={toDateFr(el.start)}/>
</ListItem>
)
}
......@@ -77,7 +61,6 @@ class InformationList extends CustomComponentForAPI {
}
InformationList.propTypes = {
classes: PropTypes.object.isRequired,
includeVariants: PropTypes.arrayOf(PropTypes.string.isRequired).isRequired,
};
......@@ -99,10 +82,8 @@ const mapDispatchToProps = (dispatch) => {
};
};
const styles = theme => ({});
export default compose(
withStyles(styles),
withSnackbar,
connect(mapStateToProps, mapDispatchToProps),
withErrorBoundary(),
......
......@@ -7,6 +7,7 @@ import {withPaddedPaper} from "./shared";
import InformationList from "../app/InformationList";
import CustomLink from "../common/CustomLink";
import {APP_ROUTES} from "../../config/appRoutes";
import ExternalDataUpdateInfo from "../app/ExternalDataUpdateInfo";
const sourceIntro = `
**REX-DRI** c'est LA plateforme de capitalisation sur les départs à l'étranger à l'UTC.
......@@ -49,10 +50,6 @@ function PageHome() {
Focus sur le markdown
</Typography>
<Markdown source={sourceFocusMarkdown}/>
<Typography variant="h4">
Informations dynamiques
</Typography>
<InformationList/>
<Typography variant="h4">
Amélioration continue
</Typography>
......@@ -61,9 +58,15 @@ function PageHome() {
d'informations <CustomLink to={APP_ROUTES.aboutProject}>ici</CustomLink>.
</Typography>
<Typography variant="h4">
Informations dynamiques
</Typography>
<Typography variant={"h5"}>Nouvelles</Typography>
<InformationList/>
<Typography variant="h5" display={"inline"}>
Status des données importées
</Typography>
<Typography variant={"caption"} display={"inline"}> (Dernières mise à jour)</Typography>
<ExternalDataUpdateInfo/>
</>
);
}
......
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 LocalizedUtils
* @extends {DateFnsUtils}
*/
class LocalizedUtils extends DateFnsUtils {
getDateText(date) {
return format(date, "d MMM yyyy, HH:mm", {locale: frLocale});
}
}
const util = new LocalizedUtils();
export function toDateFr(dateIso) {
return util.getDateText(parseISO(dateIso));
}
\ No newline at end of file
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