Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add "lastModified" to Incident entity, add column in DataTable #1589

Merged
merged 1 commit into from
Feb 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/ims/element/incident/incidents_template/template.xhtml
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@
<tr>
<th>#</th>
<th>Created</th>
<th>Modified</th>
<th>State</th>
<th>Rangers</th>
<th>Location</th>
Expand All @@ -178,6 +179,7 @@
<tr>
<th>#</th>
<th>Created</th>
<th>Modified</th>
<th>State</th>
<th>Rangers</th>
<th>Location</th>
Expand Down
12 changes: 3 additions & 9 deletions src/ims/element/static/ims.js
Original file line number Diff line number Diff line change
Expand Up @@ -505,10 +505,7 @@ function incidentAsString(incident) {
if (incident.number == null) {
return "New Incident";
}
return (
"IMS #" + incident.number + ": " +
summarizeIncident(incident)
);
return `#${incident.number}: ${summarizeIncident(incident)} (${incident.event})`;
}


Expand All @@ -517,11 +514,8 @@ function fieldReportAsString(report) {
if (report.number == null) {
return "New Field Report";
}
return (
"FR #" + report.number +
" (" + fieldReportAuthor(report) + "): " +
summarizeFieldReport(report)
);
return `FR #${report.number} (${fieldReportAuthor(report)}): ` +
`${summarizeFieldReport(report)} (${report.event})`;
}


Expand Down
35 changes: 17 additions & 18 deletions src/ims/element/static/incidents.js
Original file line number Diff line number Diff line change
Expand Up @@ -242,36 +242,43 @@ function initDataTables() {
"render": renderDate,
},
{ // 2
"name": "incident_last_modified",
"className": "incident_last_modified text-center",
"data": "last_modified",
"defaultContent": null,
"render": renderDate,
},
{ // 3
"name": "incident_state",
"className": "incident_state text-center",
"data": "state",
"defaultContent": null,
"render": renderState,
},
{ // 3
{ // 4
"name": "incident_ranger_handles",
"className": "incident_ranger_handles",
"data": "ranger_handles",
"defaultContent": "",
"render": renderSafeSorted,
"width": "6em",
},
{ // 4
{ // 5
"name": "incident_location",
"className": "incident_location",
"data": "location",
"defaultContent": "",
"render": renderLocation,
},
{ // 5
{ // 6
"name": "incident_types",
"className": "incident_types",
"data": "incident_types",
"defaultContent": "",
"render": renderSafeSorted,
"width": "5em",
},
{ // 6
{ // 7
"name": "incident_summary",
"className": "incident_summary",
"data": "summary",
Expand All @@ -295,6 +302,11 @@ function initDataTables() {
"title",
fullDateTime.format(Date.parse(incident.created)),
);
row.getElementsByClassName("incident_last_modified")[0]
.setAttribute(
"title",
fullDateTime.format(Date.parse(incident.last_modified)),
);
},
});
}
Expand Down Expand Up @@ -435,19 +447,6 @@ function initSearchField() {
//

function initSearch() {
function modifiedAfter(incident, timestamp) {
if (timestamp < Date.parse(incident.created)) {
return true;
}

for (const entry of incident.report_entries??[]) {
if (timestamp < Date.parse(entry.created)) {
return true;
}
}

return false;
}

$.fn.dataTable.ext.search.push(
function(settings, rowData, rowIndex) {
Expand All @@ -472,7 +471,7 @@ function initSearch() {

if (
_showModifiedAfter != null &&
! modifiedAfter(incident, _showModifiedAfter)
Date.parse(incident.last_modified) < _showModifiedAfter
) {
return false
}
Expand Down
5 changes: 4 additions & 1 deletion src/ims/model/_incident.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from collections.abc import Iterable, Sequence
from datetime import datetime as DateTime

from attrs import field, frozen
from attrs import converters, field, frozen

from ims.ext.attr import sorted_tuple

Expand Down Expand Up @@ -53,6 +53,9 @@ class Incident(ReplaceMixIn):
eventID: str
number: int
created: DateTime = field(converter=normalizeDateTime)
lastModified: DateTime | None = field(
converter=converters.optional(normalizeDateTime)
)
state: IncidentState
priority: IncidentPriority
summary: str | None
Expand Down
2 changes: 2 additions & 0 deletions src/ims/model/json/_incident.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class IncidentJSONKey(Enum):
eventID = "event"
number = "number"
created = "created"
lastModified = "last_modified"
state = "state"
priority = "priority"
summary = "summary"
Expand All @@ -65,6 +66,7 @@ class IncidentJSONType(Enum):
eventID = str
number = int
created = DateTime
lastModified = DateTime | None
state = IncidentState
priority = IncidentPriority
summary = str | None
Expand Down
1 change: 1 addition & 0 deletions src/ims/model/json/test/json_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ def jsonFromIncident(incident: Incident) -> dict[str, Any]:
"event": jsonSerialize(incident.eventID),
"number": jsonSerialize(incident.number),
"created": jsonSerialize(incident.created),
"last_modified": jsonSerialize(incident.lastModified),
"state": jsonSerialize(incident.state),
"priority": jsonSerialize(incident.priority),
"summary": jsonSerialize(incident.summary),
Expand Down
14 changes: 8 additions & 6 deletions src/ims/model/strategies.py
Original file line number Diff line number Diff line change
Expand Up @@ -392,21 +392,23 @@ def incidents(

types = [t.name for t in draw(lists(incidentTypes()))]

created = draw(dateTimes(beforeNow=beforeNow, fromNow=fromNow))
entries = draw(
lists(reportEntries(automatic=automatic, beforeNow=beforeNow, fromNow=fromNow))
)
lastModified = max(re.created for re in entries) if entries else created
return Incident(
eventID=event.id,
number=number,
created=draw(dateTimes(beforeNow=beforeNow, fromNow=fromNow)),
created=created,
lastModified=lastModified,
state=draw(incidentStates()),
priority=draw(incidentPriorities()),
summary=draw(incidentSummaries()),
location=draw(locations()),
rangerHandles=draw(lists(rangerHandles())),
incidentTypes=types,
reportEntries=draw(
lists(
reportEntries(automatic=automatic, beforeNow=beforeNow, fromNow=fromNow)
)
),
reportEntries=entries,
fieldReportNumbers=frozenset(),
)

Expand Down
13 changes: 12 additions & 1 deletion src/ims/store/_db.py
Original file line number Diff line number Diff line change
Expand Up @@ -659,11 +659,17 @@ def _fetchIncidents(
int(val) for val in loads(str(row["FIELD_REPORT_NUMBERS"]))
]
incidentNumber = cast(int, row["NUMBER"])

lastModified = self.fromDateTimeValue(row["CREATED"])
if reportEntries[incidentNumber]:
lastModified = max(re.created for re in reportEntries[incidentNumber])

results.append(
Incident(
eventID=eventID,
number=incidentNumber,
created=self.fromDateTimeValue(row["CREATED"]),
lastModified=lastModified,
state=self.fromIncidentStateValue(row["STATE"]),
priority=self.fromPriorityValue(row["PRIORITY"]),
summary=cast(str | None, row["SUMMARY"]),
Expand Down Expand Up @@ -715,7 +721,7 @@ def notFound() -> NoReturn:

txn.execute(self.query.incident_reportEntries.text, parameters)

reportEntries = (
reportEntries = tuple(
ReportEntry(
id=cast(int, row["ID"]),
created=self.fromDateTimeValue(row["CREATED"]),
Expand All @@ -728,6 +734,10 @@ def notFound() -> NoReturn:
if row["TEXT"]
)

lastModified = self.fromDateTimeValue(row["CREATED"])
if reportEntries:
lastModified = max(re.created for re in reportEntries)

# FIXME: This is because schema thinks concentric is an int
if row["LOCATION_CONCENTRIC"] is None:
concentric = None
Expand All @@ -742,6 +752,7 @@ def notFound() -> NoReturn:
eventID=eventID,
number=incidentNumber,
created=self.fromDateTimeValue(row["CREATED"]),
lastModified=lastModified,
state=self.fromIncidentStateValue(row["STATE"]),
priority=self.fromPriorityValue(row["PRIORITY"]),
summary=cast(str | None, row["SUMMARY"]),
Expand Down
7 changes: 7 additions & 0 deletions src/ims/store/test/incident.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
eventID=anEvent.id,
number=0,
created=DateTime.now(UTC) + TimeDelta(seconds=1),
lastModified=DateTime.now(UTC) + TimeDelta(seconds=2),
state=IncidentState.new,
priority=IncidentPriority.normal,
summary="A thing happened",
Expand All @@ -70,6 +71,7 @@
eventID=anEvent.id,
number=1,
created=DateTime.now(UTC) + TimeDelta(seconds=2),
lastModified=DateTime.now(UTC) + TimeDelta(seconds=3),
state=IncidentState.new,
priority=IncidentPriority.normal,
summary="A thing happened",
Expand All @@ -84,6 +86,7 @@
eventID=anEvent2.id,
number=325,
created=DateTime.now(UTC) + TimeDelta(seconds=3),
lastModified=DateTime.now(UTC) + TimeDelta(seconds=4),
state=IncidentState.new,
priority=IncidentPriority.normal,
summary="Another thing happened 🙂",
Expand Down Expand Up @@ -884,6 +887,10 @@ def assertIncidentsEqual(
if store.dateTimesEqual(valueA, valueB):
continue
messages.append(f"{name} delta: {valueA - valueB}")
elif name == "lastModified":
# this field is calculated on read, and shouldn't be equal
# to what was written
continue
elif name == "reportEntries":
if store.reportEntriesEqual(valueA, valueB, ignoreAutomatic):
continue
Expand Down