diff --git a/webapp/index.html b/webapp/index.html index c80d13d..f074ce2 100644 --- a/webapp/index.html +++ b/webapp/index.html @@ -6,6 +6,9 @@ + + + @@ -14,16 +17,6 @@ DeFlock - ALPR Database -
diff --git a/webapp/package-lock.json b/webapp/package-lock.json index 1b9e9de..0d0f120 100644 --- a/webapp/package-lock.json +++ b/webapp/package-lock.json @@ -8,6 +8,7 @@ "name": "deflock", "version": "0.0.0", "dependencies": { + "@unhead/vue": "^1.11.14", "axios": "^1.7.7", "countup.js": "^2.8.0", "vue": "^3.4.29", @@ -678,6 +679,59 @@ "undici-types": "~6.19.2" } }, + "node_modules/@unhead/dom": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.11.14.tgz", + "integrity": "sha512-FaHCWo9JR4h7PCpSRaXuMC6ifXOuBzlI0PD1MmUcxND2ayDl1d6DauIbN8TUf9TDRxNkrK1Ehb0OCXjC1ZJtrg==", + "dependencies": { + "@unhead/schema": "1.11.14", + "@unhead/shared": "1.11.14" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/schema": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.11.14.tgz", + "integrity": "sha512-V9W9u5tF1/+TiLqxu+Qvh1ShoMDkPEwHoEo4DKdDG6ko7YlbzFfDxV6el9JwCren45U/4Vy/4Xi7j8OH02wsiA==", + "dependencies": { + "hookable": "^5.5.3", + "zhead": "^2.2.4" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/shared": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.11.14.tgz", + "integrity": "sha512-41Qt4PJKYVrEGOTXgBJLRYrEu3S7n5stoB4TFC6312CIBVedXqg7voHQurn32LVDjpfJftjLa2ggCjpqdqoRDw==", + "dependencies": { + "@unhead/schema": "1.11.14" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, + "node_modules/@unhead/vue": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.11.14.tgz", + "integrity": "sha512-6nfi7FsZ936gscmj+1nUB1pybiFMFbnuEFo7B/OY2klpLWsYDUOVvpsJhbu7C3u7wkTlJXglmAk6jdd8I7WgZA==", + "dependencies": { + "@unhead/schema": "1.11.14", + "@unhead/shared": "1.11.14", + "defu": "^6.1.4", + "hookable": "^5.5.3", + "unhead": "1.11.14" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + }, + "peerDependencies": { + "vue": ">=2.7 || >=3" + } + }, "node_modules/@vitejs/plugin-vue": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", @@ -960,6 +1014,11 @@ "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", "dev": true }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -1077,6 +1136,11 @@ "he": "bin/he" } }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==" + }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -1387,6 +1451,20 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, + "node_modules/unhead": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/unhead/-/unhead-1.11.14.tgz", + "integrity": "sha512-XmXW0aZyX9kGk9ejCKCSvv/J4T3Rt4hoAe2EofM+nhG+zwZ7AArUMK/0F/fj6FTkfgY0u0/JryE00qUDULgygA==", + "dependencies": { + "@unhead/dom": "1.11.14", + "@unhead/schema": "1.11.14", + "@unhead/shared": "1.11.14", + "hookable": "^5.5.3" + }, + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } + }, "node_modules/vite": { "version": "5.4.7", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", @@ -1546,6 +1624,14 @@ "engines": { "node": ">= 8" } + }, + "node_modules/zhead": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz", + "integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==", + "funding": { + "url": "https://github.com/sponsors/harlan-zw" + } } }, "dependencies": { @@ -1881,6 +1967,44 @@ "undici-types": "~6.19.2" } }, + "@unhead/dom": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/dom/-/dom-1.11.14.tgz", + "integrity": "sha512-FaHCWo9JR4h7PCpSRaXuMC6ifXOuBzlI0PD1MmUcxND2ayDl1d6DauIbN8TUf9TDRxNkrK1Ehb0OCXjC1ZJtrg==", + "requires": { + "@unhead/schema": "1.11.14", + "@unhead/shared": "1.11.14" + } + }, + "@unhead/schema": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/schema/-/schema-1.11.14.tgz", + "integrity": "sha512-V9W9u5tF1/+TiLqxu+Qvh1ShoMDkPEwHoEo4DKdDG6ko7YlbzFfDxV6el9JwCren45U/4Vy/4Xi7j8OH02wsiA==", + "requires": { + "hookable": "^5.5.3", + "zhead": "^2.2.4" + } + }, + "@unhead/shared": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/shared/-/shared-1.11.14.tgz", + "integrity": "sha512-41Qt4PJKYVrEGOTXgBJLRYrEu3S7n5stoB4TFC6312CIBVedXqg7voHQurn32LVDjpfJftjLa2ggCjpqdqoRDw==", + "requires": { + "@unhead/schema": "1.11.14" + } + }, + "@unhead/vue": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/@unhead/vue/-/vue-1.11.14.tgz", + "integrity": "sha512-6nfi7FsZ936gscmj+1nUB1pybiFMFbnuEFo7B/OY2klpLWsYDUOVvpsJhbu7C3u7wkTlJXglmAk6jdd8I7WgZA==", + "requires": { + "@unhead/schema": "1.11.14", + "@unhead/shared": "1.11.14", + "defu": "^6.1.4", + "hookable": "^5.5.3", + "unhead": "1.11.14" + } + }, "@vitejs/plugin-vue": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.1.4.tgz", @@ -2125,6 +2249,11 @@ "integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==", "dev": true }, + "defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==" + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -2199,6 +2328,11 @@ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, + "hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==" + }, "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", @@ -2403,6 +2537,17 @@ "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true }, + "unhead": { + "version": "1.11.14", + "resolved": "https://registry.npmjs.org/unhead/-/unhead-1.11.14.tgz", + "integrity": "sha512-XmXW0aZyX9kGk9ejCKCSvv/J4T3Rt4hoAe2EofM+nhG+zwZ7AArUMK/0F/fj6FTkfgY0u0/JryE00qUDULgygA==", + "requires": { + "@unhead/dom": "1.11.14", + "@unhead/schema": "1.11.14", + "@unhead/shared": "1.11.14", + "hookable": "^5.5.3" + } + }, "vite": { "version": "5.4.7", "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.7.tgz", @@ -2466,6 +2611,11 @@ "requires": { "isexe": "^2.0.0" } + }, + "zhead": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/zhead/-/zhead-2.2.4.tgz", + "integrity": "sha512-8F0OI5dpWIA5IGG5NHUg9staDwz/ZPxZtvGVf01j7vHqSyZ0raHY+78atOVxRqb73AotX22uV1pXt3gYSstGag==" } } } diff --git a/webapp/package.json b/webapp/package.json index c48f62f..70c1fb7 100644 --- a/webapp/package.json +++ b/webapp/package.json @@ -11,6 +11,7 @@ "type-check": "vue-tsc --build --force" }, "dependencies": { + "@unhead/vue": "^1.11.14", "axios": "^1.7.7", "countup.js": "^2.8.0", "vue": "^3.4.29", diff --git a/webapp/public/chicago-pd.jpg b/webapp/public/chicago-pd.jpg new file mode 100644 index 0000000..69de0de Binary files /dev/null and b/webapp/public/chicago-pd.jpg differ diff --git a/webapp/src/App.vue b/webapp/src/App.vue index 1b1a4e8..581de5c 100644 --- a/webapp/src/App.vue +++ b/webapp/src/App.vue @@ -15,6 +15,7 @@ const items = [ { title: 'Home', icon: 'mdi-home', to: '/' }, { title: 'Map', icon: 'mdi-map', to: '/map' }, { title: 'What is an ALPR?', icon: 'mdi-cctv', to: '/what-is-an-alpr' }, + { title: 'Dangers of ALPRs', icon: 'mdi-shield-alert', to: '/dangers' }, { title: 'Report an ALPR', icon: 'mdi-map-marker-plus', to: '/report' }, { title: 'Known Operators', icon: 'mdi-police-badge', to: '/operators' }, // { title: 'About', icon: 'mdi-information', to: '/about' }, diff --git a/webapp/src/assets/main.css b/webapp/src/assets/main.css index 1f425f4..1ccee5e 100644 --- a/webapp/src/assets/main.css +++ b/webapp/src/assets/main.css @@ -21,3 +21,12 @@ a:hover { .leaflet-bar a { color: var(--df-text-color) !important; } + +p { + font-family: "PT Serif", serif; + /* font-size: 1.1em; */ +} + +.serif { + font-family: "PT Serif", serif; +} diff --git a/webapp/src/components/Dangers.vue b/webapp/src/components/Dangers.vue new file mode 100644 index 0000000..afa6a3c --- /dev/null +++ b/webapp/src/components/Dangers.vue @@ -0,0 +1,178 @@ + + + + + diff --git a/webapp/src/components/QuotedSource.vue b/webapp/src/components/QuotedSource.vue new file mode 100644 index 0000000..d907553 --- /dev/null +++ b/webapp/src/components/QuotedSource.vue @@ -0,0 +1,29 @@ + + + + + diff --git a/webapp/src/main.ts b/webapp/src/main.ts index 76aa551..bc024da 100644 --- a/webapp/src/main.ts +++ b/webapp/src/main.ts @@ -3,6 +3,7 @@ import './assets/main.css' import { createApp } from 'vue' import App from './App.vue' import router from './router' +import { createHead } from '@unhead/vue' import 'vuetify/styles' import { createVuetify } from 'vuetify' @@ -19,7 +20,7 @@ const vuetify = createVuetify({ }) const app = createApp(App) - +app.use(createHead()) app.use(router) app.use(vuetify) diff --git a/webapp/src/router/index.ts b/webapp/src/router/index.ts index 7631ccf..7c835f2 100644 --- a/webapp/src/router/index.ts +++ b/webapp/src/router/index.ts @@ -1,6 +1,7 @@ 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({ history: createWebHistory(import.meta.env.BASE_URL), @@ -17,12 +18,18 @@ const router = createRouter({ { path: '/', name: 'home', - component: Landing + component: Landing, + meta: { + title: 'Find Nearby ALPRs | DeFlock' + } }, { path: '/map', name: 'map', - component: Map + component: Map, + meta: { + title: 'ALPR Map | DeFlock' + } }, { path: '/about', @@ -30,58 +37,102 @@ const router = createRouter({ // route level code-splitting // this generates a separate chunk (About.[hash].js) for this route // which is lazy-loaded when the route is visited. - component: () => import('../views/AboutView.vue') + component: () => import('../views/AboutView.vue'), + meta: { + title: 'About | DeFlock' + } }, { path: '/what-is-an-alpr', name: 'what-is-an-alpr', - component: () => import('../views/WhatIsAnALPRView.vue') + component: () => import('../views/WhatIsAnALPRView.vue'), + meta: { + title: 'What is an ALPR | DeFlock' + } }, { path: '/report', name: 'report', - component: () => import('../views/ReportView.vue') + component: () => import('../views/ReportView.vue'), + meta: { + title: 'Report an ALPR | DeFlock' + } }, { path: '/operators', name: 'operators', - component: () => import('../views/OperatorsView.vue') + component: () => import('../views/OperatorsView.vue'), + meta: { + title: 'Operators | DeFlock' + } }, { path: '/contact', name: 'contact', - component: () => import('../views/ContactView.vue') + component: () => import('../views/ContactView.vue'), + meta: { + title: 'Contact | DeFlock' + } }, { path: '/roadmap', name: 'roadmap', - component: () => import('../views/RoadmapView.vue') + component: () => import('../views/RoadmapView.vue'), + meta: { + title: 'Roadmap | DeFlock' + } }, { path: '/legal', name: 'legal', - component: () => import('../views/LegalView.vue') + component: () => import('../views/LegalView.vue'), + meta: { + title: 'Legal | DeFlock' + } }, { path: '/qr', name: 'qr-landing', - component: () => import('../views/QRLandingView.vue') + component: () => import('../views/QRLandingView.vue'), + meta: { + title: 'You Found an ALPR | DeFlock' + } }, { path: '/donate', name: 'donate', - component: () => import('../views/Donate.vue') + component: () => import('../views/Donate.vue'), + meta: { + title: 'Donate | DeFlock' + } + }, + { + path: '/dangers', + name: 'dangers', + component: () => import('../views/Dangers.vue'), + meta: { + title: 'ALPR Dangers | DeFlock' + } }, { path: '/:pathMatch(.*)*', name: 'not-found', - component: () => import('../views/404.vue') + component: () => import('../views/404.vue'), + meta: { + title: 'Not Found | DeFlock' + } } ] }) // backward compatibility with old url scheme router.beforeEach((to, from, next) => { + if (to.meta.title) { + useHead({ + title: to.meta.title + }) + } + if (to.path === '/' && to.hash) { next({ path: '/map', hash: to.hash }) } else { diff --git a/webapp/src/views/Dangers.vue b/webapp/src/views/Dangers.vue new file mode 100644 index 0000000..774e34b --- /dev/null +++ b/webapp/src/views/Dangers.vue @@ -0,0 +1,64 @@ + + + + + diff --git a/webapp/src/views/Landing.vue b/webapp/src/views/Landing.vue index ca004fe..1a80b80 100644 --- a/webapp/src/views/Landing.vue +++ b/webapp/src/views/Landing.vue @@ -5,7 +5,7 @@

You're Being Tracked by ALPRs!

-

+

Automated License Plate Readers (ALPRs) are monitoring your every move. Learn more about how they work and how you can protect your privacy.

@@ -16,9 +16,14 @@ - - - + + +

The Dangers of ALPRs

+

+ ALPRs are a threat to your privacy and civil liberties. They can be used to track your movements, profile you, and even stalk you. Learn more about the dangers of ALPRs and how you can protect yourself. +

+ + @@ -52,8 +57,13 @@ - -
+
+ + + See All Dangers + mdi-shield-alert + +
@@ -63,14 +73,6 @@ mdi-map
- - - - - Maps © OpenStreetMap contributors. - - - diff --git a/webapp/src/views/OperatorsView.vue b/webapp/src/views/OperatorsView.vue index 4f4cc63..a75a770 100644 --- a/webapp/src/views/OperatorsView.vue +++ b/webapp/src/views/OperatorsView.vue @@ -1,5 +1,5 @@ diff --git a/webapp/src/views/ReportView.vue b/webapp/src/views/ReportView.vue index 0eb28a1..c2d6737 100644 --- a/webapp/src/views/ReportView.vue +++ b/webapp/src/views/ReportView.vue @@ -1,5 +1,5 @@