Changes: - Move v-model directives before other attributes - Move v-bind directives before event handlers - Reorder attributes for better readability - Fix template attribute ordering across components - Improve eslint rules - add default vite config for testing (handles nostr error too) This follows Vue.js style guide recommendations for attribute ordering and improves template consistency.
290 lines
8.3 KiB
Vue
290 lines
8.3 KiB
Vue
<template>
|
|
<QuickNav />
|
|
|
|
<!-- CONTENT -->
|
|
<section id="Content" class="p-6 pb-24 max-w-3xl mx-auto">
|
|
<!-- Breadcrumb -->
|
|
<div class="mb-8">
|
|
<!-- Back -->
|
|
<div class="text-lg text-center font-light relative px-7">
|
|
<h1
|
|
class="text-lg text-center px-2 py-1 absolute -left-2 -top-1"
|
|
@click="$router.back()"
|
|
>
|
|
<font-awesome icon="chevron-left" class="fa-fw"></font-awesome>
|
|
</h1>
|
|
</div>
|
|
|
|
<!-- Heading -->
|
|
<h1 id="ViewHeading" class="text-4xl text-center font-light pt-4 mb-8">
|
|
Area for Nearby Search
|
|
</h1>
|
|
</div>
|
|
|
|
<div class="px-2 py-4">
|
|
This location is only stored on your device. It is sometimes sent from
|
|
your device to run searches but it is not stored on our servers.
|
|
</div>
|
|
|
|
<div class="text-center">
|
|
<button v-if="!searchBox && !isNewMarkerSet" class="m-4 px-4 py-2">
|
|
Click to Choose a Location for Nearby Search
|
|
</button>
|
|
<button
|
|
v-if="isNewMarkerSet"
|
|
class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
|
|
@click="storeSearchBox"
|
|
>
|
|
<font-awesome icon="save" class="fa-fw" />
|
|
Store This Location for Nearby Search
|
|
</button>
|
|
<button
|
|
v-if="searchBox"
|
|
class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
|
|
@click="forgetSearchBox"
|
|
>
|
|
<font-awesome icon="trash-can" class="fa-fw" />
|
|
Delete Stored Location
|
|
</button>
|
|
<button
|
|
v-if="searchBox"
|
|
class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
|
|
@click="resetLatLong"
|
|
>
|
|
<font-awesome icon="rotate" class="fa-fw" />
|
|
Reset To Original
|
|
</button>
|
|
<button
|
|
v-if="isNewMarkerSet"
|
|
class="m-4 px-4 py-2 rounded-md bg-blue-200 text-blue-500"
|
|
@click="isNewMarkerSet = false"
|
|
>
|
|
<font-awesome icon="eraser" class="fa-fw" />
|
|
Erase Marker
|
|
</button>
|
|
<div v-if="isNewMarkerSet">
|
|
Click on the pin to erase it. Click anywhere else to set a different
|
|
different corner.
|
|
</div>
|
|
</div>
|
|
|
|
<div class="aspect-video">
|
|
<l-map
|
|
ref="map"
|
|
v-model:zoom="localZoom"
|
|
:center="[localCenterLat, localCenterLong]"
|
|
class="!z-40 rounded-md"
|
|
@click="setMapPoint"
|
|
>
|
|
<l-tile-layer
|
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
|
layer-type="base"
|
|
name="OpenStreetMap"
|
|
/>
|
|
<l-marker
|
|
v-if="isNewMarkerSet"
|
|
:lat-lng="[localCenterLat, localCenterLong]"
|
|
@click="isNewMarkerSet = false"
|
|
/>
|
|
<l-rectangle
|
|
v-if="isNewMarkerSet"
|
|
:bounds="[
|
|
[localCenterLat - localLatDiff, localCenterLong - localLongDiff],
|
|
[localCenterLat + localLatDiff, localCenterLong + localLongDiff],
|
|
]"
|
|
:weight="1"
|
|
/>
|
|
</l-map>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script lang="ts">
|
|
import { LeafletMouseEvent } from "leaflet";
|
|
import "leaflet/dist/leaflet.css";
|
|
import { Component, Vue } from "vue-facing-decorator";
|
|
import {
|
|
LMap,
|
|
LMarker,
|
|
LRectangle,
|
|
LTileLayer,
|
|
} from "@vue-leaflet/vue-leaflet";
|
|
import { Router } from "vue-router";
|
|
|
|
import QuickNav from "../components/QuickNav.vue";
|
|
import { NotificationIface } from "../constants/app";
|
|
import { db, retrieveSettingsForActiveAccount } from "../db/index";
|
|
import { BoundingBox, MASTER_SETTINGS_KEY } from "../db/tables/settings";
|
|
|
|
const DEFAULT_LAT_LONG_DIFF = 0.01;
|
|
const WORLD_ZOOM = 2;
|
|
const DEFAULT_ZOOM = 2;
|
|
|
|
@Component({
|
|
components: {
|
|
QuickNav,
|
|
LRectangle,
|
|
LMap,
|
|
LMarker,
|
|
LTileLayer,
|
|
},
|
|
})
|
|
export default class SearchAreaView extends Vue {
|
|
$notify!: (notification: NotificationIface, timeout?: number) => void;
|
|
$router!: Router;
|
|
|
|
isChoosingSearchBox = false;
|
|
isNewMarkerSet = false;
|
|
|
|
// "local" vars are for the currently selected map box
|
|
localCenterLat = 0;
|
|
localCenterLong = 0;
|
|
localLatDiff = DEFAULT_LAT_LONG_DIFF;
|
|
localLongDiff = DEFAULT_LAT_LONG_DIFF;
|
|
localZoom = DEFAULT_ZOOM;
|
|
|
|
// searchBox reflects what is stored in the database
|
|
searchBox: { name: string; bbox: BoundingBox } | null = null;
|
|
|
|
async mounted() {
|
|
const settings = await retrieveSettingsForActiveAccount();
|
|
this.searchBox = settings.searchBoxes?.[0] || null;
|
|
this.resetLatLong();
|
|
}
|
|
|
|
setMapPoint(event: LeafletMouseEvent) {
|
|
if (this.isNewMarkerSet) {
|
|
this.localLatDiff = Math.abs(event.latlng.lat - this.localCenterLat);
|
|
this.localLongDiff = Math.abs(event.latlng.lng - this.localCenterLong);
|
|
} else {
|
|
// marker is not set
|
|
this.localCenterLat = event.latlng.lat;
|
|
this.localCenterLong = event.latlng.lng;
|
|
|
|
let latDiff = DEFAULT_LAT_LONG_DIFF;
|
|
let longDiff = DEFAULT_LAT_LONG_DIFF;
|
|
// Guess at a size for the bounding box.
|
|
// This doesn't seem like the right approach but it's the only way I can find to get the screen bounds.
|
|
const bounds = event.target.boxZoom?._map?.getBounds();
|
|
if (bounds) {
|
|
latDiff =
|
|
Math.abs(bounds.getNorthEast().lat - bounds.getSouthWest().lat) / 8;
|
|
longDiff =
|
|
Math.abs(bounds.getNorthEast().lng - bounds.getSouthWest().lng) / 8;
|
|
}
|
|
this.localLatDiff = latDiff;
|
|
this.localLongDiff = longDiff;
|
|
this.isNewMarkerSet = true;
|
|
}
|
|
}
|
|
|
|
public resetLatLong() {
|
|
if (this.searchBox?.bbox) {
|
|
const bbox = this.searchBox.bbox;
|
|
this.localCenterLat = (bbox.maxLat + bbox.minLat) / 2;
|
|
this.localCenterLong = (bbox.eastLong + bbox.westLong) / 2;
|
|
this.localLatDiff = (bbox.maxLat - bbox.minLat) / 2;
|
|
this.localLongDiff = (bbox.eastLong - bbox.westLong) / 2;
|
|
this.localZoom = WORLD_ZOOM;
|
|
this.isNewMarkerSet = true;
|
|
} else {
|
|
this.isNewMarkerSet = false;
|
|
}
|
|
}
|
|
|
|
public async storeSearchBox() {
|
|
if (this.localCenterLong || this.localCenterLat) {
|
|
try {
|
|
const newSearchBox = {
|
|
name: "Local",
|
|
bbox: {
|
|
eastLong: this.localCenterLong + this.localLongDiff,
|
|
maxLat: this.localCenterLat + this.localLatDiff,
|
|
minLat: this.localCenterLat - this.localLatDiff,
|
|
westLong: this.localCenterLong - this.localLongDiff,
|
|
},
|
|
};
|
|
await db.open();
|
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
|
searchBoxes: [newSearchBox],
|
|
});
|
|
this.searchBox = newSearchBox;
|
|
this.isChoosingSearchBox = false;
|
|
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "success",
|
|
title: "Saved",
|
|
text: "That has been saved in your preferences. You can now filter by it on your home screen feed.",
|
|
},
|
|
7000,
|
|
);
|
|
this.$router.back();
|
|
} catch (err) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error Updating Search Settings",
|
|
text: "Try going to a different page and then coming back.",
|
|
},
|
|
5000,
|
|
);
|
|
console.error(
|
|
"Telling user to retry the location search setting because:",
|
|
err,
|
|
);
|
|
}
|
|
} else {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "warning",
|
|
title: "No Location Selected",
|
|
text: "Select a location on the map.",
|
|
},
|
|
5000,
|
|
);
|
|
}
|
|
}
|
|
|
|
public async forgetSearchBox() {
|
|
try {
|
|
await db.open();
|
|
await db.settings.update(MASTER_SETTINGS_KEY, {
|
|
searchBoxes: [],
|
|
filterFeedByNearby: false,
|
|
});
|
|
this.searchBox = null;
|
|
this.localCenterLat = 0;
|
|
this.localCenterLong = 0;
|
|
this.localLatDiff = DEFAULT_LAT_LONG_DIFF;
|
|
this.localLongDiff = DEFAULT_LAT_LONG_DIFF;
|
|
this.localZoom = DEFAULT_ZOOM;
|
|
this.isChoosingSearchBox = false;
|
|
this.isNewMarkerSet = false;
|
|
} catch (err) {
|
|
this.$notify(
|
|
{
|
|
group: "alert",
|
|
type: "danger",
|
|
title: "Error Updating Search Settings",
|
|
text: "Try going to a different page and then coming back.",
|
|
},
|
|
5000,
|
|
);
|
|
console.error(
|
|
"Telling user to retry the location search setting because:",
|
|
err,
|
|
);
|
|
}
|
|
}
|
|
|
|
public cancelSearchBoxSelect() {
|
|
this.isChoosingSearchBox = false;
|
|
this.localZoom = WORLD_ZOOM;
|
|
}
|
|
}
|
|
</script>
|