Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
355 changes: 355 additions & 0 deletions webapp/bun.lock

Large diffs are not rendered by default.

Binary file modified webapp/public/map-interface-nationwide.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added webapp/public/new-df-map.webp
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions webapp/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ onMounted(() => {

const items = [
{ title: 'Home', icon: 'mdi-home', to: '/' },
{ title: 'Map', icon: 'mdi-map', to: '/map' },
{ title: 'Map', icon: 'mdi-map', href: 'https://maps.deflock.org' },
{ title: 'Learn', icon: 'mdi-school', to: '/what-is-an-alpr' },
{ title: 'News', icon: 'mdi-newspaper', to: '/blog' },
]
Expand Down Expand Up @@ -95,10 +95,11 @@ watch(() => theme.global.name.value, (newTheme) => {
<div class="d-none d-md-flex ml-8 flex-grow-1">
<!-- Main navigation items -->
<div class="d-flex align-center">
<v-btn
v-for="item in items.slice(1)"
<v-btn
v-for="item in items.slice(1)"
:key="item.title"
:to="item.to"
:href="item.href"
variant="text"
class="mx-1"
:prepend-icon="item.icon"
Expand Down Expand Up @@ -196,6 +197,7 @@ watch(() => theme.global.name.value, (newTheme) => {
:key="item.title"
link
:to="item.to"
:href="item.href"
role="option"
>
<v-icon start>{{ item.icon }}</v-icon>
Expand Down
76 changes: 76 additions & 0 deletions webapp/src/components/NewMapNotice.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<template>
<v-dialog v-model="show" max-width="500" persistent>
<v-card>
<v-btn icon variant="text" size="small" @click="dismiss" style="position: absolute; top: 10px; right: 10px;">
<v-icon>mdi-close</v-icon>
</v-btn>
<v-card-title class="text-center py-4 font-weight-bold">
<h3 class="headline">Try Our New Map</h3>
</v-card-title>
<v-card-text>
<v-img src="/new-df-map.webp" alt="New Map" contain max-width="500" class="mx-auto mb-4 w-full rounded" />
<v-list density="compact" class="py-0">
<v-list-item prepend-icon="mdi-lightning-bolt">Faster Performance</v-list-item>
<v-list-item prepend-icon="mdi-routes">ALPR-Avoidance Routing</v-list-item>
<v-list-item prepend-icon="mdi-share-variant">Network Sharing</v-list-item>
</v-list>
</v-card-text>
<v-card-actions class="flex-column px-4 pb-4 gap-2">
<v-btn
block
size="large"
color="rgb(18, 151, 195)"
variant="elevated"
:href="newMapUrl"
@click="goToNewMap"
>
Continue in New Map
<v-icon end>mdi-arrow-right</v-icon>
</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script setup lang="ts">
import { ref, computed, onMounted } from 'vue';

const STORAGE_KEY = 'new-map-notice-dismissed';

const comingFromNewMap = document.referrer.includes('maps.deflock.org');
const isIframe = window.self !== window.top;
const show = ref(false);

onMounted(() => {
if (!comingFromNewMap && !isIframe && !localStorage.getItem(STORAGE_KEY)) {
show.value = true;
}
});

const newMapUrl = computed(() => {
const hash = window.location.hash;
const match = hash.match(/^#map=([\d.]+)\/([-\d.]+)\/([-\d.]+)/);
if (match) {
const zoom = parseFloat(match[1]).toFixed(2);
const lat = match[2];
const lng = match[3];
return `https://maps.deflock.org/?lat=${lat}&lng=${lng}&zoom=${zoom}`;
}
return 'https://maps.deflock.org';
});

function dismiss() {
show.value = false;
localStorage.setItem(STORAGE_KEY, 'true');
}

function goToNewMap() {
localStorage.setItem(STORAGE_KEY, 'true');
}
</script>

<style scoped>
.gap-2 {
gap: 8px;
}
</style>
63 changes: 0 additions & 63 deletions webapp/src/components/NewVisitor.vue

This file was deleted.

3 changes: 1 addition & 2 deletions webapp/src/router/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { createRouter, createWebHistory } from 'vue-router'
import Landing from '../views/Landing.vue'
import Map from '../views/Map.vue'
import { useHead } from '@unhead/vue'

const router = createRouter({
Expand All @@ -27,7 +26,7 @@ const router = createRouter({
{
path: '/map',
name: 'map',
component: Map,
component: () => import('../views/Map.vue'),
meta: {
title: 'ALPR Map | DeFlock'
}
Expand Down
31 changes: 4 additions & 27 deletions webapp/src/views/Landing.vue
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,8 @@

<ALPRCounter class="my-6" />

<v-btn size="large" color="rgb(18, 151, 195)" large @click="goToMap({ withCurrentLocation: true })">
Explore the Map
<v-btn size="large" color="rgb(18, 151, 195)" large href="https://maps.deflock.org">
Launch the Map
<v-icon end>mdi-map</v-icon>
</v-btn>
</v-col>
Expand Down Expand Up @@ -151,8 +151,8 @@
<!-- Map Section -->
<v-container fluid class="map-section py-10 text-center">
<h2 class="display-2 mb-4">Explore ALPR Locations Near You</h2>
<v-btn color="white" large @click="goToMap({ withCurrentLocation: true })">
View the Map
<v-btn color="white" large href="https://maps.deflock.org">
Launch the Map
<v-icon end>mdi-map</v-icon>
</v-btn>
</v-container>
Expand Down Expand Up @@ -259,14 +259,9 @@

<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import ALPRCounter from '@/components/ALPRCounter.vue';
import { useGlobalStore } from '@/stores/global';
import DefaultLayout from '@/layouts/DefaultLayout.vue';

const router = useRouter();
const { setCurrentLocation } = useGlobalStore();

interface ServiceAlert {
id: number;
date_updated: string | null;
Expand Down Expand Up @@ -294,22 +289,4 @@ onMounted(() => {
fetchServiceAlert();
});

interface GoToMapOptions {
withCurrentLocation?: boolean;
}

async function goToMap(options: GoToMapOptions = {}) {
if (options.withCurrentLocation) {
setCurrentLocation()
.then((currentLocation) => {
const [lat, lon] = currentLocation;
router.push({ path: '/map', hash: `#map=12/${lat.toFixed(6)}/${lon.toFixed(6)}` });
})
.catch(() => {
router.push({ path: '/map' });
});
} else {
router.push({ path: '/map' });
}
}
</script>
4 changes: 2 additions & 2 deletions webapp/src/views/Map.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<NewVisitor v-if="!isIframe" />
<NewMapNotice v-if="!isIframe" />
<ShareDialog v-model="shareDialogOpen" />

<div class="map-container" @keyup="handleKeyUp">
Expand Down Expand Up @@ -72,7 +72,7 @@ import L from 'leaflet';
globalThis.L = L;
import 'leaflet/dist/leaflet.css'
import LeafletMap from '@/components/LeafletMap.vue';
import NewVisitor from '@/components/NewVisitor.vue';
import NewMapNotice from '@/components/NewMapNotice.vue';
import ShareDialog from '@/components/ShareDialog.vue';

const DEFAULT_ZOOM = 12;
Expand Down
13 changes: 1 addition & 12 deletions webapp/src/views/Press.vue
Original file line number Diff line number Diff line change
Expand Up @@ -28,17 +28,7 @@

<h2>Embedding our Map</h2>
<p>
You are welcome to embed our map on your website. Use the following HTML snippet:
</p>

<p>
<DFCode>
&lt;iframe src=&quot;https://deflock.org/map&quot; width=&quot;100%&quot; height=&quot;600&quot; style=&quot;border: none;&quot;&gt;&lt;/iframe&gt;
</DFCode>
</p>

<p>
If you would like to <b>localize the URL</b> to a specific region, please zoom to the area at <router-link to="/map">https://deflock.org/map</router-link> and copy the URL from your browser's address bar.
You are welcome to embed our map on your website. Simply <a href="https://maps.deflock.org" target="_blank">click the share button on our map</a>, and copy the embed code.
</p>

<h2>Contact Us</h2>
Expand All @@ -53,5 +43,4 @@
<script setup lang="ts">
import DefaultLayout from '@/layouts/DefaultLayout.vue';
import Hero from '@/components/layout/Hero.vue';
import DFCode from "@/components/DFCode.vue";
</script>
5 changes: 5 additions & 0 deletions webapp/src/views/PrivacyPolicy.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@
DeFlock does not collect, store, or process any personal information about our users. We use local storage in your browser to anonymously identify first-time visitors for the purpose of showing an introductory message as well as to persist application state, including your dark/light theme preference. This data cannot be used to identify you personally. We do not use cookies, analytics, or tracking technologies on our website.
</p>

<h2>Route Calculation (maps.deflock.org)</h2>
<p>
On our maps page (<a href="https://maps.deflock.org">maps.deflock.org</a>), we offer a route planning feature that calculates routes designed to avoid ALPR cameras. When you request a route, your start and end coordinates are sent to our server solely for the purpose of computing the route. These coordinates are not logged or retained long-term.
</p>

<h2>Third-Party Services</h2>
<p>
DeFlock relies on OpenStreetMap (OSM) for map data and functionality. If you choose to contribute Automatic License Plate Recognition (ALPR) data or other content to OSM, you will interact directly with their platform. OSM may request personal information, such as your email address and name, to facilitate your contributions. Please refer to the OpenStreetMap Privacy Policy for details on their data practices.
Expand Down