Skip to content

Commit

Permalink
Events matrix.
Browse files Browse the repository at this point in the history
  • Loading branch information
Francisco del Castillo committed Oct 7, 2024
1 parent 20ebc50 commit a3abfe2
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 13 deletions.
25 changes: 24 additions & 1 deletion client/src/components/EventCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { setPagination } from "actions"
import ButtonToggleGroup from "components/ButtonToggleGroup"
import EventCalendar from "components/EventCalendar"
import EventMap from "components/EventMap"
import EventMatrix from "components/EventMatrix"
import EventSummary from "components/EventSummary"
import EventTable from "components/EventTable"
import {
Expand All @@ -17,6 +18,7 @@ export const FORMAT_CALENDAR = "calendar"
export const FORMAT_MAP = "map"
export const FORMAT_SUMMARY = "summary"
export const FORMAT_TABLE = "table"
export const FORMAT_MATRIX = "matrix"

const EventCollection = ({
pageDispatchers,
Expand Down Expand Up @@ -65,6 +67,11 @@ const EventCollection = ({
Map
</Button>
)}
{viewFormats.includes(FORMAT_MATRIX) && (
<Button value={FORMAT_MATRIX} variant="outline-secondary">
Matrix
</Button>
)}
</ButtonToggleGroup>
</>
)}
Expand Down Expand Up @@ -110,6 +117,16 @@ const EventCollection = ({
marginBottom={marginBottom}
/>
)}
{viewFormat === FORMAT_MATRIX && (
<EventMatrix
pageDispatchers={pageDispatchers}
paginationKey={paginationKey}
pagination={pagination}
setPagination={setPagination}
queryParams={queryParams}
setTotalCount={setTotalCount}
/>
)}
</div>
</div>
</div>
Expand All @@ -131,7 +148,13 @@ EventCollection.propTypes = {
}

EventCollection.defaultProps = {
viewFormats: [FORMAT_TABLE, FORMAT_SUMMARY, FORMAT_CALENDAR, FORMAT_MAP]
viewFormats: [
FORMAT_TABLE,
FORMAT_SUMMARY,
FORMAT_CALENDAR,
FORMAT_MAP,
FORMAT_MATRIX
]
}

const mapDispatchToProps = (dispatch, ownProps) => {
Expand Down
234 changes: 234 additions & 0 deletions client/src/components/EventMatrix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,234 @@
import { Icon } from "@blueprintjs/core"
import { IconNames } from "@blueprintjs/icons"
import API from "api"
import LinkTo from "components/LinkTo"
import Messages from "components/Messages"
import { mapPageDispatchersToProps } from "components/Page"
import { Event } from "models"
import moment from "moment/moment"
import PropTypes from "prop-types"
import React, { useEffect, useState } from "react"
import { Button, Table } from "react-bootstrap"
import { connect } from "react-redux"
import Settings from "settings"

const dayNames = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday"
]

const EventMatrix = props => {
const [weekNumber, setWeekNumber] = useState(null)
const [startDay, setStartDay] = useState(getFirstDayOfCurrentWeek())
const [events, setEvents] = useState([])
const [tasks, setTasks] = useState([])
const [weekDays, setWeekDays] = useState([])
const [error, setError] = useState(null)

useEffect(() => {
async function fetchEvents(eventQuery) {
try {
return await API.query(Event.getEventListQuery, {
eventQuery
})
} catch (error) {
setError(error)
}
}

// Determine date range
const week = []
for (let i = 0; i <= 6; i++) {
week.push(moment(startDay).add(i, "days").toDate())
}
setWeekDays(week)
setWeekNumber(moment(startDay).week())

// Get the events
const eventQuery = Object.assign({}, props.queryParams)
eventQuery.startDate = week[0]
eventQuery.endDate = week[6]
eventQuery.onlyWithTasks = true
fetchEvents(eventQuery).then(response =>
setEvents(response?.eventList?.list)
)
}, [startDay, props.queryParams])

useEffect(() => {
// TODO possibly this can be improved
const tasksSet = new Set()
const tasksArray = []
events
.map(event => event.tasks)
.flat()
.forEach(task => {
if (!tasksSet.has(task.uuid)) {
tasksSet.add(task.uuid)
tasksArray.push(task)
}
tasksSet.add(task)
})
tasksArray.sort((a, b) => a.shortName.localeCompare(b.shortName))
setTasks(tasksArray)
}, [events])

function getFirstDayOfCurrentWeek() {
const today = new Date()
const day = today.getDay()
const diff = today.getDate() - day + (day === 0 ? -6 : 1) // adjust when day is sunday
return new Date(today.setDate(diff))
}

function isEventIncluded(event, task, dateToCheck) {
return (
dateToCheck.getTime() >= event.startDate &&
dateToCheck.getTime() <= event.endDate &&
event.tasks.filter(t => t.uuid === task.uuid).length > 0
)
}

function showEventTitle(event, dateToCheck) {
// Case one event starts on this date
if (new Date(event.startDate).toDateString() === dateToCheck.toDateString()) {
return true
}
// Case two event started earlier and we are checking on the Monday
if (dateToCheck.getDay() === 1) {
return true
}
}

function getEvent(task, dayOfWeek) {
// Get the date
const dateToCheck = new Date(weekDays[dayOfWeek])
// Now get events including this task
const selectedEvents = events.filter(event =>
isEventIncluded(event, task, dateToCheck)
)
if (selectedEvents.length > 0) {
selectedEvents.sort((a, b) => a.name.localeCompare(b.name))
return (
<>
<Table className="event-matrix" responsive hover id={dayOfWeek}>
<tbody>
{events.map(event => (
<tr key={event.uuid}>
{isEventIncluded(event, task, dateToCheck) && (
<td
height="55px"
style={{
backgroundColor: "var(--anet-blue)"
}}
>
{showEventTitle(event, dateToCheck) && (
<LinkTo
style={{
marginLeft: "10px",
backgroundColor: "var(--anet-blue)",
color: "white"
}}
modelType="Event"
model={event}
/>)}
</td>
)}
{!isEventIncluded(event, task, dateToCheck) && (
<td height="55px" style={{ backgroundColor: "white" }} />
)}
</tr>
))}
</tbody>
</Table>
</>
)
} else {
return ""
}
}

function showPreviousPeriod() {
setStartDay(moment(startDay).subtract(7, "days").toDate())
}

function showNextPeriod() {
setStartDay(moment(startDay).add(7, "days").toDate())
}

return (
<div style={{ marginTop: "20px" }}>
<Messages error={error} />
<div style={{ float: "left" }}>
<div className="rollup-date-range-container">
<Button
id="previous-period"
onClick={() => showPreviousPeriod()}
variant="outline-secondary"
style={{ marginRight: 5 }}
>
<Icon icon={IconNames.DOUBLE_CHEVRON_LEFT} />
</Button>
Events in week {weekNumber}
<Button
id="next-period"
onClick={() => showNextPeriod()}
variant="outline-secondary"
style={{ marginLeft: 5 }}
>
<Icon icon={IconNames.DOUBLE_CHEVRON_RIGHT} />
</Button>
</div>
</div>
<div>
<Table
className="event-matrix"
responsive
hover
id="events-matrix"
>
<thead>
<tr>
<th />
{weekDays.map(weekDay => (
<th key={weekDay}>{weekDay.toISOString().slice(0, 10)}</th>
))}
</tr>
<tr>
<th>{Settings.fields.task.shortLabel}</th>
{weekDays.map(weekDay => (
<th key={weekDay}>{dayNames[weekDay.getDay()]}</th>
))}
</tr>
</thead>
<tbody>
{tasks.map(task => (
<tr key={task.uuid}>
<td>
<LinkTo modelType="Task" model={task} />
</td>
<td>{getEvent(task, 0)}</td>
<td>{getEvent(task, 1)}</td>
<td>{getEvent(task, 2)}</td>
<td>{getEvent(task, 3)}</td>
<td>{getEvent(task, 4)}</td>
<td>{getEvent(task, 5)}</td>
<td>{getEvent(task, 6)}</td>
</tr>
))}
</tbody>
</Table>
{events.length === 0 && <em>No events in this week </em>}
</div>
</div>
)
}

EventMatrix.propTypes = {
// query variables for events, when query & pagination wanted:
queryParams: PropTypes.object
}
export default connect(null, mapPageDispatchersToProps)(EventMatrix)
7 changes: 3 additions & 4 deletions client/src/components/EventSummary.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import _isEmpty from "lodash/isEmpty"
import _isEqual from "lodash/isEqual"
import { Event, Location } from "models"
import moment from "moment"
import pluralize from "pluralize"
import PropTypes from "prop-types"
import React, { useEffect, useRef, useState } from "react"
import { Badge, Col, Container, Row } from "react-bootstrap"
Expand Down Expand Up @@ -187,7 +186,7 @@ const EventSummaryRow = ({ event }) => {
<Row>
<Col md={12}>
<span>
<strong>{pluralize(Settings.fields.event.tasks)}:</strong>{" "}
<strong>{Settings.fields.event.tasks.label}:</strong>{" "}
{event.tasks.map((task, i) => (
<React.Fragment key={task.uuid}>
{i > 0 && (
Expand All @@ -209,7 +208,7 @@ const EventSummaryRow = ({ event }) => {
<Row>
<Col md={12}>
<span>
<strong>{pluralize(Settings.fields.event.organizations)}:</strong>{" "}
<strong>{Settings.fields.event.organizations.label}:</strong>{" "}
{event.organizations.map((organization, i) => (
<React.Fragment key={organization.uuid}>
{i > 0 && (
Expand All @@ -230,7 +229,7 @@ const EventSummaryRow = ({ event }) => {
<Row>
<Col md={12}>
<span>
<strong>{pluralize(Settings.fields.event.people)}:</strong>{" "}
<strong>{Settings.fields.event.people.label}:</strong>{" "}
{event.people.map((person, i) => (
<React.Fragment key={person.uuid}>
{i > 0 && (
Expand Down
6 changes: 4 additions & 2 deletions client/src/components/aggregations/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -260,8 +260,10 @@ export function reportsToEvents(reports, showInterlocutors) {
export function eventToCalendarEvents(events) {
return events
.map(event => {
// If no other data available title is the location name
const title = `${event.name}@${event.location.name}`
let title = `${event.name}`
if (event.location) {
title = `${title}@${event.location.name}`
}
const start = new Date(event.startDate)
start.setSeconds(0, 0) // truncate at the minute part
const end = new Date(event.endDate)
Expand Down
4 changes: 2 additions & 2 deletions client/src/components/previews/EventPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@ const EventPreview = ({ className, uuid }) => {
wrappedComponent={PreviewField}
dictProps={Settings.fields.event.startDate}
extraColForValue
value={moment(event.engagementDate).format(
value={moment(event.startDate).format(
Event.getEventDateFormat()
)}
/>
<DictionaryField
wrappedComponent={PreviewField}
dictProps={Settings.fields.event.endDate}
extraColForValue
value={moment(event.engagementDate).format(
value={moment(event.endDate).format(
Event.getEventDateFormat()
)}
/>
Expand Down
4 changes: 4 additions & 0 deletions client/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -1252,4 +1252,8 @@ div[id*='fg-entityAssessment'] {
padding-top: 15px;
box-shadow: 0 1px 3px hsla(0, 0%, 0%, 0.15);
}

table.event-matrix > :not(caption) > * > * {
padding: 0.5rem 0.0rem;
}
}
Loading

0 comments on commit a3abfe2

Please sign in to comment.