mirror of
https://github.com/FoggedLens/deflock.git
synced 2026-07-06 04:18:00 +02:00
Minor Improvements (#24)
* remove dangers page, fix counter * fix bad instrucitons * cleanup * allow nonstandard direction tag, link to OSM * update privacy policy to account for intro message
This commit is contained in:
@@ -12,6 +12,13 @@ import { useDisplay } from 'vuetify'
|
||||
import { getALPRCounts } from '@/services/apiService';
|
||||
import { CountUp } from 'countup.js';
|
||||
|
||||
const props = defineProps({
|
||||
delayMs: {
|
||||
type: Number,
|
||||
default: 200,
|
||||
}
|
||||
});
|
||||
|
||||
const counterEl: Ref<HTMLElement|null> = ref(null);
|
||||
const countupOptions = {
|
||||
useEasing: true,
|
||||
@@ -33,13 +40,17 @@ const counts: Ref<Counts> = ref({
|
||||
const showFinalAnimation = ref(false);
|
||||
const { xs: isMobile } = useDisplay();
|
||||
|
||||
let timeOfMount: number|undefined = undefined;
|
||||
|
||||
onMounted(() => {
|
||||
getALPRCounts().then((response) => {
|
||||
counts.value = response;
|
||||
timeOfMount = new Date().getTime();
|
||||
getALPRCounts().then((countResponse) => {
|
||||
counts.value = countResponse;
|
||||
countUp(countResponse);
|
||||
});
|
||||
});
|
||||
|
||||
watch(counts, (newCounts: Counts) => {
|
||||
function countUp(newCounts: Counts) {
|
||||
if (!newCounts.worldwide) return;
|
||||
if (!counterEl.value) {
|
||||
console.error('Counter element not found');
|
||||
@@ -48,14 +59,23 @@ watch(counts, (newCounts: Counts) => {
|
||||
|
||||
if (!counter) {
|
||||
counter = new CountUp(counterEl.value, newCounts.worldwide, countupOptions);
|
||||
setTimeout(() => {
|
||||
counter?.start();
|
||||
}, 500);
|
||||
|
||||
if (timeOfMount) {
|
||||
const timeSinceMount = new Date().getTime() - timeOfMount;
|
||||
if (timeSinceMount < props.delayMs) {
|
||||
setTimeout(() => {
|
||||
counter?.start();
|
||||
}, props.delayMs - timeSinceMount);
|
||||
} else {
|
||||
counter.start();
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
showFinalAnimation.value = true;
|
||||
}, 3000);
|
||||
}, 2500);
|
||||
}
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
{{ alpr.tags.brand }}
|
||||
</span>
|
||||
<span v-else>
|
||||
Unknown Manufacturer
|
||||
Unspecified Manufacturer
|
||||
</span>
|
||||
</b>
|
||||
</v-list-item>
|
||||
@@ -32,19 +32,14 @@
|
||||
{{ alpr.tags.operator }}
|
||||
</span>
|
||||
<span v-else>
|
||||
Unknown Operator
|
||||
Unspecified Operator
|
||||
</span>
|
||||
</b>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<div class="text-center text-grey-darken-1">
|
||||
|
||||
<v-tooltip open-delay="500" text="OSM Node ID" location="bottom">
|
||||
<template #activator="{ props }">
|
||||
<span style="font-size: 0.9em; cursor: default" v-bind="props">node/{{ alpr.id }}</span>
|
||||
</template>
|
||||
</v-tooltip>
|
||||
<div class="text-center">
|
||||
<v-btn target="_blank" size="x-small" :href="osmNodeLink(props.alpr.id)" variant="text" color="grey-darken-1"><v-icon start>mdi-open-in-new</v-icon>View on OSM</v-btn>
|
||||
</div>
|
||||
</v-sheet>
|
||||
</template>
|
||||
@@ -53,7 +48,7 @@
|
||||
import { defineProps, computed } from 'vue';
|
||||
import type { PropType } from 'vue';
|
||||
import type { ALPR } from '@/types';
|
||||
import { VIcon, VList, VSheet, VListItem, VTooltip } from 'vuetify/components';
|
||||
import { VIcon, VList, VSheet, VListItem, VBtn } from 'vuetify/components';
|
||||
|
||||
const props = defineProps({
|
||||
alpr: {
|
||||
@@ -64,12 +59,18 @@ const props = defineProps({
|
||||
|
||||
const isFaceRecognition = computed(() => props.alpr.tags.brand === 'Avigilon');
|
||||
|
||||
const cardinalDirection = computed(() =>
|
||||
props.alpr.tags.direction === undefined ? 'Unknown Direction' : degreesToCardinal(parseInt(props.alpr.tags.direction))
|
||||
const cardinalDirection = computed(() => {
|
||||
const direction = props.alpr.tags.direction || props.alpr.tags["camera:direction"];
|
||||
return direction === undefined ? 'Unspecified Direction' : degreesToCardinal(parseInt(direction))
|
||||
}
|
||||
);
|
||||
|
||||
function degreesToCardinal(degrees: number): string {
|
||||
const cardinals = ['North', 'Northeast', 'East', 'Southeast', 'South', 'Southwest', 'West', 'Northwest'];
|
||||
return 'Faces ' + cardinals[Math.round(degrees / 45) % 8];
|
||||
}
|
||||
|
||||
function osmNodeLink(id: string): string {
|
||||
return `https://www.openstreetmap.org/node/${id}`;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -56,7 +56,7 @@ let currentLocationLayer: FeatureGroup;
|
||||
|
||||
// Marker Creation Utilities
|
||||
function createSVGMarker(alpr: ALPR): string {
|
||||
const orientationDegrees = alpr.tags.direction;
|
||||
const orientationDegrees = alpr.tags.direction || alpr.tags['camera:direction'];
|
||||
const fovPath = `
|
||||
<path class="someSVGpath" d="M215.248,221.461L99.696,43.732C144.935,16.031 198.536,0 256,0C313.464,0 367.065,16.031 412.304,43.732L296.752,221.461C287.138,209.593 272.448,202.001 256,202.001C239.552,202.001 224.862,209.593 215.248,221.461Z" style="fill:rgb(87,87,87);fill-opacity:0.46;"/>
|
||||
<path class="someSVGpath" d="M215.248,221.461L99.696,43.732C144.935,16.031 198.536,0 256,0C313.464,0 367.065,16.031 412.304,43.732L296.752,221.461C287.138,209.593 272.448,202.001 256,202.001C239.552,202.001 224.862,209.593 215.248,221.461ZM217.92,200.242C228.694,192.652 241.831,188.195 256,188.195C270.169,188.195 283.306,192.652 294.08,200.242C294.08,200.242 392.803,48.4 392.803,48.4C352.363,26.364 305.694,13.806 256,13.806C206.306,13.806 159.637,26.364 119.197,48.4L217.92,200.242Z" style="fill:rgb(137,135,135);"/>
|
||||
@@ -73,7 +73,7 @@ function createSVGMarker(alpr: ALPR): string {
|
||||
}
|
||||
|
||||
function createMarker(alpr: ALPR): Marker | CircleMarker {
|
||||
if (hasPlottableOrientation(alpr.tags.direction)) {
|
||||
if (hasPlottableOrientation(alpr.tags.direction || alpr.tags['camera:direction'])) {
|
||||
const icon = L.divIcon({
|
||||
className: 'leaflet-data-marker',
|
||||
html: createSVGMarker(alpr),
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<v-dialog v-model="show" max-width="900">
|
||||
<v-card>
|
||||
<v-card-title class="text-center py-4 font-weight-bold">
|
||||
<h3 class="headline">Welcome to DeFlock</h3>
|
||||
</v-card-title>
|
||||
<p class="mx-8 text-center">
|
||||
DeFlock is powered by <b>crowdsourced data</b> from the OpenStreetMap community.
|
||||
</p>
|
||||
|
||||
<v-divider class="mx-4 mt-4" />
|
||||
|
||||
<v-list class="text-center">
|
||||
<v-list-item class="my-4">
|
||||
<v-icon size="x-large" color="primary" class="mb-2">mdi-progress-pencil</v-icon>
|
||||
<v-list-item-title class="font-weight-bold">The map is incomplete!</v-list-item-title>
|
||||
<v-list-item-subtitle>The ALPRs displayed here are a starting point, and new locations are constantly being added.</v-list-item-subtitle>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
|
||||
<div class="small text-grey-darken-2 text-center mx-4 mb-2">By using this site, you agree to our <router-link to="/terms">Terms of Service</router-link>.</div>
|
||||
<v-card-actions>
|
||||
<v-btn flat class="w-100" size="x-large" color="rgb(18, 151, 195)" variant="elevated" @click="acknowledge">Got it</v-btn>
|
||||
</v-card-actions>
|
||||
</v-card>
|
||||
</v-dialog>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue';
|
||||
|
||||
const show = ref(false);
|
||||
|
||||
onMounted(() => {
|
||||
if (!localStorage.getItem('acknowledged')) {
|
||||
show.value = true;
|
||||
}
|
||||
});
|
||||
|
||||
function acknowledge() {
|
||||
show.value = false;
|
||||
localStorage.setItem('acknowledged', 'true');
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.no-small {
|
||||
min-width: 160px;
|
||||
}
|
||||
|
||||
.small {
|
||||
font-size: 0.8rem;
|
||||
}
|
||||
</style>
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<v-row class="align-center justify-center my-4">
|
||||
<v-col cols="12" sm="6">
|
||||
<v-col cols="12" sm="6" class="text-center">
|
||||
<v-select
|
||||
color="rgb(18, 151, 195)"
|
||||
prepend-inner-icon="mdi-factory"
|
||||
@@ -22,6 +22,7 @@
|
||||
max-width="100%"
|
||||
class="my-4"
|
||||
></v-img>
|
||||
<v-btn to="/what-is-an-alpr#photos" color="grey-darken-2" variant="text" size="small"><v-icon start>mdi-image-multiple</v-icon> See All Photos</v-btn>
|
||||
</v-col>
|
||||
|
||||
<v-col cols="12" sm="6">
|
||||
@@ -56,25 +57,25 @@ const alprBrands: WikidataItem[] = [
|
||||
name: 'Flock Safety',
|
||||
nickname: 'Flock',
|
||||
wikidata: 'Q108485435',
|
||||
exampleImage: '/flock-1.jpg',
|
||||
exampleImage: '/alprs/flock-1.jpg',
|
||||
},
|
||||
{
|
||||
name: 'Motorola Solutions',
|
||||
nickname: 'Motorola/Vigilant',
|
||||
wikidata: 'Q634815',
|
||||
exampleImage: '/vigilant-1.jpg',
|
||||
exampleImage: '/alprs/motorola-4.jpg',
|
||||
},
|
||||
{
|
||||
name: 'Leonardo',
|
||||
nickname: 'Leonardo/ELSAG',
|
||||
wikidata: 'Q910379',
|
||||
exampleImage: '/elsag.webp',
|
||||
exampleImage: '/alprs/elsag-1.jpg',
|
||||
},
|
||||
{
|
||||
name: 'Neology, Inc.',
|
||||
nickname: 'Neology',
|
||||
wikidata: 'Q130958232',
|
||||
exampleImage: '/neology-1.jpg',
|
||||
exampleImage: '/alprs/neology-2.jpg',
|
||||
},
|
||||
{
|
||||
name: '(brand goes here)',
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
<div>
|
||||
<p>© {{ currentYear }} DeFlock. All Rights Reserved</p>
|
||||
<p>Map data © <a href="https://www.openstreetmap.org/copyright" target="_blank" style="color: unset; font-weight: normal;">OpenStreetMap contributors</a></p>
|
||||
<p class="mt-4">v1.0</p>
|
||||
<p class="mt-4">v1.0.1</p>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
|
||||
Reference in New Issue
Block a user