diff --git a/src/dispatch/incident/models.py b/src/dispatch/incident/models.py index c7057fb5e064..dcb94a4a8381 100644 --- a/src/dispatch/incident/models.py +++ b/src/dispatch/incident/models.py @@ -2,7 +2,8 @@ from datetime import datetime from typing import ForwardRef, List, Optional -from pydantic import validator +from pydantic import validator, Field + from sqlalchemy import Column, DateTime, ForeignKey, Integer, PrimaryKeyConstraint, String, Table from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.orm import relationship @@ -46,6 +47,7 @@ from dispatch.report.models import ReportRead from dispatch.storage.models import StorageRead from dispatch.tag.models import TagRead, TagReadMinimal +from dispatch.task.enums import TaskStatus from dispatch.term.models import TermRead from dispatch.ticket.models import TicketRead from dispatch.workflow.models import WorkflowInstanceRead @@ -235,6 +237,15 @@ class CaseRead(DispatchBase): name: Optional[NameStr] +class TaskRead(DispatchBase): + id: PrimaryKey + assignees: List[Optional[ParticipantRead]] = [] + created_at: Optional[datetime] + description: Optional[str] = Field(None, nullable=True) + status: TaskStatus = TaskStatus.open + weblink: Optional[str] + + # Pydantic models... class IncidentBase(DispatchBase): title: str @@ -327,16 +338,25 @@ def find_exclusive(cls, v): class IncidentRead(IncidentBase): id: PrimaryKey + cases: Optional[List[CaseRead]] = [] closed_at: Optional[datetime] = None commander: Optional[ParticipantRead] commanders_location: Optional[str] + conference: Optional[ConferenceRead] = None + conversation: Optional[ConversationRead] = None created_at: Optional[datetime] = None + documents: Optional[List[DocumentRead]] = [] + duplicates: Optional[List[IncidentReadMinimal]] = [] duplicates: Optional[List[IncidentReadMinimal]] = [] + events: Optional[List[EventRead]] = [] incident_costs: Optional[List[IncidentCostRead]] = [] incident_priority: IncidentPriorityRead incident_severity: IncidentSeverityRead incident_type: IncidentTypeRead + last_executive_report: Optional[ReportRead] + last_tactical_report: Optional[ReportRead] name: Optional[NameStr] + participants: Optional[List[ParticipantRead]] = [] participants_location: Optional[str] participants_team: Optional[str] project: ProjectRead @@ -344,20 +364,12 @@ class IncidentRead(IncidentBase): reporter: Optional[ParticipantRead] reporters_location: Optional[str] stable_at: Optional[datetime] = None - tags: Optional[List[TagRead]] = [] - total_cost: Optional[float] - cases: Optional[List[CaseRead]] = [] - conference: Optional[ConferenceRead] = None - conversation: Optional[ConversationRead] = None - documents: Optional[List[DocumentRead]] = [] - duplicates: Optional[List[IncidentReadMinimal]] = [] - events: Optional[List[EventRead]] = [] - last_executive_report: Optional[ReportRead] - last_tactical_report: Optional[ReportRead] - participants: Optional[List[ParticipantRead]] = [] storage: Optional[StorageRead] = None + tasks: Optional[List[TaskRead]] = [] + tags: Optional[List[TagRead]] = [] terms: Optional[List[TermRead]] = [] ticket: Optional[TicketRead] = None + total_cost: Optional[float] workflow_instances: Optional[List[WorkflowInstanceRead]] = [] diff --git a/src/dispatch/static/dispatch/src/filters.js b/src/dispatch/static/dispatch/src/filters.js index 064eb9777589..0f20b5b44264 100644 --- a/src/dispatch/static/dispatch/src/filters.js +++ b/src/dispatch/static/dispatch/src/filters.js @@ -117,3 +117,13 @@ export const activeRoles = function (value) { } Vue.filter("activeRoles", activeRoles) + +Vue.filter("individualNames", function (value) { + if (value) { + return value + .map(function (item) { + return item.individual.name + }) + .join(", ") + } +}) diff --git a/src/dispatch/static/dispatch/src/incident/EditSheet.vue b/src/dispatch/static/dispatch/src/incident/EditSheet.vue index 5fdbb6a14f1d..7f18b0ca9535 100644 --- a/src/dispatch/static/dispatch/src/incident/EditSheet.vue +++ b/src/dispatch/static/dispatch/src/incident/EditSheet.vue @@ -31,6 +31,7 @@ Resources Participants Timeline + Tasks Workflows Costs @@ -47,6 +48,9 @@ + + + @@ -63,23 +67,25 @@ import { mapFields } from "vuex-map-fields" import { mapActions } from "vuex" import { ValidationObserver } from "vee-validate" +import IncidentCostsTab from "@/incident/CostsTab.vue" import IncidentDetailsTab from "@/incident/DetailsTab.vue" -import IncidentResourcesTab from "@/incident/ResourcesTab.vue" import IncidentParticipantsTab from "@/incident/ParticipantsTab.vue" +import IncidentResourcesTab from "@/incident/ResourcesTab.vue" +import IncidentTasksTab from "@/incident/TasksTab.vue" import IncidentTimelineTab from "@/incident/TimelineTab.vue" -import IncidentCostsTab from "@/incident/CostsTab.vue" import WorkflowInstanceTab from "@/workflow/WorkflowInstanceTab.vue" export default { name: "IncidentEditSheet", components: { - ValidationObserver, + IncidentCostsTab, IncidentDetailsTab, - IncidentResourcesTab, IncidentParticipantsTab, + IncidentResourcesTab, + IncidentTasksTab, IncidentTimelineTab, - IncidentCostsTab, + ValidationObserver, WorkflowInstanceTab, }, diff --git a/src/dispatch/static/dispatch/src/incident/TasksTab.vue b/src/dispatch/static/dispatch/src/incident/TasksTab.vue new file mode 100644 index 000000000000..0d67304f9165 --- /dev/null +++ b/src/dispatch/static/dispatch/src/incident/TasksTab.vue @@ -0,0 +1,42 @@ + + + diff --git a/src/dispatch/static/dispatch/src/incident/store.js b/src/dispatch/static/dispatch/src/incident/store.js index fa214e13dd31..09ed7f029d38 100644 --- a/src/dispatch/static/dispatch/src/incident/store.js +++ b/src/dispatch/static/dispatch/src/incident/store.js @@ -31,6 +31,7 @@ const getDefaultSelectedState = () => { status: null, storage: null, tags: [], + tasks: [], terms: [], ticket: null, title: null,