Enregistrement et affichage d'un flux d'évènements
- Ajout d'une nouvelle entité "Event" - Affichage d'une "timeline" sur le tableau de bord - Création semi-automatique des évènements lors des modifications par les utilisateurs
This commit is contained in:
208
client/src/components/Timeline.tsx
Normal file
208
client/src/components/Timeline.tsx
Normal file
@ -0,0 +1,208 @@
|
||||
import React, { FunctionComponent } from "react";
|
||||
import { formatDate } from "../util/date";
|
||||
import { Event } from "../types/event";
|
||||
import { Link } from "react-router-dom";
|
||||
import { WorkgroupLink } from "./WorkgroupLink";
|
||||
import { DecisioSupportFileLink } from "./DecisionSupportFileLink";
|
||||
|
||||
export interface TimelineProps {
|
||||
events?: Event[]
|
||||
}
|
||||
|
||||
export const Timeline: FunctionComponent<TimelineProps> = ({ events }) => {
|
||||
events = debounceEvents(events) || [];
|
||||
return (
|
||||
<React.Fragment>
|
||||
<div className="timeline">
|
||||
{
|
||||
events.map(evt => {
|
||||
return (
|
||||
<div key={evt.id} className="timeline-item">
|
||||
{renderEventMarker(evt)}
|
||||
<div className="timeline-content">
|
||||
<p className="heading">{formatDate(evt.createdAt)}</p>
|
||||
{renderEventContent(evt)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})
|
||||
}
|
||||
{
|
||||
events.length === 0 ?
|
||||
<p className="has-text-centered is-italic">Aucun évènement.</p> :
|
||||
null
|
||||
}
|
||||
</div>
|
||||
</React.Fragment>
|
||||
);
|
||||
}
|
||||
|
||||
function debounceEvents(events: Event[]): Event[] {
|
||||
const debounced = [];
|
||||
for(let evt: Event, i = 0; (evt = events[i]); ++i) {
|
||||
const prev = i > 0 ? events[i-1] : null;
|
||||
|
||||
if (!prev) {
|
||||
debounced.push(evt);
|
||||
continue;
|
||||
}
|
||||
|
||||
const isSame = evt.objectId === prev.objectId &&
|
||||
evt.objectType === prev.objectType &&
|
||||
evt.type === prev.type &&
|
||||
evt.user.id === prev.user.id
|
||||
;
|
||||
|
||||
if (isSame) continue;
|
||||
|
||||
debounced.push(evt);
|
||||
}
|
||||
|
||||
return debounced;
|
||||
}
|
||||
|
||||
const eventMarkerMap = {
|
||||
"closed": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-danger">
|
||||
<i className="fa fa-times"></i>
|
||||
</div>
|
||||
),
|
||||
"created": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-success">
|
||||
<i className="fa fa-plus"></i>
|
||||
</div>
|
||||
),
|
||||
"updated": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-info">
|
||||
<i className="fa fa-pen"></i>
|
||||
</div>
|
||||
),
|
||||
"title-changed": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-info">
|
||||
<i className="fa fa-pen"></i>
|
||||
</div>
|
||||
),
|
||||
"status-changed": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-primary">
|
||||
<i className="fa fa-star"></i>
|
||||
</div>
|
||||
),
|
||||
"joined": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-info">
|
||||
<i className="fa fa-users"></i>
|
||||
</div>
|
||||
),
|
||||
"leaved": (evt:Event) => (
|
||||
<div className="timeline-marker is-icon is-warning">
|
||||
<i className="fas fa-users-slash"></i>
|
||||
</div>
|
||||
),
|
||||
}
|
||||
|
||||
function renderEventMarker(evt: Event) {
|
||||
const render = eventMarkerMap[evt.type];
|
||||
if (!render) return ( <div className="timeline-marker"></div> );
|
||||
return render(evt);
|
||||
}
|
||||
|
||||
const eventContentMap = {
|
||||
"created": {
|
||||
"workgroup": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a créé le groupe de travail `}</span>
|
||||
"<WorkgroupLink workgroupId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
"dsf": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a créé le dossier d'aide à la décision `}</span>
|
||||
"<DecisioSupportFileLink decisionSupportFileId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
},
|
||||
"title-changed": {
|
||||
"dsf": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a modifié le titre du dossier d'aide à la décision `}</span>
|
||||
"<DecisioSupportFileLink decisionSupportFileId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
},
|
||||
"status-changed": {
|
||||
"dsf": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a modifié le statut du dossier d'aide à la décision `}</span>
|
||||
"<DecisioSupportFileLink decisionSupportFileId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
)
|
||||
}
|
||||
},
|
||||
"joined": {
|
||||
"workgroup": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a rejoint le groupe de travail `}</span>
|
||||
"<WorkgroupLink workgroupId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
},
|
||||
"updated": {
|
||||
"workgroup": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a mis à jour le groupe de travail `}</span>
|
||||
"<WorkgroupLink workgroupId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
"dsf": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a modifié le dossier d'aide à la décision `}</span>
|
||||
"<DecisioSupportFileLink decisionSupportFileId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
},
|
||||
"leaved": {
|
||||
"workgroup": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a quitté le groupe de travail `}</span>
|
||||
"<WorkgroupLink workgroupId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
},
|
||||
"closed": {
|
||||
"workgroup": (evt:Event) => {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<span>{`${evt.user.name ? evt.user.name : evt.user.email} a clos le groupe de travail `}</span>
|
||||
"<WorkgroupLink workgroupId={evt.objectId} />".
|
||||
</React.Fragment>
|
||||
);
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
function renderEventContent(evt: Event) {
|
||||
const eventTypeMap = eventContentMap[evt.type];
|
||||
const render = eventTypeMap && eventTypeMap[evt.objectType];
|
||||
|
||||
if (!eventTypeMap || !render) {
|
||||
return (
|
||||
<span className="is-italic">{`Type d'évènement "${evt.type}/${evt.objectType}" inconnu.`}</span>
|
||||
);
|
||||
}
|
||||
|
||||
return render(evt);
|
||||
}
|
Reference in New Issue
Block a user