diff --git a/README.md b/README.md index 16962c6..dcd69b0 100644 --- a/README.md +++ b/README.md @@ -14,24 +14,24 @@ I created this project after noticing the mass deployment of ALPRs in cities, to Uses OpenStreetMap data to populate a map with crowdsourced locations of ALPRs, along with their type and direction they face. ### Report ALPRs -Provides OSM tags for easy reporting of ALPRs based on brand on OSM's editing site. Evemtually, this will be a native feature of the site. +Provides OSM tags for easy reporting of ALPRs based on brand on OSM's editing site. Eventually, this will be a native feature of the site. ### Learn About ALPRs See photos of common ALPRs and learn about their capabilities. ## Tech Stack -_Likely to change soon._ - ### Backend * Scala * PekkoHTTP * Nginx ### Cloud -* AWS Lambda (for [clustering](serverless/alpr_clusters) and [counts](serverless/alpr_counts)) +* AWS Lambda (for [region segmenting](serverless/alpr_clusters) and [counts](serverless/alpr_counts)) * AWS S3 * AWS ECR +* Cloudflare as DNS + Proxy +* Directus CDN ### Frontend * Vue3 @@ -39,9 +39,8 @@ _Likely to change soon._ * Vue Leaflet (mapping library) ### Services -* OpenStreetMap - Overpass API +* OpenStreetMap - Overpass API, Basic Map Tiles * Nominatim - Geocoding -* Stadia Maps - Map Tiles ## Usage @@ -60,6 +59,10 @@ _Likely to change soon._ 1. `cd shotgun` 2. `sbt run` +### Building for Production + +See [Dockerfile](./Dockerfile). + ## Contributing We welcome contributions from anyone. Here's how you can help: diff --git a/webapp/public/donate.webp b/webapp/public/donate.webp new file mode 100644 index 0000000..7644f2b Binary files /dev/null and b/webapp/public/donate.webp differ diff --git a/webapp/public/torches.webp b/webapp/public/torches.webp deleted file mode 100644 index 6bc78db..0000000 Binary files a/webapp/public/torches.webp and /dev/null differ diff --git a/webapp/src/assets/main.css b/webapp/src/assets/main.css index 7d65277..3491c0a 100644 --- a/webapp/src/assets/main.css +++ b/webapp/src/assets/main.css @@ -1,44 +1,169 @@ +/* Modern CSS Custom Properties */ +:root { + --df-background-color: white; + --df-blue: rgb(18, 151, 195); + + /* Modern Typography Scale */ + --font-size-base: 1rem; + --font-size-lg: 1.125rem; + --font-size-xl: 1.25rem; + --font-size-2xl: 1.5rem; + + /* Responsive font sizes */ + --font-size-body: clamp(1rem, 2.5vw, 1.125rem); + --line-height-base: 1.6; + --line-height-relaxed: 1.75; + + /* Spacing scale */ + --space-xs: 0.5rem; + --space-sm: 0.75rem; + --space-md: 1rem; + --space-lg: 1.5rem; + --space-xl: 2rem; + --space-2xl: 3rem; +} + +/* Improved base typography */ +html { + font-size: 16px; /* Base font size for rem calculations */ +} + +body { + font-size: var(--font-size-body); + line-height: var(--line-height-relaxed); + font-feature-settings: "kern" 1, "liga" 1; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + margin: 0; + padding: 0; +} + +/* Modern link styles */ a { - font-weight: bold; + font-weight: 600; color: var(--df-blue); text-decoration: none; + transition: color 0.2s ease-in-out; +} + +a:hover { + color: color-mix(in srgb, var(--df-blue) 80%, black); } /* underline only simple elements */ a:not([class]):hover { text-decoration: underline; -} - -:root { - --df-background-color: white; - --df-text-color: #ccc; - --df-blue: rgb(18, 151, 195); + text-decoration-thickness: 2px; + text-underline-offset: 2px; } .leaflet-popup-content-wrapper, .leaflet-popup-tip, .leaflet-bar a { background: var(--df-background-color) !important; } -.leaflet-bar a { - color: var(--df-text-color) !important; -} - .marker-cluster span { /* changing to dark mode should not affect the map yet */ color: #000000 !important; } -p { - font-family: "PT Serif", serif; - /* font-size: 1.1em; */ +/* Content elements use serif for better readability */ +p, li, blockquote, .content { + font-family: "PT Serif", Georgia, "Times New Roman", serif; } +/* Modern paragraph styling */ +p { + font-size: var(--font-size-body); + line-height: var(--line-height-relaxed); + margin: var(--space-md) 0; +} + +/* Responsive headings */ +h1, h2, h3, h4, h5, h6 { + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; + font-weight: 700; + line-height: 1.2; + margin-top: var(--space-xl); + margin-bottom: var(--space-md); +} + +/* Reduce heading top margins in Vuetify components */ +.v-card h1, .v-card h2, .v-card h3, .v-card h4, .v-card h5, .v-card h6, .v-card p, +.v-dialog h1, .v-dialog h2, .v-dialog h3, .v-dialog h4, .v-dialog h5, .v-dialog h6, .v-dialog p, +.v-sheet h1, .v-sheet h2, .v-sheet h3, .v-sheet h4, .v-sheet h5, .v-sheet h6, .v-sheet p, +.v-toolbar h1, .v-toolbar h2, .v-toolbar h3, .v-toolbar h4, .v-toolbar h5, .v-toolbar h6, .v-toolbar p, +.v-expansion-panel h1, .v-expansion-panel h2, .v-expansion-panel h3, .v-expansion-panel h4, .v-expansion-panel h5, .v-expansion-panel h6, .v-expansion-panel p { + margin-top: 0; + margin-bottom: 0; +} + +h1 { + font-size: clamp(1.75rem, 5vw, 3rem); +} + +h2 { + font-size: clamp(1.5rem, 4vw, 2.25rem); +} + +h3 { + font-size: clamp(1.25rem, 3vw, 1.875rem); +} + +/* Utility classes */ .serif { - font-family: "PT Serif", serif; + font-family: "PT Serif", Georgia, "Times New Roman", serif; } .sans-serif { - font-family: unset !important; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important; +} + +/* Improved list styling */ +ul, ol { + margin: var(--space-md) 0; + padding-left: var(--space-lg); + line-height: var(--line-height-relaxed); +} + +ul li, ol li { + margin: var(--space-sm) 0; +} + +/* Better text spacing for improved readability */ +blockquote { + margin: var(--space-xl) 0; + padding: var(--space-md) var(--space-lg); + border-left: 4px solid var(--df-blue); + font-style: italic; + background-color: #f8f9fa; +} + +/* Code styling */ +code, pre { + font-family: "SF Mono", Monaco, "Cascadia Code", "Roboto Mono", Consolas, "Courier New", monospace; + font-size: 0.875em; + background-color: rgb(33,33,33); + color: white; + padding: 0.125em 0.25em; + border-radius: 3px; +} + +pre { + padding: var(--space-md); + overflow-x: auto; + border-radius: 6px; +} + +pre code { + background: none; + padding: 0; +} + +.narrow-text { + max-width: 85ch !important; + margin-left: auto; + margin-right: auto; } /* Prevent Scrolling Horizontally */ diff --git a/webapp/src/assets/typography.css b/webapp/src/assets/typography.css deleted file mode 100644 index 146f5e3..0000000 --- a/webapp/src/assets/typography.css +++ /dev/null @@ -1,26 +0,0 @@ -/* Typography rules */ - -body { - line-height: 1.6; - margin: 0; - padding: 0; -} - -h1, h2, h3, h4, h5, h6 { - margin-top: 1.5em; - margin-bottom: 0.5em; - font-weight: bold; -} - -p { - margin: 0.8em 0; -} - -ul, ol { - margin: 1em 0; - padding-left: 1.5em; -} - -ul li, ol li { - margin: 0.5em 0; -} diff --git a/webapp/src/components/DiscordWarningDialog.vue b/webapp/src/components/DiscordWarningDialog.vue index 4a3ad7c..2a834e3 100644 --- a/webapp/src/components/DiscordWarningDialog.vue +++ b/webapp/src/components/DiscordWarningDialog.vue @@ -29,8 +29,6 @@ diff --git a/webapp/src/router/index.ts b/webapp/src/router/index.ts index d8b42c7..3d8506a 100644 --- a/webapp/src/router/index.ts +++ b/webapp/src/router/index.ts @@ -49,26 +49,19 @@ const router = createRouter({ }, { path: '/report', - name: 'reportChoose', - component: () => import('../views/ReportBase.vue'), - children: [ - { - path: '', - name: 'report', - component: () => import('../views/ReportChoose.vue'), - meta: { - title: 'Submit Cameras | DeFlock' - }, - }, - { - path: '/report/id', - name: 'reportID', - component: () => import('../views/ReportID.vue'), - meta: { - title: 'Submit Cameras | DeFlock' - } - }, - ] + name: 'report', + component: () => import('../views/ReportChoose.vue'), + meta: { + title: 'Submit Cameras | DeFlock' + } + }, + { + path: '/report/id', + name: 'reportID', + component: () => import('../views/ReportID.vue'), + meta: { + title: 'Submit Cameras | DeFlock' + } }, { path: '/council', @@ -138,6 +131,9 @@ const router = createRouter({ path: '/foia', name: 'foia', component: () => import('../views/FOIA.vue'), + meta: { + title: 'How to Request Public Records | DeFlock' + } }, { path: '/identify', diff --git a/webapp/src/views/404.vue b/webapp/src/views/404.vue index 238adc2..4825d9a 100644 --- a/webapp/src/views/404.vue +++ b/webapp/src/views/404.vue @@ -1,21 +1,25 @@ + + diff --git a/webapp/src/views/AboutView.vue b/webapp/src/views/AboutView.vue index b4dfa10..888eca8 100644 --- a/webapp/src/views/AboutView.vue +++ b/webapp/src/views/AboutView.vue @@ -1,86 +1,59 @@ - diff --git a/webapp/src/views/ContactView.vue b/webapp/src/views/ContactView.vue index ca10bed..8ea96a5 100644 --- a/webapp/src/views/ContactView.vue +++ b/webapp/src/views/ContactView.vue @@ -1,5 +1,6 @@ diff --git a/webapp/src/views/FOIA.vue b/webapp/src/views/FOIA.vue index 361c9c4..08dd1cd 100644 --- a/webapp/src/views/FOIA.vue +++ b/webapp/src/views/FOIA.vue @@ -1,112 +1,90 @@ - - diff --git a/webapp/src/views/Identification.vue b/webapp/src/views/Identification.vue index 54f2a7e..f834f6b 100644 --- a/webapp/src/views/Identification.vue +++ b/webapp/src/views/Identification.vue @@ -1,10 +1,12 @@ diff --git a/webapp/src/views/PrivacyPolicy.vue b/webapp/src/views/PrivacyPolicy.vue index dcffb1b..9ad25dc 100644 --- a/webapp/src/views/PrivacyPolicy.vue +++ b/webapp/src/views/PrivacyPolicy.vue @@ -1,5 +1,6 @@ - - diff --git a/webapp/src/views/ReportBase.vue b/webapp/src/views/ReportBase.vue deleted file mode 100644 index cbc43e6..0000000 --- a/webapp/src/views/ReportBase.vue +++ /dev/null @@ -1,10 +0,0 @@ - - - - diff --git a/webapp/src/views/ReportChoose.vue b/webapp/src/views/ReportChoose.vue index 6a7a061..731ac9a 100644 --- a/webapp/src/views/ReportChoose.vue +++ b/webapp/src/views/ReportChoose.vue @@ -1,5 +1,6 @@ diff --git a/webapp/src/views/ReportID.vue b/webapp/src/views/ReportID.vue index 2e9fbbd..2947c38 100644 --- a/webapp/src/views/ReportID.vue +++ b/webapp/src/views/ReportID.vue @@ -1,11 +1,14 @@ + - - diff --git a/webapp/src/views/WhatIsAnALPRView.vue b/webapp/src/views/WhatIsAnALPRView.vue index 4020bbb..ba06a8a 100644 --- a/webapp/src/views/WhatIsAnALPRView.vue +++ b/webapp/src/views/WhatIsAnALPRView.vue @@ -1,8 +1,11 @@