Initial work marking communications

And a bunch of lint fixes
This commit is contained in:
Eli Ribble 2026-05-04 19:07:29 +00:00
parent 67c99436d1
commit 3153e8bf13
No known key found for this signature in database
36 changed files with 1958 additions and 487 deletions

View file

@ -8,7 +8,7 @@
<div class="card shadow-sm h-100">
<div class="card-header bg-light pane-header">Actions</div>
<div class="card-body scroll-pane">
<div v-if="loading" class="loading">Loading...</div>
<div v-if="isLoading" class="loading">Loading...</div>
<div v-else>
<div
v-if="!selectedCommunication"
@ -25,22 +25,51 @@
class="actions-panel d-flex flex-column"
>
<div class="p-3 flex-grow-1">
<!-- Create Signal -->
<p class="text-muted mt-1">Send to planning</p>
<div class="d-grid mb-3">
<button class="btn btn-success btn-lg" @click="markSignal()">
<i class="bi bi-plus-circle me-2"></i>Mark Signal
</button>
<small class="text-muted mt-1"
>This report is useful signal</small
>
<ButtonLoading
@click="markPossibleIssue()"
:disabled="!selectedReport"
icon="bi-plus-circle"
:loading="isLoading"
text="Possible Issue"
variant="warning"
/>
</div>
<!-- Mark Invalid -->
<div class="d-grid mb-3">
<button class="btn btn-outline-danger" @click="markInvalid()">
<i class="bi bi-x-circle me-2"></i>Mark Invalid
</button>
<small class="text-muted mt-1">This report isn't useful</small>
<ButtonLoading
@click="markPossibleResolved()"
:disabled="!selectedReport"
icon="bi-x-circle"
:loading="isLoading"
text="May Be Resolved"
variant="outline-success"
/>
</div>
<hr />
<div class="d-grid mb-3">
<p class="text-muted mt-1">Resolve immediately</p>
<ButtonLoading
@click="markInvalid()"
:disabled="!selectedReport"
icon="bi-x-circle"
:loading="isLoading"
text="Invalid"
variant="outline-danger"
/>
</div>
<div class="d-grid mb-3">
<ButtonLoading
@click="markPendingResponse()"
:disabled="!selectedReport"
icon="bi-clock"
:loading="isLoading"
text="Pending Response"
variant="secondary"
/>
</div>
<hr />
@ -134,14 +163,17 @@
<script setup lang="ts">
import { ref } from "vue";
import { Communication, PublicReport, User } from "@/type/api";
import ButtonLoading from "@/components/common/ButtonLoading.vue";
import ListCardActivityLog from "@/components/ListCardActivityLog.vue";
interface Emits {
(e: "markSignal"): void;
(e: "markInvalid"): void;
(e: "markPendingResponse"): void;
(e: "markPossibleIssue"): void;
(e: "markPossibleResolved"): void;
(e: "sendMessage", message: string): void;
}
interface Props {
loading: boolean;
isLoading: boolean;
selectedCommunication: Communication | null;
selectedReport: PublicReport | undefined;
}
@ -169,8 +201,14 @@ function handleTemplateChange(event: Event) {
function markInvalid() {
emit("markInvalid");
}
function markSignal() {
emit("markSignal");
function markPendingResponse() {
emit("markPendingResponse");
}
function markPossibleResolved() {
emit("markPossibleResolved");
}
function markPossibleIssue() {
emit("markPossibleIssue");
}
function sendMessage() {
emit("sendMessage", messageText.value);

View file

@ -534,6 +534,7 @@ export interface CommunicationDTO {
id: string;
source: string;
type: string;
uri: string;
}
export class Communication {
constructor(
@ -541,6 +542,7 @@ export class Communication {
public id: string,
public source: string,
public type: string,
public uri: string,
) {}
static fromJSON(json: CommunicationDTO): Communication {
return new Communication(
@ -548,6 +550,7 @@ export class Communication {
json.id,
json.source,
json.type,
json.uri,
);
}
}

View file

@ -33,9 +33,11 @@
</template>
<template #right>
<CommunicationColumnAction
:loading="storePublicReport.loading || storeCommunication.loading"
:isLoading="storePublicReport.loading || storeCommunication.loading"
@markInvalid="markInvalid"
@markSignal="markSignal"
@markPendingResponse="markPendingResponse"
@markPossibleIssue="markPossibleIssue"
@markPossibleResolved="markPossibleResolved"
@sendMessage="sendMessage"
:selectedCommunication="selectedCommunication"
:selectedReport="selectedReport"
@ -62,6 +64,7 @@ import { computed, onMounted, ref, watch } from "vue";
import { computedAsync } from "@vueuse/core";
import maplibregl from "maplibre-gl";
import { apiClient } from "@/client";
import CommunicationColumnAction from "@/components/CommunicationColumnAction.vue";
import CommunicationColumnDetail from "@/components/CommunicationColumnDetail.vue";
import CommunicationColumnList from "@/components/CommunicationColumnList.vue";
@ -212,60 +215,32 @@ function openImageViewer(index: number) {
}
async function markInvalid() {
markReport("Invalid", "invalid");
}
async function markPendingResponse() {
markReport("Pending Response", "pending-response");
}
async function markPossibleIssue() {
markReport("Possible Issue", "possible-issue");
}
async function markPossibleResolved() {
markReport("Possibly Resolved", "possible-resolved");
}
async function markReport(title: string, status: string) {
if (selectedCommunication.value == null) {
return;
}
console.log("Marking report as invalid:", selectedCommunication.value.id);
const payload = {
reportID: selectedCommunication.value.id,
};
const response = await fetch("/api/publicreport/invalid", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
const url = `${selectedCommunication.value.uri}/${status}`;
const result = apiClient.JSONPost(url, {});
showNotification(
"Report Marked Invalid",
`Report #${selectedCommunication.value.id} has been marked as invalid`,
`Report Marked ${title}`,
`Report #${selectedCommunication.value.id} has been updated`,
);
removeCurrentFromList();
await storeCommunication.fetchAll();
}
async function markSignal() {
if (selectedCommunication.value == null) {
return;
}
console.log("Marking report as signal:", selectedCommunication.value.id);
try {
const report_id = selectedCommunication.value.id;
const payload = {
reportID: report_id,
};
removeCurrentFromList();
const response = await fetch("api/publicreport/signal", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (!response.ok) {
throw new Error("Failed to submit signal");
}
showNotification(
"Report Marked Signal",
`Report #${report_id} has been marked as useful signal`,
);
await storeCommunication.fetchAll();
} catch (err) {
console.error("Error creating lead:", err);
}
}
function removeCurrentFromList() {
if (storeCommunication.all == null) {
return;