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 8, 2024
1 parent 20ebc50 commit de19400
Show file tree
Hide file tree
Showing 8 changed files with 278 additions and 17 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
221 changes: 221 additions & 0 deletions client/src/components/EventMatrix.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
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(() => {
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, dateToCheck) {
return (
dateToCheck.getTime() >= event.startDate &&
dateToCheck.getTime() <= event.endDate
)
}

function showEventTitle(event, dateToCheck) {
// True if event starts on this date or Monday
return (
new Date(event.startDate).toDateString() === dateToCheck.toDateString() ||
dateToCheck.getDay() === 1
)
}

function getEvent(task, dayOfWeek) {
// Get the date
const dateToCheck = new Date(weekDays[dayOfWeek])
return (
<>
<Table className="event-matrix" responsive hover id={dayOfWeek}>
<tbody>
{events
.filter(
event =>
event.tasks.filter(t => t.uuid === task.uuid).length > 0
)
.map(event => (
<tr key={event.uuid}>
{isEventIncluded(event, 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, dateToCheck) && (
<td height="55px" style={{ backgroundColor: "white" }} />
)}
</tr>
))}
</tbody>
</Table>
</>
)
}

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
8 changes: 2 additions & 6 deletions client/src/components/previews/EventPreview.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,13 @@ const EventPreview = ({ className, uuid }) => {
wrappedComponent={PreviewField}
dictProps={Settings.fields.event.startDate}
extraColForValue
value={moment(event.engagementDate).format(
Event.getEventDateFormat()
)}
value={moment(event.startDate).format(Event.getEventDateFormat())}
/>
<DictionaryField
wrappedComponent={PreviewField}
dictProps={Settings.fields.event.endDate}
extraColForValue
value={moment(event.engagementDate).format(
Event.getEventDateFormat()
)}
value={moment(event.endDate).format(Event.getEventDateFormat())}
/>
<PreviewField
extraColForValue
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;
}
}
16 changes: 14 additions & 2 deletions src/main/java/mil/dds/anet/beans/search/EventSearchQuery.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public class EventSearchQuery extends EventSeriesSearchQuery {
@GraphQLQuery
@GraphQLInputField
String type;
@GraphQLQuery
@GraphQLInputField
Boolean onlyWithTasks;

public EventSearchQuery() {
super();
Expand Down Expand Up @@ -89,10 +92,18 @@ public void setType(String type) {
this.type = type;
}

public boolean isOnlyWithTasks() {
return Boolean.TRUE.equals(onlyWithTasks);
}

public void setOnlyWithTasks(Boolean onlyWithTasks) {
this.onlyWithTasks = onlyWithTasks;
}

@Override
public int hashCode() {
return Objects.hash(super.hashCode(), getHostOrgUuid(), getAdminOrgUuid(), eventSeriesUuid,
locationUuid, taskUuid, includeDate, startDate, endDate, type);
locationUuid, taskUuid, includeDate, startDate, endDate, type, onlyWithTasks);
}

@Override
Expand All @@ -108,7 +119,8 @@ public boolean equals(Object obj) {
&& Objects.equals(getIncludeDate(), other.getIncludeDate())
&& Objects.equals(getStartDate(), other.getStartDate())
&& Objects.equals(getEndDate(), other.getEndDate())
&& Objects.equals(getType(), other.getType());
&& Objects.equals(getType(), other.getType())
&& Objects.equals(isOnlyWithTasks(), other.isOnlyWithTasks());
}

@Override
Expand Down
Loading

0 comments on commit de19400

Please sign in to comment.