Skip to content
Merged
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
3 changes: 3 additions & 0 deletions app_vue/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@ bin/vueLocalDeploy.sh
### Vue3 Leaflet - Map Library
- this library allows us to generate a map and place relevant markers

### Google Maps Routes API
- this is used to calculate the optimal order of bins to visit
- note that if it returns empty object {} it is likely that your request is passing incorrect lat/long or location data

## Folder structure

Expand Down
1 change: 1 addition & 0 deletions app_vue/src/assets/images/feather-disc.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions app_vue/src/assets/images/feather-map-pin.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 0 additions & 3 deletions app_vue/src/assets/images/generic-material.svg

This file was deleted.

Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions app_vue/src/assets/stylesheets/_functions.scss
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,19 @@
color: #C92828;
}

.color-warning-bg {
background-color: #FFF4E5;
}

// text
.font-body {
@include fontBody;
}

.font-body-small {
@include fontBodySmall;
}

// misc
.cursor-pointer {
cursor: pointer;
Expand Down
78 changes: 62 additions & 16 deletions app_vue/src/components/sensorMap.vue
Original file line number Diff line number Diff line change
@@ -1,35 +1,68 @@
<script setup>
import { reactive, ref, onMounted, watch } from 'vue'
import { reactive, onMounted, watch, onBeforeMount, onDeactivated } from 'vue'
import SensorMapMarker from '@/components/sensorMapMarker.vue';
import 'leaflet/dist/leaflet.css'
import { LMap, LTileLayer, LMarker, LControlZoom, LPolyline } from '@vue-leaflet/vue-leaflet'
import { LMap, LTileLayer, LMarker, LControlZoom, LPolyline, LIcon } from '@vue-leaflet/vue-leaflet'
import { useDevice, DEVICE_SIZE } from '@/utils/screenSizeHelper';
import { getLatLng } from '@/utils/getLatLngFromAddressHelper';
import { useSensorStore } from '@/stores/sensors_store';
import { useRouteStore } from '@/stores/route_store';
import { storeToRefs } from 'pinia';

const center = ref([43.7, -79.42]); // TODO: update to possibly be user's current location
const zoom = ref(10);
// stores
const sensorStore = useSensorStore();
const { sensors } = storeToRefs(sensorStore);
const routeStore = useRouteStore();
const {
getSelectedRouteLatLong,
getIsRouteOptimized } = storeToRefs(routeStore);

const state = reactive({
location: 'bottomright',
device: useDevice()
device: useDevice(),
isRouteOptimized: false,
polyLineLatLngs: [],
startPointLatLng: [],
endPointLatLng: [],
zoom: 10,
center: [43.7, -79.42]
});
const polyLineLatLngs = ref([]);

const routeStore = useRouteStore();
const { getSensorRouteLatLong } = storeToRefs(routeStore);
const startImgUrl = 'src/assets/images/feather-disc.svg';
const endImgUrl = 'src/assets/images/feather-map-pin.svg';

watch(getSensorRouteLatLong, () => {
polyLineLatLngs.value = routeStore.getSensorRouteLatLong;
}, { deep: true })
onBeforeMount(async () => {
// processing start/end/center lat lng points
state.startPointLatLng = await getLatLng(routeStore.getStartPointAddress);
state.endPointLatLng = await getLatLng(routeStore.getEndPointAddress);
state.center = state.startPointLatLng;

routeStore.setHasMappedStartEnd(true);
})
Comment on lines +34 to +41

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

gets start and end point lat lng and sets the center of the map to be the start point


onMounted(() => {
positionZoom();
window.addEventListener("resize", positionZoom);
});

onDeactivated(() => {
routeStore.setHasMappedStartEnd(false);
})

watch(getSelectedRouteLatLong, () => {
state.polyLineLatLngs = routeStore.getSelectedRouteLatLong;

// additional lines for start and end points
if (state.startPointLatLng.length && state.endPointLatLng.length) {
state.polyLineLatLngs.unshift(state.startPointLatLng); // append as first element
state.polyLineLatLngs.push(state.endPointLatLng); // append as last element
}
}, { deep: true })
Comment on lines +52 to +60

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here we are drawing the additional map polylines for the start and end points


watch(getIsRouteOptimized, () => {
state.isRouteOptimized = routeStore.getIsRouteOptimized;
})

function positionZoom() {
state.device = useDevice();
if (state.device.size === DEVICE_SIZE.s || state.device.size === DEVICE_SIZE.xs) {
Expand All @@ -42,17 +75,30 @@

<template>
<div v-if="sensors" class="sensor-map-container">
<l-map ref="map" v-model:zoom="zoom" :use-global-leaflet="false" :center="center" :options="{zoomControl: false}">
<l-map ref="map" v-model:zoom="state.zoom" :use-global-leaflet="false" :center="state.center" :options="{zoomControl: false}">
<l-control-zoom :position="state.location"/>
<!-- alternative maps (for aesthetic): -->
<!-- favourite: https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png -->
<!-- another one: https://tiles.stadiamaps.com/tiles/osm_bright/{z}/{x}/{y}{r}.png -->
<!-- alternative maps URLS (for aesthetic): -->
<!-- https://tiles.stadiamaps.com/tiles/alidade_smooth/{z}/{x}/{y}{r}.png -->
<!-- https://tiles.stadiamaps.com/tiles/osm_bright/{z}/{x}/{y}{r}.png -->
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
layer-type="base"
name="OpenStreetMap"
></l-tile-layer>
<l-polyline :lat-lngs="polyLineLatLngs"></l-polyline>
<l-polyline v-if="state.isRouteOptimized" :lat-lngs="state.polyLineLatLngs"></l-polyline>

<!-- starting point marker -->
<l-marker v-if="state.startPointLatLng.length"
:lat-lng="state.startPointLatLng">
<l-icon class="color-green" :icon-size="[25, 25]" :icon-anchor="[15, 14]" :icon-url="startImgUrl" />
</l-marker>

<!-- ending point marker -->
<l-marker v-if="state.endPointLatLng.length"
:lat-lng="state.endPointLatLng">
<l-icon :icon-size="[25, 25]" :icon-anchor="[12, 14]" :icon-url="endImgUrl" />
</l-marker>

Comment on lines +90 to +101

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

places start and end point map markers


<l-marker
v-for="sensor in sensors"
Expand Down
25 changes: 14 additions & 11 deletions app_vue/src/components/sensorMapMarker.vue
Original file line number Diff line number Diff line change
Expand Up @@ -15,32 +15,35 @@
// set html element variables
const fillPercent = ref(Math.round(props.sensor.fill_level || 0));
const { iconUrl, linearProgressColor } = getIconAndProgressColor(props.sensor);

const isAlreadyInRoute = ref(false);
const isRouteCreated = ref(false);

// route store
const routeStore = useRouteStore();
const isAlreadyInRoute = ref(false);
const { getSensorRouteList } = storeToRefs(routeStore);
const { getSelectedRouteList, getIsRouteOptimized } = storeToRefs(routeStore);

// watch for changes in stored sensor route array (ie. when a sensor gets added or removed)
watch(getSensorRouteList, () => {
if (routeStore.getSensorRouteList.length > 0) {
isAlreadyInRoute.value = !!routeStore.getSensorRouteList.find(bin => bin.id === props.sensor.id);
} else {
isAlreadyInRoute.value = false
}
watch(getSelectedRouteList, () => {
isAlreadyInRoute.value = routeStore.isAlreadyInRoute(props.sensor);
}, { deep: true })

watch(getIsRouteOptimized, () => {
isRouteCreated.value = routeStore.getIsRouteOptimized;
}, { deep: true })

function addBinToRoute(sensor) {
// only add to route if not already added
if (isAlreadyInRoute.value === false) {
routeStore.addSensorToRoute(sensor);
routeStore.googOptimizeRoute();
}
}

function removeBinFromRoute(sensor) {
// only add to route if not already added
// only remove from route if already added
if (isAlreadyInRoute.value === true) {
routeStore.removeSensorFromRoute(sensor);
routeStore.googOptimizeRoute();
}
}

Expand Down Expand Up @@ -72,7 +75,7 @@
<span class="bin-details__tag-list-text">Tags:</span>
<span class="bin-details__tag">{{ props.sensor.asset_tag }}</span>
</div>
<div class="bin-details__cta-routes">
<div class="bin-details__cta-routes" v-if="isRouteCreated">
<v-btn variant="flat"
class="mt-2 mb-2"
color="#191A1C"
Expand Down
Loading