Migrate existing ts types from the API into the API module
This makes it possible to start hydrating the types into valid data types like Dates which means I can get type safety guarantees when displaying information.
This commit is contained in:
parent
b2c24a0438
commit
f88ca57d97
39 changed files with 382 additions and 320 deletions
|
|
@ -12,7 +12,7 @@
|
|||
<script setup lang="ts">
|
||||
import { onMounted } from "vue";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import { Session } from "@/types";
|
||||
import { Session } from "@/type/api";
|
||||
|
||||
import Sidebar from "./components/layout/Sidebar.vue";
|
||||
import MainContent from "./components/layout/MainContent.vue";
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { User } from "@/types";
|
||||
import { User } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
user: User;
|
||||
|
|
|
|||
|
|
@ -107,9 +107,9 @@
|
|||
<h6><i class="bi bi-clock-history"></i> Activity Log</h6>
|
||||
<div class="small">
|
||||
<div
|
||||
v-for="entry in selectedCommunication?.public_report?.log ||
|
||||
[]"
|
||||
:key="entry.created"
|
||||
v-for="(entry, index) in selectedCommunication?.public_report
|
||||
?.log || []"
|
||||
:key="index"
|
||||
class="border-start border-2 ps-2 mb-2"
|
||||
>
|
||||
<div v-if="entry.type === 'created'">
|
||||
|
|
@ -147,7 +147,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import { Communication, User } from "@/types";
|
||||
import { Communication, User } from "@/type/api";
|
||||
interface Emits {
|
||||
(e: "markSignal"): void;
|
||||
(e: "markInvalid"): void;
|
||||
|
|
@ -173,8 +173,8 @@ function applyMessageTemplate(template: string) {
|
|||
messageText.value = templates[template as keyof typeof templates];
|
||||
}
|
||||
}
|
||||
function formatDate(date: string) {
|
||||
return new Date(date).toLocaleString();
|
||||
function formatDate(date: Date) {
|
||||
return date.toLocaleString();
|
||||
}
|
||||
function handleTemplateChange(event: Event) {
|
||||
const target = event.target as HTMLSelectElement;
|
||||
|
|
|
|||
|
|
@ -75,7 +75,8 @@ import { computed } from "vue";
|
|||
import MapMultipoint from "@/components/MapMultipoint.vue";
|
||||
import PublicreportCard from "@/components/PublicreportCard.vue";
|
||||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { Bounds, Communication, Marker, User } from "@/types";
|
||||
import type { Bounds, Marker } from "@/types";
|
||||
import type { Communication, User } from "@/type/api";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
||||
interface Emits {
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@
|
|||
import { computed, ref } from "vue";
|
||||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { formatAddress } from "@/format";
|
||||
import { Communication, LogEntry, PublicReport } from "@/types";
|
||||
import { Communication, LogEntry, PublicReport } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
all: Communication[] | null;
|
||||
|
|
@ -211,8 +211,8 @@ function filterMatchesLogEntry(filter: string, logs: LogEntry[]) {
|
|||
}
|
||||
function filterMatchesPublicReport(filter: string, pr: PublicReport) {
|
||||
if (
|
||||
pr.address_raw.includes(filter) ||
|
||||
pr.public_id.includes(filter) ||
|
||||
pr.address.raw.includes(filter) ||
|
||||
pr.id.includes(filter) ||
|
||||
filterMatchesLogEntry(filter, pr.log)
|
||||
) {
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -97,7 +97,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { formatDistance } from "@/format";
|
||||
import { Image } from "@/types";
|
||||
import { Image } from "@/type/api";
|
||||
|
||||
interface Emits {
|
||||
(e: "close"): void;
|
||||
|
|
|
|||
|
|
@ -45,7 +45,7 @@ interface Props {
|
|||
const emit = defineEmits<Emits>();
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
// default bounds cover a bunch of the continental US
|
||||
bounds: () => {
|
||||
bounds: (): Bounds => {
|
||||
return {
|
||||
max: { longitude: -70, latitude: 50 },
|
||||
min: { longitude: -125, latitude: 25 },
|
||||
|
|
|
|||
|
|
@ -73,8 +73,8 @@ import PlanningColumnDetailEntry from "@/components/PlanningColumnDetailEntry.vu
|
|||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { shortAddress } from "@/format";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import { MapClickEvent, Marker, Signal } from "@/types";
|
||||
import type { Location } from "@/type/api";
|
||||
import { MapClickEvent, Marker } from "@/types";
|
||||
import type { Location, Signal } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
markers: Marker[];
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ import FlyoverPoolCard from "@/components/FlyoverPoolCard.vue";
|
|||
import PublicreportCard from "@/components/PublicreportCard.vue";
|
||||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { shortAddress } from "@/format";
|
||||
import { Signal } from "@/types";
|
||||
import { Signal } from "@/type/api";
|
||||
interface Props {
|
||||
signal: Signal;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@
|
|||
<script setup lang="ts">
|
||||
import { ref } from "vue";
|
||||
import PlanningColumnListEntry from "@/components/PlanningColumnListEntry.vue";
|
||||
import { Followup, Lead, Signal } from "@/types";
|
||||
import { Followup, Lead, Signal } from "@/type/api";
|
||||
|
||||
interface Emits {
|
||||
(e: "refresh"): void;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<script setup lang="ts">
|
||||
import { shortAddress } from "@/format";
|
||||
import { Signal } from "@/types";
|
||||
import { Signal } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
selected: boolean;
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
Standing Water Report
|
||||
</span>
|
||||
</h5>
|
||||
<small class="text-muted">Report ID: #{{ report.public_id }}</small>
|
||||
<small class="text-muted">Report ID: #{{ report.id }}</small>
|
||||
</div>
|
||||
<span class="badge bg-secondary">
|
||||
<TimeRelative :time="report.created" />
|
||||
|
|
@ -316,7 +316,7 @@ import MapMultipoint from "@/components/MapMultipoint.vue";
|
|||
import PublicreportCard from "@/components/PublicreportCard.vue";
|
||||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { formatAddress } from "@/format";
|
||||
import { PublicReport } from "@/types";
|
||||
import { PublicReport } from "@/type/api";
|
||||
|
||||
interface Emits {
|
||||
(e: "viewImage", index: number): void;
|
||||
|
|
|
|||
|
|
@ -56,7 +56,8 @@
|
|||
<script setup lang="ts">
|
||||
import MapMultipoint from "@/components/MapMultipoint.vue";
|
||||
import MapProxiedArcgisTile from "@/components/MapProxiedArcgisTile.vue";
|
||||
import { Changes, ReviewTask } from "@/types";
|
||||
import { Changes } from "@/types";
|
||||
import { ReviewTask } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
changes: Changes;
|
||||
|
|
|
|||
|
|
@ -149,15 +149,8 @@ import MapMultipoint from "@/components/MapMultipoint.vue";
|
|||
import MapProxiedArcgisTile from "@/components/MapProxiedArcgisTile.vue";
|
||||
import { formatAddress } from "@/format";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import {
|
||||
Bounds,
|
||||
Contact,
|
||||
MapClickEvent,
|
||||
Marker,
|
||||
Pool,
|
||||
ReviewTask,
|
||||
User,
|
||||
} from "@/types";
|
||||
import type { Bounds, MapClickEvent, Marker } from "@/types";
|
||||
import { Contact, Pool, ReviewTask, User } from "@/type/api";
|
||||
import type { Location } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { formatAddress } from "@/format";
|
||||
import { ReviewTask } from "@/types";
|
||||
import { ReviewTask } from "@/type/api";
|
||||
|
||||
interface Emits {
|
||||
(e: "doSelectTask", id: number): void;
|
||||
|
|
|
|||
|
|
@ -14,8 +14,7 @@ export default defineComponent({
|
|||
|
||||
props: {
|
||||
time: {
|
||||
type: String,
|
||||
default: "",
|
||||
type: Date,
|
||||
},
|
||||
},
|
||||
|
||||
|
|
@ -56,7 +55,7 @@ export default defineComponent({
|
|||
}
|
||||
},
|
||||
|
||||
formatRelativeTime(timestamp: string): string {
|
||||
formatRelativeTime(timestamp: Date): string {
|
||||
const now = new Date();
|
||||
const date = new Date(timestamp);
|
||||
const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000);
|
||||
|
|
|
|||
|
|
@ -54,7 +54,7 @@ import { ref, onMounted, watch } from "vue";
|
|||
import { computedAsync } from "@vueuse/core";
|
||||
import Avatar from "@/components/Avatar.vue";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import type { User } from "@/types";
|
||||
import type { User } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
modelValue?: User | null;
|
||||
|
|
|
|||
|
|
@ -210,7 +210,7 @@ import { Tooltip, Popover } from "bootstrap";
|
|||
import NavigationLink from "@/components/common/NavigationLink.vue";
|
||||
import { SSEManager, type SSEMessage } from "@/SSEManager";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import type { Session } from "@/types";
|
||||
import type { Session } from "@/type/api";
|
||||
|
||||
// Reactive state
|
||||
const isCollapsed = ref(false);
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@ import { onMounted, ref } from "vue";
|
|||
import { useSessionStore } from "@/store/session";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import UserSelector from "@/components/UserSelector.vue";
|
||||
import type { Session, User } from "@/types";
|
||||
import type { Session, User } from "@/type/api";
|
||||
|
||||
const session = useSessionStore();
|
||||
const user = useUserStore();
|
||||
|
|
|
|||
|
|
@ -523,14 +523,14 @@ import ImageUpload, { Image } from "@/components/ImageUpload.vue";
|
|||
import MapLocator from "@/components/MapLocator.vue";
|
||||
import { useGeocodeStore } from "@/store/geocode";
|
||||
import { useLocationStore } from "@/store/location";
|
||||
import { useStorePublicreport } from "@/store/publicreport";
|
||||
import { useStorePublicReport } from "@/store/publicreport";
|
||||
import type { Marker } from "@/types";
|
||||
import type {
|
||||
Address,
|
||||
Geocode,
|
||||
GeocodeSuggestion,
|
||||
Location,
|
||||
Publicreport,
|
||||
PublicReport,
|
||||
} from "@/type/api";
|
||||
import type { Camera } from "@/type/map";
|
||||
|
||||
|
|
@ -546,7 +546,7 @@ const marker = ref<Marker | null>(null);
|
|||
const showMore = ref<boolean>(false);
|
||||
const selectedSuggestion = ref<GeocodeSuggestion | null>(null);
|
||||
const locationStore = useLocationStore();
|
||||
const storePublicreport = useStorePublicreport();
|
||||
const storePublicReport = useStorePublicReport();
|
||||
const geocode = useGeocodeStore();
|
||||
const markers = computed((): Marker[] => {
|
||||
if (marker.value) {
|
||||
|
|
@ -637,8 +637,8 @@ async function doSubmit() {
|
|||
body: formData,
|
||||
// Don't set Content-Type, the borwser should do it
|
||||
});
|
||||
const data: Publicreport = (await resp.json()) as Publicreport;
|
||||
storePublicreport.add(data);
|
||||
const data: PublicReport = (await resp.json()) as PublicReport;
|
||||
storePublicReport.add(data);
|
||||
router.push("/submitted/" + data.id);
|
||||
} catch (error) {
|
||||
errorMessage.value =
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ export const useStoreDistrict = defineStore("district", () => {
|
|||
// Actions
|
||||
async function byURI(uri: string): Promise<District | undefined> {
|
||||
let district = _byURI.value.get(uri);
|
||||
console.log("district by uri", uri, district);
|
||||
if (district) {
|
||||
return district;
|
||||
}
|
||||
|
|
@ -45,6 +46,7 @@ export const useStoreDistrict = defineStore("district", () => {
|
|||
const data: District[] = await response.json();
|
||||
data.forEach((d: District) => {
|
||||
_byURI.value.set(d.uri, d);
|
||||
console.log("district", d.uri);
|
||||
});
|
||||
return data;
|
||||
} catch (e) {
|
||||
|
|
|
|||
|
|
@ -258,8 +258,8 @@ import { ref, onMounted } from "vue";
|
|||
import { computedAsync } from "@vueuse/core";
|
||||
import { useRouter } from "vue-router";
|
||||
import { useStoreDistrict } from "@/rmo/store/district";
|
||||
import { useStorePublicreport } from "@/store/publicreport";
|
||||
import type { District, Publicreport } from "@/type/api";
|
||||
import { useStorePublicReport } from "@/store/publicreport";
|
||||
import type { District, PublicReport } from "@/type/api";
|
||||
|
||||
interface FormData {
|
||||
name: string;
|
||||
|
|
@ -286,10 +286,10 @@ const formData = ref<FormData>({
|
|||
});
|
||||
const router = useRouter();
|
||||
const storeDistrict = useStoreDistrict();
|
||||
const storePublicreport = useStorePublicreport();
|
||||
const storePublicReport = useStorePublicReport();
|
||||
|
||||
const report = computedAsync(async (): Promise<Publicreport | undefined> => {
|
||||
return await storePublicreport.byID(props.id);
|
||||
const report = computedAsync(async (): Promise<PublicReport | undefined> => {
|
||||
return await storePublicReport.byID(props.id);
|
||||
});
|
||||
const district = computedAsync(async (): Promise<District | undefined> => {
|
||||
if (!(report.value && report.value.district)) {
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@
|
|||
}
|
||||
</style>
|
||||
<template>
|
||||
<HeaderDistrict v-if="district" />
|
||||
<HeaderDistrict :district="district" v-if="district" />
|
||||
<Header v-else />
|
||||
<div class="container my-4" v-if="report">
|
||||
<!-- Report ID and Status Section -->
|
||||
|
|
@ -83,7 +83,9 @@
|
|||
<strong><i class="bi bi-images me-2"></i>Images:</strong>
|
||||
<span>
|
||||
{{
|
||||
report.image_count > 0 ? report.image_count : "None provided"
|
||||
report.images.length > 0
|
||||
? report.images.length
|
||||
: "None provided"
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
|
|
@ -139,9 +141,9 @@ import Header from "@/rmo/components/Header.vue";
|
|||
import HeaderDistrict from "@/components/HeaderDistrict.vue";
|
||||
import MapLocatorDisplay from "@/components/MapLocatorDisplay.vue";
|
||||
import { useStoreDistrict } from "@/rmo/store/district";
|
||||
import { useStorePublicreport } from "@/store/publicreport";
|
||||
import { useStorePublicReport } from "@/store/publicreport";
|
||||
import type { Marker } from "@/types";
|
||||
import type { District, Publicreport } from "@/type/api";
|
||||
import type { District, PublicReport } from "@/type/api";
|
||||
import { formatTimeRelative } from "@/format";
|
||||
|
||||
// Props
|
||||
|
|
@ -151,10 +153,10 @@ interface Props {
|
|||
|
||||
const props = defineProps<Props>();
|
||||
const storeDistrict = useStoreDistrict();
|
||||
const storePublicreport = useStorePublicreport();
|
||||
const storePublicReport = useStorePublicReport();
|
||||
// Computed
|
||||
const report = computedAsync(async (): Promise<Publicreport | undefined> => {
|
||||
return await storePublicreport.byID(props.id);
|
||||
const report = computedAsync(async (): Promise<PublicReport | undefined> => {
|
||||
return await storePublicReport.byID(props.id);
|
||||
});
|
||||
const district = computedAsync(async (): Promise<District | undefined> => {
|
||||
if (!(report.value && report.value.district)) {
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref, computed } from "vue";
|
||||
import { Communication } from "../types";
|
||||
import { SSEManager, SSEMessage } from "../SSEManager";
|
||||
import { useSessionStore } from "./session";
|
||||
import { ref } from "vue";
|
||||
import { Communication } from "@/type/api";
|
||||
import { SSEManager, SSEMessage } from "@/SSEManager";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
||||
export const useCommunicationStore = defineStore("communication", () => {
|
||||
// State
|
||||
|
|
|
|||
|
|
@ -1,19 +1,19 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { Publicreport, type PublicreportDTO } from "@/type/api";
|
||||
import { PublicReport, type PublicReportDTO } from "@/type/api";
|
||||
|
||||
export const useStorePublicreport = defineStore("publicreport", () => {
|
||||
export const useStorePublicReport = defineStore("publicreport", () => {
|
||||
// State
|
||||
const _byID = ref<Map<string, Publicreport>>(new Map());
|
||||
const _byID = ref<Map<string, PublicReport>>(new Map());
|
||||
const error = ref(null);
|
||||
const loading = ref(false);
|
||||
//const ongoingFetch = ref<Promise<Publicreport[]> | null>(null);
|
||||
//const ongoingFetch = ref<Promise<PublicReport[]> | null>(null);
|
||||
|
||||
function add(pr: Publicreport) {
|
||||
function add(pr: PublicReport) {
|
||||
_byID.value.set(pr.id, pr);
|
||||
}
|
||||
// Actions
|
||||
async function byID(id: string): Promise<Publicreport | undefined> {
|
||||
async function byID(id: string): Promise<PublicReport | undefined> {
|
||||
loading.value = true;
|
||||
error.value = null;
|
||||
try {
|
||||
|
|
@ -23,8 +23,8 @@ export const useStorePublicreport = defineStore("publicreport", () => {
|
|||
if (!response.ok) {
|
||||
throw new Error(`HTTP error! status: ${response.status}`);
|
||||
}
|
||||
const body: PublicreportDTO = await response.json();
|
||||
const report = Publicreport.fromJSON(body);
|
||||
const body: PublicReportDTO = await response.json();
|
||||
const report = PublicReport.fromJSON(body);
|
||||
_byID.value.set(id, report);
|
||||
return report;
|
||||
} catch (err) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { SSEManager, SSEMessage } from "@/SSEManager";
|
||||
import { ReviewTask } from "@/types";
|
||||
import { ReviewTask } from "@/type/api";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
||||
export const useReviewTaskStore = defineStore("review-task", () => {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ import {
|
|||
SessionNotificationCounts,
|
||||
URLs,
|
||||
User,
|
||||
} from "@/types";
|
||||
} from "@/type/api";
|
||||
|
||||
export const useSessionStore = defineStore("session", () => {
|
||||
// State
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { Signal } from "@/types";
|
||||
import { Signal } from "@/type/api";
|
||||
import { SSEManager, type SSEMessage } from "@/SSEManager";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { Upload } from "@/types";
|
||||
import { Upload } from "@/type/api";
|
||||
import { SSEManager, type SSEMessage } from "@/SSEManager";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { defineStore } from "pinia";
|
||||
import { ref } from "vue";
|
||||
import { User } from "@/types";
|
||||
import { User } from "@/type/api";
|
||||
import { SSEManager, type SSEMessage } from "@/SSEManager";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
|
||||
|
|
|
|||
309
ts/type/api.ts
309
ts/type/api.ts
|
|
@ -9,6 +9,15 @@ export interface Address {
|
|||
street: string;
|
||||
unit: string;
|
||||
}
|
||||
export interface Bounds {
|
||||
min: Location;
|
||||
max: Location;
|
||||
}
|
||||
export interface Contact {
|
||||
has_email: boolean;
|
||||
has_phone: boolean;
|
||||
name?: string;
|
||||
}
|
||||
export interface District {
|
||||
name: string;
|
||||
phone_office: string;
|
||||
|
|
@ -38,6 +47,26 @@ export interface LogEntryDTO {
|
|||
type: string;
|
||||
user_id: number;
|
||||
}
|
||||
export interface CSVPoolDetailCount {
|
||||
existing: number;
|
||||
new: number;
|
||||
outside: number;
|
||||
}
|
||||
export interface CSVPoolError {
|
||||
column: number;
|
||||
line: number;
|
||||
message: string;
|
||||
}
|
||||
export interface Followup {
|
||||
description: string;
|
||||
id: number;
|
||||
title: string;
|
||||
}
|
||||
export interface Lead {
|
||||
description: string;
|
||||
id: number;
|
||||
title: string;
|
||||
}
|
||||
export class LogEntry {
|
||||
constructor(
|
||||
public created: Date,
|
||||
|
|
@ -54,43 +83,305 @@ export class LogEntry {
|
|||
);
|
||||
}
|
||||
}
|
||||
export interface PublicreportDTO {
|
||||
export interface Exif {
|
||||
created: string;
|
||||
make: string;
|
||||
model: string;
|
||||
}
|
||||
export interface Image {
|
||||
distance_from_reporter_meters?: number;
|
||||
exif: Exif;
|
||||
exif_make: string;
|
||||
exif_model: string;
|
||||
exif_datetime: string;
|
||||
location?: Location;
|
||||
report_id: number;
|
||||
url_content: string;
|
||||
uuid: string;
|
||||
}
|
||||
export interface Nuisance {
|
||||
additional_info: string;
|
||||
duration: string;
|
||||
is_location_backyard: boolean;
|
||||
is_location_frontyard: boolean;
|
||||
is_location_garden: boolean;
|
||||
is_location_other: boolean;
|
||||
is_location_pool: boolean;
|
||||
source_container: boolean;
|
||||
source_description: string;
|
||||
source_gutter: boolean;
|
||||
source_stagnant: boolean;
|
||||
time_of_day_day: boolean;
|
||||
time_of_day_early: boolean;
|
||||
time_of_day_evening: boolean;
|
||||
time_of_day_night: boolean;
|
||||
}
|
||||
export interface Water {
|
||||
access_comments: string;
|
||||
access_gate: boolean;
|
||||
access_fence: boolean;
|
||||
access_locked: boolean;
|
||||
access_dog: boolean;
|
||||
access_other: boolean;
|
||||
comments: string;
|
||||
has_adult: boolean;
|
||||
has_backyard_permission: boolean;
|
||||
has_larvae: boolean;
|
||||
has_pupae: boolean;
|
||||
is_reporter_confidential: boolean;
|
||||
is_reporter_owner: boolean;
|
||||
owner: Contact;
|
||||
}
|
||||
export interface PublicReportDTO {
|
||||
address: Address;
|
||||
created: string;
|
||||
district: string;
|
||||
id: string;
|
||||
image_count: number;
|
||||
images: Image[];
|
||||
location: Location;
|
||||
log: LogEntryDTO[];
|
||||
nuisance: Nuisance;
|
||||
reporter: Contact;
|
||||
status: string;
|
||||
type: string;
|
||||
water: Water;
|
||||
uri: string;
|
||||
}
|
||||
export class Publicreport {
|
||||
export class PublicReport {
|
||||
constructor(
|
||||
public address: Address,
|
||||
public created: Date,
|
||||
public district: string,
|
||||
public id: string,
|
||||
public image_count: number,
|
||||
public location: Location,
|
||||
public images: Image[],
|
||||
public log: LogEntry[],
|
||||
public reporter: Contact,
|
||||
public status: string,
|
||||
public type: string,
|
||||
public uri: string,
|
||||
public location?: Location,
|
||||
public nuisance?: Nuisance,
|
||||
public water?: Water,
|
||||
) {}
|
||||
static fromJSON(json: PublicreportDTO): Publicreport {
|
||||
return new Publicreport(
|
||||
static fromJSON(json: PublicReportDTO): PublicReport {
|
||||
return new PublicReport(
|
||||
json.address,
|
||||
new Date(json.created),
|
||||
json.district,
|
||||
json.id,
|
||||
json.image_count,
|
||||
json.location,
|
||||
json.images,
|
||||
json.log.map((l: LogEntryDTO) => LogEntry.fromJSON(l)),
|
||||
json.reporter,
|
||||
json.status,
|
||||
json.type,
|
||||
json.uri,
|
||||
json.location,
|
||||
json.nuisance,
|
||||
json.water,
|
||||
);
|
||||
}
|
||||
}
|
||||
export interface CommunicationDTO {
|
||||
created: string;
|
||||
id: string;
|
||||
public_report?: PublicReportDTO;
|
||||
type: string;
|
||||
}
|
||||
export class Communication {
|
||||
constructor(
|
||||
public created: Date,
|
||||
public id: string,
|
||||
public type: string,
|
||||
public public_report?: PublicReport,
|
||||
) {}
|
||||
static fromJSON(json: CommunicationDTO): Communication {
|
||||
return new Communication(
|
||||
new Date(json.created),
|
||||
json.id,
|
||||
json.type,
|
||||
json.public_report == undefined
|
||||
? undefined
|
||||
: PublicReport.fromJSON(json.public_report),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export interface Pool {
|
||||
condition: string;
|
||||
id: number;
|
||||
location: Location;
|
||||
site: Site;
|
||||
}
|
||||
export interface SignalDTO {
|
||||
address?: Address;
|
||||
addressed?: string;
|
||||
addressor?: number;
|
||||
created: string;
|
||||
creator: number;
|
||||
id: number;
|
||||
location: Location;
|
||||
pool?: Pool;
|
||||
report?: PublicReport;
|
||||
species?: string;
|
||||
type: string;
|
||||
}
|
||||
export class Signal {
|
||||
constructor(
|
||||
public created: Date,
|
||||
public creator: number,
|
||||
public id: number,
|
||||
public location: Location,
|
||||
public type: string,
|
||||
public address?: Address,
|
||||
public addressed?: string,
|
||||
public addressor?: number,
|
||||
public pool?: Pool,
|
||||
public report?: PublicReport,
|
||||
public species?: string,
|
||||
) {}
|
||||
static fromJSON(json: SignalDTO): Signal {
|
||||
return new Signal(
|
||||
new Date(json.created),
|
||||
json.creator,
|
||||
json.id,
|
||||
json.location,
|
||||
json.type,
|
||||
json.address,
|
||||
json.addressed,
|
||||
json.addressor,
|
||||
json.pool,
|
||||
json.report,
|
||||
json.species,
|
||||
);
|
||||
}
|
||||
}
|
||||
export interface Site {
|
||||
address: Address;
|
||||
created: string;
|
||||
creator_id: number;
|
||||
file_id: number;
|
||||
id: number;
|
||||
location: Location;
|
||||
notes: string;
|
||||
organization_id: number;
|
||||
owner?: Contact;
|
||||
parcel_id?: number;
|
||||
resident?: Contact;
|
||||
resident_owned: boolean;
|
||||
tags: Map<string, string>;
|
||||
version: number;
|
||||
}
|
||||
export interface ReviewTaskPool {
|
||||
condition: string;
|
||||
location: Location;
|
||||
owner: Contact;
|
||||
site: Site;
|
||||
}
|
||||
export interface ReviewTask {
|
||||
address: Address;
|
||||
addressed?: string;
|
||||
addressor?: User;
|
||||
created: string;
|
||||
creator: User;
|
||||
pool?: ReviewTaskPool;
|
||||
id: number;
|
||||
}
|
||||
export interface UploadDTO {
|
||||
created: string;
|
||||
filename: string;
|
||||
id: number;
|
||||
recordcount: number;
|
||||
status: string;
|
||||
type: string;
|
||||
csv_pool?: CSVPoolDetail;
|
||||
}
|
||||
export class Upload {
|
||||
constructor(
|
||||
public created: Date,
|
||||
public filename: string,
|
||||
public id: number,
|
||||
public recordcount: number,
|
||||
public status: string,
|
||||
public type: string,
|
||||
public csv_pool?: CSVPoolDetail,
|
||||
) {}
|
||||
static fromJSON(json: UploadDTO): Upload {
|
||||
return new Upload(
|
||||
new Date(json.created),
|
||||
json.filename,
|
||||
json.id,
|
||||
json.recordcount,
|
||||
json.status,
|
||||
json.type,
|
||||
json.csv_pool,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export interface UploadPoolRow {
|
||||
address: Address;
|
||||
condition: string;
|
||||
errors: UploadPoolError[];
|
||||
status: string;
|
||||
tags: Map<string, string>;
|
||||
}
|
||||
export interface UploadPoolError {
|
||||
column: number;
|
||||
line: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface CSVPoolDetail {
|
||||
count: CSVPoolDetailCount;
|
||||
errors: CSVPoolError[];
|
||||
pools: UploadPoolRow[];
|
||||
}
|
||||
export interface User {
|
||||
avatar: string;
|
||||
display_name: string;
|
||||
id: number;
|
||||
initials: string;
|
||||
is_active: boolean;
|
||||
role: string;
|
||||
tags: string[];
|
||||
uri: string;
|
||||
username: string;
|
||||
}
|
||||
export interface Organization {
|
||||
id: number;
|
||||
service_area?: Bounds;
|
||||
}
|
||||
export interface UserNotificationCounts {
|
||||
communication: number;
|
||||
home: number;
|
||||
review: number;
|
||||
}
|
||||
export interface SessionNotificationCounts {
|
||||
communication: number;
|
||||
home: number;
|
||||
review: number;
|
||||
}
|
||||
export interface Session {
|
||||
impersonating?: string;
|
||||
notifications: Notification[];
|
||||
notification_counts: SessionNotificationCounts;
|
||||
organization: Organization;
|
||||
self: User;
|
||||
urls: URLs;
|
||||
}
|
||||
export interface URLs {
|
||||
api: URLsAPI;
|
||||
tegola: string;
|
||||
tile: string;
|
||||
}
|
||||
// Define interfaces matching your Go structs
|
||||
interface URLsAPI {
|
||||
avatar: string;
|
||||
communication: string;
|
||||
impersonation: string;
|
||||
publicreport_message: string;
|
||||
review_task: string;
|
||||
signal: string;
|
||||
upload: string;
|
||||
user: string;
|
||||
}
|
||||
|
|
|
|||
224
ts/types.ts
224
ts/types.ts
|
|
@ -1,5 +1,5 @@
|
|||
import type { Map as MapLibreMap } from "maplibre-gl";
|
||||
import { Address, Location } from "@/type/api";
|
||||
import { Location } from "@/type/api";
|
||||
|
||||
export interface Bounds {
|
||||
min: Location;
|
||||
|
|
@ -10,58 +10,6 @@ export interface Changes {
|
|||
unchanged: string[];
|
||||
}
|
||||
|
||||
export interface Communication {
|
||||
created: string;
|
||||
id: string;
|
||||
public_report: PublicReport | null;
|
||||
type: string;
|
||||
}
|
||||
export interface Contact {
|
||||
has_email: boolean;
|
||||
has_phone: boolean;
|
||||
name?: string;
|
||||
}
|
||||
export interface CSVPoolDetailCount {
|
||||
existing: number;
|
||||
new: number;
|
||||
outside: number;
|
||||
}
|
||||
export interface CSVPoolError {
|
||||
column: number;
|
||||
line: number;
|
||||
message: string;
|
||||
}
|
||||
export interface CSVPoolDetail {
|
||||
count: CSVPoolDetailCount;
|
||||
errors: CSVPoolError[];
|
||||
pools: UploadPoolRow[];
|
||||
}
|
||||
export interface Exif {
|
||||
created: string;
|
||||
make: string;
|
||||
model: string;
|
||||
}
|
||||
export interface Followup {
|
||||
description: string;
|
||||
id: number;
|
||||
title: string;
|
||||
}
|
||||
export interface Image {
|
||||
distance_from_reporter_meters?: number;
|
||||
exif: Exif;
|
||||
exif_make: string;
|
||||
exif_model: string;
|
||||
exif_datetime: string;
|
||||
location?: Location;
|
||||
report_id: number;
|
||||
url_content: string;
|
||||
uuid: string;
|
||||
}
|
||||
export interface Lead {
|
||||
description: string;
|
||||
id: number;
|
||||
title: string;
|
||||
}
|
||||
export interface LogEntry {
|
||||
created: string;
|
||||
id: number;
|
||||
|
|
@ -82,177 +30,7 @@ export interface Marker {
|
|||
location: Location;
|
||||
}
|
||||
|
||||
export interface Nuisance {
|
||||
additional_info: string;
|
||||
duration: string;
|
||||
is_location_backyard: boolean;
|
||||
is_location_frontyard: boolean;
|
||||
is_location_garden: boolean;
|
||||
is_location_other: boolean;
|
||||
is_location_pool: boolean;
|
||||
source_container: boolean;
|
||||
source_description: string;
|
||||
source_gutter: boolean;
|
||||
source_stagnant: boolean;
|
||||
time_of_day_day: boolean;
|
||||
time_of_day_early: boolean;
|
||||
time_of_day_evening: boolean;
|
||||
time_of_day_night: boolean;
|
||||
}
|
||||
export interface Organization {
|
||||
id: number;
|
||||
service_area?: Bounds;
|
||||
}
|
||||
export interface Point {
|
||||
x: number;
|
||||
y: number;
|
||||
}
|
||||
export interface Pool {
|
||||
condition: string;
|
||||
id: number;
|
||||
location: Location;
|
||||
site: Site;
|
||||
}
|
||||
export interface PublicReport {
|
||||
address: Address;
|
||||
address_raw: string;
|
||||
created: string;
|
||||
images: Image[];
|
||||
location?: Location;
|
||||
log: LogEntry[];
|
||||
nuisance?: Nuisance;
|
||||
public_id: string;
|
||||
reporter: Contact;
|
||||
status: string;
|
||||
type: string;
|
||||
water?: Water;
|
||||
}
|
||||
export interface Signal {
|
||||
address?: Address;
|
||||
addressed?: string;
|
||||
addressor?: number;
|
||||
created: string;
|
||||
creator: number;
|
||||
id: number;
|
||||
location: Location;
|
||||
pool?: Pool;
|
||||
report?: PublicReport;
|
||||
species?: string;
|
||||
type: string;
|
||||
}
|
||||
export interface ReviewTask {
|
||||
address: Address;
|
||||
addressed?: string;
|
||||
addressor?: User;
|
||||
created: string;
|
||||
creator: User;
|
||||
pool?: ReviewTaskPool;
|
||||
id: number;
|
||||
}
|
||||
export interface ReviewTaskPool {
|
||||
condition: string;
|
||||
location: Location;
|
||||
owner: Contact;
|
||||
site: Site;
|
||||
}
|
||||
|
||||
export interface SessionNotificationCounts {
|
||||
communication: number;
|
||||
home: number;
|
||||
review: number;
|
||||
}
|
||||
export interface Session {
|
||||
impersonating?: string;
|
||||
notifications: Notification[];
|
||||
notification_counts: SessionNotificationCounts;
|
||||
organization: Organization;
|
||||
self: User;
|
||||
urls: URLs;
|
||||
}
|
||||
export interface Site {
|
||||
address: Address;
|
||||
created: string;
|
||||
creator_id: number;
|
||||
file_id: number;
|
||||
id: number;
|
||||
location: Location;
|
||||
notes: string;
|
||||
organization_id: number;
|
||||
owner?: Contact;
|
||||
parcel_id?: number;
|
||||
resident?: Contact;
|
||||
resident_owned: boolean;
|
||||
tags: Map<string, string>;
|
||||
version: number;
|
||||
}
|
||||
export interface Upload {
|
||||
created: string;
|
||||
filename: string;
|
||||
id: number;
|
||||
recordcount: number;
|
||||
status: string;
|
||||
type: string;
|
||||
csv_pool?: CSVPoolDetail;
|
||||
}
|
||||
export interface UploadPoolRow {
|
||||
address: Address;
|
||||
condition: string;
|
||||
errors: UploadPoolError[];
|
||||
status: string;
|
||||
tags: Map<string, string>;
|
||||
}
|
||||
export interface UploadPoolError {
|
||||
column: number;
|
||||
line: number;
|
||||
message: string;
|
||||
}
|
||||
|
||||
export interface URLs {
|
||||
api: URLsAPI;
|
||||
tegola: string;
|
||||
tile: string;
|
||||
}
|
||||
// Define interfaces matching your Go structs
|
||||
interface URLsAPI {
|
||||
avatar: string;
|
||||
communication: string;
|
||||
impersonation: string;
|
||||
publicreport_message: string;
|
||||
review_task: string;
|
||||
signal: string;
|
||||
upload: string;
|
||||
user: string;
|
||||
}
|
||||
|
||||
export interface User {
|
||||
avatar: string;
|
||||
display_name: string;
|
||||
id: number;
|
||||
initials: string;
|
||||
is_active: boolean;
|
||||
role: string;
|
||||
tags: string[];
|
||||
uri: string;
|
||||
username: string;
|
||||
}
|
||||
export interface UserNotificationCounts {
|
||||
communication: number;
|
||||
home: number;
|
||||
review: number;
|
||||
}
|
||||
export interface Water {
|
||||
access_comments: string;
|
||||
access_gate: boolean;
|
||||
access_fence: boolean;
|
||||
access_locked: boolean;
|
||||
access_dog: boolean;
|
||||
access_other: boolean;
|
||||
comments: string;
|
||||
has_adult: boolean;
|
||||
has_backyard_permission: boolean;
|
||||
has_larvae: boolean;
|
||||
has_pupae: boolean;
|
||||
is_reporter_confidential: boolean;
|
||||
is_reporter_owner: boolean;
|
||||
owner: Contact;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -68,7 +68,8 @@ import ToastNotification from "@/components/ToastNotification.vue";
|
|||
import { SSEManager } from "@/SSEManager";
|
||||
import { useCommunicationStore } from "@/store/communication";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import { Bounds, Communication, Marker } from "@/types";
|
||||
import type { Bounds, Marker } from "@/types";
|
||||
import type { Communication } from "@/type/api";
|
||||
|
||||
const communication = useCommunicationStore();
|
||||
const session = useSessionStore();
|
||||
|
|
|
|||
|
|
@ -67,8 +67,8 @@ import ThreeColumn from "@/components/layout/ThreeColumn.vue";
|
|||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { useSignalStore } from "@/store/signal";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import { Lead, Point, Signal } from "@/types";
|
||||
import type { Location } from "@/type/api";
|
||||
import type { Point } from "@/types";
|
||||
import type { Lead, Location, Signal } from "@/type/api";
|
||||
|
||||
// Refs
|
||||
const mapTile = ref(null);
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@
|
|||
import { computed, onMounted } from "vue";
|
||||
import TimeRelative from "@/components/TimeRelative.vue";
|
||||
import { useUploadStore } from "@/store/upload";
|
||||
import { Upload } from "@/types";
|
||||
import { Upload } from "@/type/api";
|
||||
|
||||
const uploadStore = useUploadStore();
|
||||
const uploads = computed((): Upload[] | null => {
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@ import { useRouter } from "vue-router";
|
|||
import MapMultipoint from "@/components/MapMultipoint.vue";
|
||||
import { useUploadStore } from "@/store/upload";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import { CSVPoolDetail, CSVPoolError, Upload, UploadPoolRow } from "@/types";
|
||||
import { CSVPoolDetail, CSVPoolError, Upload, UploadPoolRow } from "@/type/api";
|
||||
|
||||
interface ErrorMessage {
|
||||
message: string;
|
||||
|
|
|
|||
|
|
@ -103,7 +103,7 @@
|
|||
import { onMounted, ref } from "vue";
|
||||
import { computedAsync } from "@vueuse/core";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import { User } from "@/types";
|
||||
import { User } from "@/type/api";
|
||||
|
||||
interface URLConfiguration {
|
||||
userAdd: string;
|
||||
|
|
|
|||
|
|
@ -259,7 +259,7 @@ pre {
|
|||
import { onMounted, ref, toRaw } from "vue";
|
||||
import { useSessionStore } from "@/store/session";
|
||||
import { useUserStore } from "@/store/user";
|
||||
import { User } from "@/types";
|
||||
import { User } from "@/type/api";
|
||||
|
||||
interface Props {
|
||||
id: number;
|
||||
|
|
|
|||
|
|
@ -98,15 +98,9 @@ import ThreeColumn from "@/components/layout/ThreeColumn.vue";
|
|||
import ReviewPoolColumnAction from "@/components/ReviewPoolColumnAction.vue";
|
||||
import ReviewPoolColumnDetail from "@/components/ReviewPoolColumnDetail.vue";
|
||||
import ReviewPoolColumnList from "@/components/ReviewPoolColumnList.vue";
|
||||
import {
|
||||
Bounds,
|
||||
Changes,
|
||||
Contact,
|
||||
MapClickEvent,
|
||||
Marker,
|
||||
ReviewTask,
|
||||
} from "@/types";
|
||||
import type { Location } from "@/type/api";
|
||||
import type { Changes } from "@/types";
|
||||
import { Contact, Location, ReviewTask } from "@/type/api";
|
||||
import { Bounds, MapClickEvent, Marker } from "@/types";
|
||||
|
||||
interface FormData {
|
||||
latitude: number;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue