Skip to content

Commit

Permalink
Merge pull request #12 from icefoganalytics/main
Browse files Browse the repository at this point in the history
Fixes
  • Loading branch information
datajohnson authored Jul 3, 2024
2 parents 94b0785 + 6cd70fa commit 38932c6
Show file tree
Hide file tree
Showing 17 changed files with 776 additions and 138 deletions.
3 changes: 3 additions & 0 deletions api/src/data/migrations/019.create-actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ export async function up(knex: knex.Knex) {
table.string("sensitivity_code", 8).nullable();
table.string("status_code", 8).nullable();
table.string("notes", 4000).nullable();
table.datetime("complete_date").nullable();
table.string("complete_name", 200).nullable();
table.integer("complete_user_id").nullable();

table.foreign("hazard_id").references("hazards.id");
table.foreign("incident_id").references("incidents.id");
Expand Down
5 changes: 5 additions & 0 deletions api/src/data/models/action-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,9 @@ export interface Action {
sensitivity_code?: string;
status_code?: string;
notes?: string;
complete_date?: Date;
complete_name?: string;
complete_user_id?: number;

actor_display_name?: string;
}
6 changes: 4 additions & 2 deletions api/src/data/models/incident-step-model.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { Knex } from "knex";

export interface IncidentStep {
id?: number;
incident_id: number;
step_title: string;
order: number;
activate_date?: Date;
complete_date?: Date;
activate_date?: Date | Knex.Raw<any>;
complete_date?: Date | Knex.Raw<any>;
complete_name?: string;
complete_user_id?: number;
}
14 changes: 14 additions & 0 deletions api/src/routes/directory-router.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import express, { Request, Response } from "express";
import { DirectoryService } from "../services";
import { db as knex } from "../data";

export const directoryRouter = express.Router();

Expand All @@ -13,3 +14,16 @@ directoryRouter.post("/search-directory", async (req: Request, res: Response) =>

return res.json({ data: [...results] });
});

directoryRouter.post("/search-action-directory", async (req: Request, res: Response) => {
let { terms } = req.body;

await directoryService.connect();
let data = await directoryService.search(terms);

const allUsers = await knex("users");

data.map((d: any) => (d.user_id = allUsers.find((u) => u.email == d.email)?.id));

return res.json({ data });
});
147 changes: 128 additions & 19 deletions api/src/routes/report-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import { isArray } from "lodash";
import { db as knex } from "../data";
import { DepartmentService, DirectoryService, EmailService, IncidentService } from "../services";
import {
Action,
ActionStatuses,
ActionTypes,
Hazard,
HazardStatuses,
Incident,
Expand Down Expand Up @@ -110,8 +113,6 @@ reportRouter.post("/", async (req: Request, res: Response) => {
const insertedIncidents = await trx("incidents").insert(incident).returning("*");
const insertedHazards = await trx("hazards").insert(hazard).returning("*");

const supervisorUser = await trx("users").where({ email: supervisor_email }).first();

let insertedIncidentId = insertedIncidents[0].id;
let insertedHazardId = insertedHazards[0].id;

Expand Down Expand Up @@ -143,26 +144,15 @@ reportRouter.post("/", async (req: Request, res: Response) => {
activate_date: i == i ? new Date() : null,
} as IncidentStep;

if (i == 1) {
(step as any).complete_date = InsertableDate(new Date().toISOString());
step.complete_name = req.user.display_name;
step.complete_user_id = req.user.id;
}

await trx("incident_steps").insert(step);
}

/* const basicActions = ["Complete Initial Investigation", "Complete Action Plan"];
for (let i = 1; i <= basicActions.length; i++) {
const action = {
incident_id: insertedIncidentId,
created_at: new Date(),
description: basicActions[i - 1],
action_type_code: ActionTypes.SYSTEM_GENERATED.code,
sensitivity_code: SensitivityLevels.NOT_SENSITIVE.code,
status_code: ActionStatuses.OPEN.code,
actor_user_email: supervisor_email,
actor_user_id: supervisorUser?.id ?? null,
} as Action;
await trx("actions").insert(action);
} */

if (req.files && req.files.files) {
let files = req.files.files;

Expand Down Expand Up @@ -216,3 +206,122 @@ reportRouter.post("/", async (req: Request, res: Response) => {

return res.status(400).json({ data: {} });
});

reportRouter.put("/:id/step/:step_id/:operation", async (req: Request, res: Response) => {
const { id, step_id, operation } = req.params;

const step = await knex("incident_steps").where({ incident_id: id, id: step_id }).first();

if (step) {
if (operation == "complete") {
await knex("incident_steps")
.where({ incident_id: id, id: step_id })
.update({
complete_name: req.user.display_name,
complete_date: InsertableDate(new Date().toISOString()),
complete_user_id: req.user.id,
});
} else if (operation == "revert") {
await knex("incident_steps").where({ incident_id: id, id: step_id }).update({
complete_name: null,
complete_date: null,
complete_user_id: null,
});
}
}

const allSteps = await knex("incident_steps").where({ incident_id: id });
let allComplete = true;

for (const step of allSteps) {
if (!step.complete_date) allComplete = false;
}

if (allComplete) {
await knex("incidents").where({ id }).update({ status_code: IncidentStatuses.CLOSED.code });
} else {
await knex("incidents").where({ id }).update({ status_code: IncidentStatuses.IN_PROGRESS.code });
}

return res.json({ data: {} });
});

reportRouter.post("/:id/action", async (req: Request, res: Response) => {
const { id } = req.params;
const { description, notes, actor_user_email, actor_user_id, actor_role_type_id, due_date } = req.body;

const action = {
incident_id: parseInt(id),
created_at: InsertableDate(new Date().toISOString()),
description,
notes,
action_type_code: ActionTypes.USER_GENERATED.code,
sensitivity_code: SensitivityLevels.NOT_SENSITIVE.code,
status_code: ActionStatuses.OPEN.code,
actor_user_email,
actor_user_id,
actor_role_type_id,
due_date: InsertableDate(due_date),
} as Action;

await knex("actions").insert(action);

return res.json({ data: {} });
});

reportRouter.put("/:id/action/:action_id", async (req: Request, res: Response) => {
const { id, action_id } = req.params;
const { description, notes, actor_user_email, actor_user_id, actor_role_type_id, due_date } = req.body;

const action = await knex("actions").where({ incident_id: id, id: action_id }).first();
if (!action) return res.status(404).send();

await knex("actions").where({ id: action_id }).update({
description,
notes,
actor_user_email,
actor_user_id,
actor_role_type_id,
due_date,
});

return res.json({ data: {} });
});

reportRouter.delete("/:id/action/:action_id", async (req: Request, res: Response) => {
const { id, action_id } = req.params;

await knex("actions").where({ incident_id: id, id: action_id }).delete();

return res.json({ data: {} });
});

reportRouter.delete("/:id/action/:action_id", async (req: Request, res: Response) => {
const { id, action_id } = req.params;

await knex("actions").where({ incident_id: id, id: action_id }).delete();

return res.json({ data: {} });
});

reportRouter.put("/:id/action/:action_id/:operation", async (req: Request, res: Response) => {
const { id, action_id, operation } = req.params;

if (operation == "complete") {
await knex("actions")
.where({ incident_id: id, id: action_id })
.update({
complete_date: InsertableDate(new Date().toISOString()),
complete_name: req.user.display_name,
complete_user_id: req.user.id,
});
} else if (operation == "revert") {
await knex("actions").where({ incident_id: id, id: action_id }).update({
complete_date: null,
complete_name: null,
complete_user_id: null,
});
}

return res.json({ data: {} });
});
16 changes: 14 additions & 2 deletions api/src/services/incident-service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ export class IncidentService {
.where({ incident_id: item.id })
.select("id", "incident_id", "added_by_email", "file_name", "file_type", "file_size", "added_date");

item.steps = await db("incident_steps").where({ incident_id: item.id });
item.actions = await db("actions").where({ incident_id: item.id });
item.steps = await db("incident_steps").where({ incident_id: item.id }).orderBy("order");
item.actions = await db("actions").where({ incident_id: item.id }).orderBy("due_date");
item.hazards = await db("incident_hazards").where({ incident_id: item.id });

for (let hazard of item.hazards) {
Expand All @@ -49,6 +49,18 @@ export class IncidentService {
hazard.hazard = await db("hazards").where({ id: hazard.hazard_id }).first();
}

for (let action of item.actions) {
if (action.actor_role_type_id) {
action.actor_display_name = (
await db("role_types").where({ id: action.actor_role_type_id }).first()
).description;
} else if (action.actor_user_id) {
action.actor_display_name = (await db("users").where({ id: action.actor_user_id }).first()).display_name;
} else if (action.actor_user_email) {
action.actor_display_name = action.actor_user_email;
}
}

return item;
}

Expand Down
48 changes: 36 additions & 12 deletions web/src/components/action/ActionCreate.vue
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
<template>
<v-dialog width="700px">
<v-dialog width="700px" persistent>
<template #default>
<v-card v-if="action">
<v-toolbar color="primary" density="comfortable">
<v-toolbar-title class="text-white" style="">Add Action to Action Plan</v-toolbar-title>
<v-toolbar-title class="text-white" style="">Add Task to Action Plan</v-toolbar-title>
<v-spacer> </v-spacer>
<v-toolbar-items>
<v-btn icon="mdi-close" @click="closeClick"></v-btn>
</v-toolbar-items>
</v-toolbar>
<v-card-text class="pt-5">
<v-row>
<v-col>
<v-col cols="12">
<v-label>Due date</v-label>
<DateSelector ref="dp" v-model="action.due_date" :min="new Date()" />
<a @click="setToday" class="cursor-pointer text-info">Today</a>,
<a @click="setTomorrow" class="cursor-pointer text-info">Tomorrow</a>,
<a @click="setWeek" class="cursor-pointer text-info">in 1 week</a>
</v-col>
<v-col>
<v-label>Assigned to</v-label>
<v-text-field hide-details v-model="action.action_user_id" />
<a @click="setMe" class="cursor-pointer text-info">Me</a>
<ActionUserSelector
label="Search and select the group or person"
@selected="actionUserSelected"></ActionUserSelector>

<!-- <a @click="setMe" class="cursor-pointer text-info">Me</a> -->
</v-col>
<v-col cols="12">
<v-label>Task</v-label>
Expand All @@ -46,21 +48,26 @@
</v-dialog>
</template>

<script setup lang="ts">
<script setup>
import { ref, computed } from "vue";
import { storeToRefs } from "pinia";
import { DateTime } from "luxon";
import { useUserStore } from "@/store/UserStore";
import { useReportStore } from "@/store/ReportStore";
const emit = defineEmits(["doClose"]);
import ActionUserSelector from "./ActionUserSelector.vue";
import DateSelector from "@/components/DateSelector.vue";
const userStore = useUserStore();
const { user } = storeToRefs(userStore);
const action = ref({} as { description?: string; due_date?: Date; notes?: string; action_user_id?: any });
const dp = ref(null as any);
const reportStore = useReportStore();
const { saveAction } = reportStore;
const action = ref({});
const dp = ref(null);
const canSave = computed(() => {
if (action.value.due_date && action.value.description) return true;
Expand All @@ -78,7 +85,7 @@ function setWeek() {
if (dp.value) dp.value.setManual(DateTime.now().plus({ weeks: 1 }).toJSDate());
}
function setMe() {
if (user.value) action.value.action_user_id = user.value.display_name;
if (user.value) action.value.action_user_id = user.value.id;
}
function closeClick() {
Expand All @@ -87,7 +94,24 @@ function closeClick() {
}
async function saveClick() {
console.log("SAVING ACTION", action.value);
alert("This doesn't work yet");
await saveAction(action.value).then(() => {
closeClick();
});
}
function actionUserSelected(actor) {
if (actor.actor_role_type_id) {
action.value.actor_role_type_id = actor.actor_role_type_id;
action.value.actor_user_id = null;
action.value.actor_user_email = null;
} else if (actor.user_id) {
action.value.actor_role_type_id = null;
action.value.actor_user_id = actor.user_id;
action.value.actor_user_email = actor.email;
} else if (actor.email) {
action.value.actor_role_type_id = null;
action.value.actor_user_id = null;
action.value.actor_user_email = actor.email;
}
}
</script>
Loading

0 comments on commit 38932c6

Please sign in to comment.