bug fixes, improvements
@@ -7,6 +7,11 @@
|
|||||||
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png">
|
||||||
<link rel="manifest" href="/site.webmanifest">
|
<link rel="manifest" href="/site.webmanifest">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta property="og:title" content="DeFlock" />
|
||||||
|
<meta property="og:description" content="Your car is being tracked. See where license plate readers are, avoid them, and report new ones. Protect your privacy at Deflock.me." />
|
||||||
|
<meta property="og:image" content="https://deflock.me/og-banner.png" />
|
||||||
|
<meta property="og:url" content="https://deflock.me" />
|
||||||
|
<meta property="og:type" content="website" />
|
||||||
<title>DeFlock - ALPR Database</title>
|
<title>DeFlock - ALPR Database</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|||||||
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 90 KiB |
|
After Width: | Height: | Size: 108 KiB |
|
After Width: | Height: | Size: 159 KiB |
|
After Width: | Height: | Size: 139 KiB |
|
After Width: | Height: | Size: 253 KiB |
|
After Width: | Height: | Size: 405 KiB |
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container max-width="1000">
|
||||||
<h2>About Us</h2>
|
<h2>About Us</h2>
|
||||||
<p>
|
<p>
|
||||||
Welcome to DeFlock, your go-to resource for understanding and addressing the growing presence of Automated License Plate Readers (ALPRs) in our communities.
|
Welcome to DeFlock, your go-to resource for understanding and addressing the growing presence of Automated License Plate Readers (ALPRs) in our communities.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container max-width="1000">
|
||||||
<h2>Contact Us</h2>
|
<h2>Contact Us</h2>
|
||||||
<p>
|
<p>
|
||||||
If you have any questions or concerns about the data on this site, please contact us at <a href="mailto:contact@deflock.me">contact@deflock.me</a>.
|
If you have any questions or concerns about the data on this site, please contact us at <a href="mailto:contact@deflock.me">contact@deflock.me</a>.
|
||||||
|
|||||||
@@ -24,13 +24,13 @@
|
|||||||
:key="alpr.id"
|
:key="alpr.id"
|
||||||
:lat-lng="[alpr.lat, alpr.lon]"
|
:lat-lng="[alpr.lat, alpr.lon]"
|
||||||
><l-popup>
|
><l-popup>
|
||||||
<h2>ALPR</h2>
|
<p class="mb-0 mt-2" v-if="alpr.tags.brand || alpr.tags.operator"><strong>Brand: </strong><a target="_blank" :href="`https://www.wikidata.org/wiki/${alpr.tags['brand:wikidata'] || alpr.tags['operator:wikidata']}`">{{ alpr.tags.brand || alpr.tags.operator || 'Unknown' }}</a></p>
|
||||||
<p v-if="alpr.tags.brand || alpr.tags.operator"><strong>Brand: </strong><a target="_blank" :href="`https://www.wikidata.org/wiki/${alpr.tags['brand:wikidata'] || alpr.tags['operator:wikidata']}`">{{ alpr.tags.brand || alpr.tags.operator || 'Unknown' }}</a></p>
|
<p class="my-0" v-if="alpr.tags.direction"><strong>Faces: {{ degreesToCardinal(alpr.tags.direction) }} {{ alpr.tags.direction }}°</strong></p>
|
||||||
<p v-if="alpr.tags.direction"><strong>Faces: {{ degreesToCardinal(alpr.tags.direction) }}</strong></p>
|
|
||||||
</l-popup></l-marker>
|
</l-popup></l-marker>
|
||||||
</l-map>
|
</l-map>
|
||||||
<div v-else>
|
<div class="loader" v-else>
|
||||||
loading...
|
<span class="mb-4 text-grey">Loading Map</span>
|
||||||
|
<v-progress-circular indeterminate color="primary" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -44,7 +44,7 @@ import type { Ref } from 'vue';
|
|||||||
import { BoundingBox } from '@/services/apiService';
|
import { BoundingBox } from '@/services/apiService';
|
||||||
import { getALPRs } from '@/services/apiService';
|
import { getALPRs } from '@/services/apiService';
|
||||||
|
|
||||||
const zoom: Ref<number> = ref(12);
|
const zoom: Ref<number> = ref(13);
|
||||||
const center: Ref<any|null> = ref(null);
|
const center: Ref<any|null> = ref(null);
|
||||||
const bounds: Ref<BoundingBox|null> = ref(null);
|
const bounds: Ref<BoundingBox|null> = ref(null);
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
@@ -115,13 +115,15 @@ function updateMarkers() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!canRefreshMarkers.value) {
|
if (!canRefreshMarkers.value) {
|
||||||
console.log('zoomed out too far');
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
getALPRs(bounds.value)
|
getALPRs(bounds.value)
|
||||||
.then((alprs: any) => {
|
.then((alprs: any) => {
|
||||||
alprsInView.value = alprs.elements;
|
// merge incoming with existing, so that moving the map doesn't remove markers
|
||||||
|
const existingIds = new Set(alprsInView.value.map(alpr => alpr.id));
|
||||||
|
const newAlprs = alprs.elements.filter((alpr: any) => !existingIds.has(alpr.id));
|
||||||
|
alprsInView.value = [...alprsInView.value, ...newAlprs];
|
||||||
bboxForLastRequest.value = bounds.value;
|
bboxForLastRequest.value = bounds.value;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -149,6 +151,10 @@ onMounted(() => {
|
|||||||
.then(location => {
|
.then(location => {
|
||||||
if (!hash)
|
if (!hash)
|
||||||
center.value = { lat: location[0], lng: location[1] };
|
center.value = { lat: location[0], lng: location[1] };
|
||||||
|
}).catch(error => {
|
||||||
|
// TODO: allow search
|
||||||
|
console.debug('Error getting user location. Defaulting to Huntsville, AL.', error);
|
||||||
|
center.value = { lat: 34.730819, lng: -86.586114 }; // Huntsville, AL
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -167,10 +173,25 @@ onMounted(() => {
|
|||||||
bottom: 32px;
|
bottom: 32px;
|
||||||
left: 32px;
|
left: 32px;
|
||||||
width: calc(100% - 64px);
|
width: calc(100% - 64px);
|
||||||
|
max-width: 1000px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background-color: rgba(0, 0, 0, 0.8);
|
background-color: rgba(0, 0, 0, 0.6);
|
||||||
border-radius: 4px;
|
border-radius: 4px;
|
||||||
padding: 4px;
|
padding: 4px;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.loader {
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container max-width="1000">
|
||||||
<v-alert
|
<v-alert
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
type="info"
|
type="info"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container max-width="1000">
|
||||||
<h1>Feature Roadmap</h1>
|
<h1>Feature Roadmap</h1>
|
||||||
|
|
||||||
<h2>Current Features</h2>
|
<h2>Current Features</h2>
|
||||||
@@ -17,6 +17,11 @@
|
|||||||
|
|
||||||
<h2>Upcoming Features</h2>
|
<h2>Upcoming Features</h2>
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
|
<h3><v-icon start>mdi-magnify</v-icon>Search Functionality</h3>
|
||||||
|
<p>
|
||||||
|
Search the map for specific locations, cities, or regions.
|
||||||
|
</p>
|
||||||
|
|
||||||
<h3><v-icon start>mdi-map-marker-plus</v-icon>Report an ALPR on this Site</h3>
|
<h3><v-icon start>mdi-map-marker-plus</v-icon>Report an ALPR on this Site</h3>
|
||||||
<p>
|
<p>
|
||||||
Report ALPRs directly from this site, without having to use the OSM Editor or copy and paste object tags.
|
Report ALPRs directly from this site, without having to use the OSM Editor or copy and paste object tags.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<v-container>
|
<v-container max-width="1000">
|
||||||
<p>
|
<p>
|
||||||
<v-img max-height="350" width="100%" cover src="/flock-camera.jpeg" />
|
<v-img max-height="350" width="100%" cover src="/flock-camera.jpeg" />
|
||||||
</p>
|
</p>
|
||||||
@@ -31,9 +31,18 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h2 id="not-alpr" :class="{ highlighted: route.hash === '#not-alpr' }">What They Look Like</h2>
|
<h2 id="not-alpr" :class="{ highlighted: route.hash === '#not-alpr' }">What They Look Like</h2>
|
||||||
<v-img class="my-4" width="400" src="/flock-camera.jpeg" />
|
<v-carousel class="my-4" hide-delimiters>
|
||||||
|
<v-carousel-item
|
||||||
|
v-for="n in carouselCount"
|
||||||
|
:key="n"
|
||||||
|
aspect-ratio="1"
|
||||||
|
:src="`/flock-${n}.jpg`"
|
||||||
|
></v-carousel-item>
|
||||||
|
</v-carousel>
|
||||||
|
|
||||||
|
|
||||||
<p>
|
<p>
|
||||||
The most common brand of ALPRs in the US is Flock Safety. They are easy to spot because they almost all look the same. They are usually mounted on a standalone black pole with a solar panel on top. The cameras are often placed near intersections or on main roads at the edge of a city or town.
|
The most common brand of ALPRs in the US is <a href="https://en.wikipedia.org/wiki/Flock_Safety" target="_blank">Flock Safety</a>. They are easy to spot because they almost all look the same. They are almost always mounted on a pole with a solar panel on top. In rural areas, they are likely to be on standalone black poles, while in cities, they are more likely to be on existing utility/traffic poles. The cameras are often placed near intersections or on main roads at the edge of a city or town.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<h2>Not All Cameras are ALPRs</h2>
|
<h2>Not All Cameras are ALPRs</h2>
|
||||||
@@ -66,6 +75,8 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useRoute } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
|
|
||||||
|
const carouselCount = 6;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
|||||||