208 lines
5.9 KiB
TypeScript
208 lines
5.9 KiB
TypeScript
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" style={{width: '100%'}}>
|
|
{
|
|
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 mb-1 mt-1">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);
|
|
} |