map: refactor
parent
7d90aeacb1
commit
64d4205346
|
@ -379,97 +379,6 @@ class ApiBase extends Controller
|
||||||
return \OCA\Memories\Util::placesGISType() > 0;
|
return \OCA\Memories\Util::placesGISType() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get transformations depending on the request.
|
|
||||||
*
|
|
||||||
* @param bool $aggregateOnly Only apply transformations for aggregation (days call)
|
|
||||||
*/
|
|
||||||
protected function getTransformations(bool $aggregateOnly)
|
|
||||||
{
|
|
||||||
$transforms = [];
|
|
||||||
|
|
||||||
// Add extra information, basename and mimetype
|
|
||||||
if (!$aggregateOnly && ($fields = $this->request->getParam('fields'))) {
|
|
||||||
$fields = explode(',', $fields);
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformExtraFields', $fields];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter for one album
|
|
||||||
if ($this->albumsIsEnabled()) {
|
|
||||||
if ($albumId = $this->request->getParam('album')) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformAlbumFilter', $albumId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other transforms not allowed for public shares
|
|
||||||
if (null === $this->userSession->getUser()) {
|
|
||||||
return $transforms;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter only favorites
|
|
||||||
if ($this->request->getParam('fav')) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformFavoriteFilter'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter only videos
|
|
||||||
if ($this->request->getParam('vid')) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformVideoFilter'];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter only for one face on Recognize
|
|
||||||
if (($recognize = $this->request->getParam('recognize')) && $this->recognizeIsEnabled()) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformPeopleRecognitionFilter', $recognize];
|
|
||||||
|
|
||||||
$faceRect = $this->request->getParam('facerect');
|
|
||||||
if ($faceRect && !$aggregateOnly) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformPeopleRecognizeRect', $recognize];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter only for one face on Face Recognition
|
|
||||||
if (($face = $this->request->getParam('facerecognition')) && $this->facerecognitionIsEnabled()) {
|
|
||||||
$currentModel = (int) $this->config->getAppValue('facerecognition', 'model', -1);
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformPeopleFaceRecognitionFilter', $currentModel, $face];
|
|
||||||
|
|
||||||
$faceRect = $this->request->getParam('facerect');
|
|
||||||
if ($faceRect && !$aggregateOnly) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformPeopleFaceRecognitionRect', $face];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter only for one tag
|
|
||||||
if ($this->tagsIsEnabled()) {
|
|
||||||
if ($tagName = $this->request->getParam('tag')) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformTagFilter', $tagName];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter only for one place
|
|
||||||
if ($this->placesIsEnabled()) {
|
|
||||||
if ($locationId = $this->request->getParam('place')) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformPlaceFilter', (int) $locationId];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Limit number of responses for day query
|
|
||||||
$limit = $this->request->getParam('limit');
|
|
||||||
if ($limit) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformLimitDay', (int) $limit];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Filter geological bounds
|
|
||||||
$bounds = $this->request->getParam('mapbounds');
|
|
||||||
if ($bounds) {
|
|
||||||
$bounds = explode(',', $bounds);
|
|
||||||
$bounds = array_map('floatval', $bounds);
|
|
||||||
if (4 === \count($bounds)) {
|
|
||||||
$transforms[] = [$this->timelineQuery, 'transformBoundFilter', $bounds];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return $transforms;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper to get one file or null from a fiolder.
|
* Helper to get one file or null from a fiolder.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -172,6 +172,93 @@ class DaysController extends ApiBase
|
||||||
return $this->day($id);
|
return $this->day($id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get transformations depending on the request.
|
||||||
|
*
|
||||||
|
* @param bool $aggregateOnly Only apply transformations for aggregation (days call)
|
||||||
|
*/
|
||||||
|
private function getTransformations(bool $aggregateOnly)
|
||||||
|
{
|
||||||
|
$transforms = [];
|
||||||
|
|
||||||
|
// Add extra information, basename and mimetype
|
||||||
|
if (!$aggregateOnly && ($fields = $this->request->getParam('fields'))) {
|
||||||
|
$fields = explode(',', $fields);
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformExtraFields', $fields];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter for one album
|
||||||
|
if ($this->albumsIsEnabled()) {
|
||||||
|
if ($albumId = $this->request->getParam('album')) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformAlbumFilter', $albumId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Other transforms not allowed for public shares
|
||||||
|
if (null === $this->userSession->getUser()) {
|
||||||
|
return $transforms;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only favorites
|
||||||
|
if ($this->request->getParam('fav')) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformFavoriteFilter'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only videos
|
||||||
|
if ($this->request->getParam('vid')) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformVideoFilter'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only for one face on Recognize
|
||||||
|
if (($recognize = $this->request->getParam('recognize')) && $this->recognizeIsEnabled()) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformPeopleRecognitionFilter', $recognize];
|
||||||
|
|
||||||
|
$faceRect = $this->request->getParam('facerect');
|
||||||
|
if ($faceRect && !$aggregateOnly) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformPeopleRecognizeRect', $recognize];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only for one face on Face Recognition
|
||||||
|
if (($face = $this->request->getParam('facerecognition')) && $this->facerecognitionIsEnabled()) {
|
||||||
|
$currentModel = (int) $this->config->getAppValue('facerecognition', 'model', -1);
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformPeopleFaceRecognitionFilter', $currentModel, $face];
|
||||||
|
|
||||||
|
$faceRect = $this->request->getParam('facerect');
|
||||||
|
if ($faceRect && !$aggregateOnly) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformPeopleFaceRecognitionRect', $face];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only for one tag
|
||||||
|
if ($this->tagsIsEnabled()) {
|
||||||
|
if ($tagName = $this->request->getParam('tag')) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformTagFilter', $tagName];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter only for one place
|
||||||
|
if ($this->placesIsEnabled()) {
|
||||||
|
if ($locationId = $this->request->getParam('place')) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformPlaceFilter', (int) $locationId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter geological bounds
|
||||||
|
$bounds = $this->request->getParam('mapbounds');
|
||||||
|
if ($bounds) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformMapBoundsFilter', $bounds];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Limit number of responses for day query
|
||||||
|
$limit = $this->request->getParam('limit');
|
||||||
|
if ($limit) {
|
||||||
|
$transforms[] = [$this->timelineQuery, 'transformLimitDay', (int) $limit];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $transforms;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Preload a few "day" at the start of "days" response.
|
* Preload a few "day" at the start of "days" response.
|
||||||
*
|
*
|
||||||
|
|
|
@ -31,8 +31,6 @@ class LocationController extends ApiBase
|
||||||
/**
|
/**
|
||||||
* @NoAdminRequired
|
* @NoAdminRequired
|
||||||
*
|
*
|
||||||
* @PublicPage
|
|
||||||
*
|
|
||||||
* @NoCSRFRequired
|
* @NoCSRFRequired
|
||||||
*/
|
*/
|
||||||
public function clusters(): JSONResponse
|
public function clusters(): JSONResponse
|
||||||
|
@ -46,47 +44,30 @@ class LocationController extends ApiBase
|
||||||
|
|
||||||
// Get the folder to show
|
// Get the folder to show
|
||||||
$root = null;
|
$root = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$root = $this->getRequestRoot();
|
$root = $this->getRequestRoot();
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
return new JSONResponse(['message' => $e->getMessage()], Http::STATUS_NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make sure we have bounds
|
// Make sure we have bounds and zoom level
|
||||||
// $bounds = $this->request->getParam('bounds');
|
|
||||||
// if (!$bounds) {
|
|
||||||
// return new JSONResponse(['message' => 'Invalid perameters'], Http::STATUS_PRECONDITION_FAILED);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // Make sure we have 4 bounds
|
|
||||||
// $bounds = explode(',', $bounds);
|
|
||||||
// $bounds = array_map('floatval', $bounds);
|
|
||||||
// if (4 !== \count($bounds)) {
|
|
||||||
// return new JSONResponse(['message' => 'Invalid perameters'], Http::STATUS_PRECONDITION_FAILED);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// Zoom level is used to determine the grid length
|
// Zoom level is used to determine the grid length
|
||||||
|
$bounds = $this->request->getParam('bounds');
|
||||||
$zoomLevel = $this->request->getParam('zoom');
|
$zoomLevel = $this->request->getParam('zoom');
|
||||||
if (!$zoomLevel || !is_numeric($zoomLevel)) {
|
if (!$bounds || !$zoomLevel || !is_numeric($zoomLevel)) {
|
||||||
return new JSONResponse(['message' => 'Invalid zoom level'], Http::STATUS_PRECONDITION_FAILED);
|
return new JSONResponse(['message' => 'Invalid parameters'], Http::STATUS_PRECONDITION_FAILED);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A tweakable parameter to determine the number of boxes in the map
|
// A tweakable parameter to determine the number of boxes in the map
|
||||||
$clusterDensity = 2;
|
$clusterDensity = 2;
|
||||||
$gridLength = 180.0 / (2 ** $zoomLevel * $clusterDensity);
|
$gridLen = 180.0 / (2 ** $zoomLevel * $clusterDensity);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$clusters = $this->timelineQuery->getMapClusters(
|
$clusters = $this->timelineQuery->getMapClusters($gridLen, $bounds, $root);
|
||||||
$gridLength,
|
|
||||||
$root,
|
|
||||||
$uid,
|
|
||||||
$this->isRecursive(),
|
|
||||||
$this->isArchive(),
|
|
||||||
$this->getTransformations(true),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Merge clusters that are close together
|
// Merge clusters that are close together
|
||||||
$distanceThreshold = $gridLength / 3;
|
$distanceThreshold = $gridLen / 3;
|
||||||
$clusters = $this->mergeClusters($clusters, $distanceThreshold);
|
$clusters = $this->mergeClusters($clusters, $distanceThreshold);
|
||||||
|
|
||||||
return new JSONResponse($clusters);
|
return new JSONResponse($clusters);
|
||||||
|
@ -125,7 +106,7 @@ class LocationController extends ApiBase
|
||||||
return $updatedClusters;
|
return $updatedClusters;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function isCLose(array $cluster1, array $cluster2, float $threshold): bool
|
private function isClose(array $cluster1, array $cluster2, float $threshold): bool
|
||||||
{
|
{
|
||||||
$deltaX = (float) $cluster1['center'][0] - (float) $cluster2['center'][0];
|
$deltaX = (float) $cluster1['center'][0] - (float) $cluster2['center'][0];
|
||||||
$deltaY = (float) $cluster1['center'][1] - (float) $cluster2['center'][1];
|
$deltaY = (float) $cluster1['center'][1] - (float) $cluster2['center'][1];
|
||||||
|
|
|
@ -14,6 +14,7 @@ class TimelineQuery
|
||||||
use TimelineQueryFilters;
|
use TimelineQueryFilters;
|
||||||
use TimelineQueryFolders;
|
use TimelineQueryFolders;
|
||||||
use TimelineQueryLivePhoto;
|
use TimelineQueryLivePhoto;
|
||||||
|
use TimelineQueryMap;
|
||||||
use TimelineQueryPeopleFaceRecognition;
|
use TimelineQueryPeopleFaceRecognition;
|
||||||
use TimelineQueryPeopleRecognize;
|
use TimelineQueryPeopleRecognize;
|
||||||
use TimelineQueryPlaces;
|
use TimelineQueryPlaces;
|
||||||
|
|
|
@ -195,47 +195,6 @@ trait TimelineQueryDays
|
||||||
return $this->processDay($rows, $uid, $root);
|
return $this->processDay($rows, $uid, $root);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getMapClusters(
|
|
||||||
float $gridLength,
|
|
||||||
TimelineRoot &$root,
|
|
||||||
string $uid,
|
|
||||||
bool $recursive,
|
|
||||||
bool $archive,
|
|
||||||
array $queryTransforms = []
|
|
||||||
): array {
|
|
||||||
$query = $this->connection->getQueryBuilder();
|
|
||||||
|
|
||||||
// Get the average location of each cluster
|
|
||||||
$avgLat = $query->createFunction('AVG(lat) AS avgLat');
|
|
||||||
$avgLng = $query->createFunction('AVG(lon) AS avgLng');
|
|
||||||
$count = $query->createFunction('COUNT(*) AS count');
|
|
||||||
$query->select($avgLat, $avgLng, $count)
|
|
||||||
->from('memories', 'm')
|
|
||||||
;
|
|
||||||
|
|
||||||
// JOIN with filecache for existing files
|
|
||||||
$query = $this->joinFilecache($query, $root, $recursive, $archive);
|
|
||||||
|
|
||||||
// Group by cluster
|
|
||||||
$groupFunction = $query->createFunction('lat DIV '.$gridLength.', lon DIV '.$gridLength);
|
|
||||||
$query->groupBy($groupFunction);
|
|
||||||
|
|
||||||
// Apply all transformations (including map bounds)
|
|
||||||
$this->applyAllTransforms($queryTransforms, $query, $uid);
|
|
||||||
|
|
||||||
$cursor = $this->executeQueryWithCTEs($query);
|
|
||||||
$res = $cursor->fetchAll();
|
|
||||||
$cursor->closeCursor();
|
|
||||||
|
|
||||||
$clusters = [];
|
|
||||||
foreach ($res as $cluster) {
|
|
||||||
$clusters[] =
|
|
||||||
['center' => [(float) $cluster['avgLat'], (float) $cluster['avgLng']], 'count' => (float) $cluster['count']];
|
|
||||||
}
|
|
||||||
|
|
||||||
return $clusters;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Process the days response.
|
* Process the days response.
|
||||||
*
|
*
|
||||||
|
|
|
@ -40,18 +40,6 @@ trait TimelineQueryFilters
|
||||||
$query->setMaxResults($limit);
|
$query->setMaxResults($limit);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function transformBoundFilter(IQueryBuilder &$query, string $userId, array $bounds)
|
|
||||||
{
|
|
||||||
$query->andWhere(
|
|
||||||
$query->expr()->andX(
|
|
||||||
$query->expr()->gte('m.lat', $query->createNamedParameter($bounds[0], IQueryBuilder::PARAM_STR)),
|
|
||||||
$query->expr()->lte('m.lat', $query->createNamedParameter($bounds[1], IQueryBuilder::PARAM_STR)),
|
|
||||||
$query->expr()->gte('m.lon', $query->createNamedParameter($bounds[2], IQueryBuilder::PARAM_STR)),
|
|
||||||
$query->expr()->lte('m.lon', $query->createNamedParameter($bounds[3], IQueryBuilder::PARAM_STR))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function applyAllTransforms(array $transforms, IQueryBuilder &$query, string $uid): void
|
private function applyAllTransforms(array $transforms, IQueryBuilder &$query, string $uid): void
|
||||||
{
|
{
|
||||||
foreach ($transforms as &$transform) {
|
foreach ($transforms as &$transform) {
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace OCA\Memories\Db;
|
||||||
|
|
||||||
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||||
|
|
||||||
|
trait TimelineQueryMap
|
||||||
|
{
|
||||||
|
public function transformMapBoundsFilter(IQueryBuilder &$query, string $userId, string $bounds)
|
||||||
|
{
|
||||||
|
$bounds = explode(',', $bounds);
|
||||||
|
$bounds = array_map('floatval', $bounds);
|
||||||
|
if (4 !== \count($bounds)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$query->andWhere(
|
||||||
|
$query->expr()->andX(
|
||||||
|
$query->expr()->gte('m.lat', $query->createNamedParameter($bounds[0], IQueryBuilder::PARAM_STR)),
|
||||||
|
$query->expr()->lte('m.lat', $query->createNamedParameter($bounds[1], IQueryBuilder::PARAM_STR)),
|
||||||
|
$query->expr()->gte('m.lon', $query->createNamedParameter($bounds[2], IQueryBuilder::PARAM_STR)),
|
||||||
|
$query->expr()->lte('m.lon', $query->createNamedParameter($bounds[3], IQueryBuilder::PARAM_STR))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getMapClusters(
|
||||||
|
float $gridLen,
|
||||||
|
string $bounds,
|
||||||
|
TimelineRoot &$root
|
||||||
|
): array {
|
||||||
|
$query = $this->connection->getQueryBuilder();
|
||||||
|
|
||||||
|
// Get the average location of each cluster
|
||||||
|
$avgLat = $query->createFunction('AVG(m.lat) AS avgLat');
|
||||||
|
$avgLng = $query->createFunction('AVG(m.lon) AS avgLon');
|
||||||
|
$count = $query->createFunction('COUNT(m.fileid) AS count');
|
||||||
|
$query->select($avgLat, $avgLng, $count)
|
||||||
|
->from('memories', 'm')
|
||||||
|
;
|
||||||
|
|
||||||
|
// JOIN with filecache for existing files
|
||||||
|
$query = $this->joinFilecache($query, $root, true, false);
|
||||||
|
|
||||||
|
// Group by cluster
|
||||||
|
$query->addGroupBy($query->createFunction("m.lat DIV {$gridLen}"));
|
||||||
|
$query->addGroupBy($query->createFunction("m.lon DIV {$gridLen}"));
|
||||||
|
|
||||||
|
// Apply all transformations (including map bounds)
|
||||||
|
$this->transformMapBoundsFilter($query, '', $bounds);
|
||||||
|
|
||||||
|
// Execute query
|
||||||
|
$cursor = $this->executeQueryWithCTEs($query);
|
||||||
|
$res = $cursor->fetchAll();
|
||||||
|
$cursor->closeCursor();
|
||||||
|
|
||||||
|
// Post-process results
|
||||||
|
$clusters = [];
|
||||||
|
foreach ($res as $cluster) {
|
||||||
|
$clusters[] =
|
||||||
|
[
|
||||||
|
'center' => [
|
||||||
|
(float) $cluster['avgLat'],
|
||||||
|
(float) $cluster['avgLon'],
|
||||||
|
],
|
||||||
|
'count' => (float) $cluster['count'],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return $clusters;
|
||||||
|
}
|
||||||
|
}
|
|
@ -23,7 +23,6 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from "vue";
|
import { defineComponent } from "vue";
|
||||||
import { LMap, LTileLayer, LMarker, LPopup } from "vue2-leaflet";
|
import { LMap, LTileLayer, LMarker, LPopup } from "vue2-leaflet";
|
||||||
import { IMarkerCluster } from "../../types";
|
|
||||||
import { Icon } from "leaflet";
|
import { Icon } from "leaflet";
|
||||||
|
|
||||||
import { API } from "../../services/API";
|
import { API } from "../../services/API";
|
||||||
|
@ -36,6 +35,11 @@ const TILE_URL = "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png";
|
||||||
const ATTRIBUTION =
|
const ATTRIBUTION =
|
||||||
'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
'© <a target="_blank" href="http://osm.org/copyright">OpenStreetMap</a> contributors';
|
||||||
|
|
||||||
|
type IMarkerCluster = {
|
||||||
|
center: [number, number];
|
||||||
|
count: number;
|
||||||
|
};
|
||||||
|
|
||||||
Icon.Default.mergeOptions({
|
Icon.Default.mergeOptions({
|
||||||
iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
|
iconRetinaUrl: require("leaflet/dist/images/marker-icon-2x.png"),
|
||||||
iconUrl: require("leaflet/dist/images/marker-icon.png"),
|
iconUrl: require("leaflet/dist/images/marker-icon.png"),
|
||||||
|
@ -89,16 +93,9 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
this.$router.replace({ query: { b: bounds, z: zoom } });
|
this.$router.replace({ query: { b: bounds, z: zoom } });
|
||||||
|
|
||||||
// Get query parameters for cluster API
|
|
||||||
// const mapWidth = maxLat - minLat;
|
|
||||||
// const mapHeight = maxLon - minLon;
|
|
||||||
|
|
||||||
// Show clusters correctly while draging the map
|
// Show clusters correctly while draging the map
|
||||||
const query = new URLSearchParams();
|
const query = new URLSearchParams();
|
||||||
// query.set("minLat", (minLat - mapWidth).toString());
|
query.set("bounds", bounds);
|
||||||
// query.set("maxLat", (maxLat + mapWidth).toString());
|
|
||||||
// query.set("minLon", (minLon - mapHeight).toString());
|
|
||||||
// query.set("maxLon", (maxLon + mapHeight).toString());
|
|
||||||
query.set("zoom", zoom);
|
query.set("zoom", zoom);
|
||||||
|
|
||||||
// Make API call
|
// Make API call
|
||||||
|
|
|
@ -14,7 +14,6 @@ import FolderTopMatter from "./FolderTopMatter.vue";
|
||||||
import TagTopMatter from "./TagTopMatter.vue";
|
import TagTopMatter from "./TagTopMatter.vue";
|
||||||
import FaceTopMatter from "./FaceTopMatter.vue";
|
import FaceTopMatter from "./FaceTopMatter.vue";
|
||||||
import AlbumTopMatter from "./AlbumTopMatter.vue";
|
import AlbumTopMatter from "./AlbumTopMatter.vue";
|
||||||
import LocationTopMatter from "./LocationTopMatter.vue";
|
|
||||||
|
|
||||||
import { TopMatterType } from "../../types";
|
import { TopMatterType } from "../../types";
|
||||||
|
|
||||||
|
@ -25,7 +24,6 @@ export default defineComponent({
|
||||||
TagTopMatter,
|
TagTopMatter,
|
||||||
FaceTopMatter,
|
FaceTopMatter,
|
||||||
AlbumTopMatter,
|
AlbumTopMatter,
|
||||||
LocationTopMatter,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
data: () => ({
|
data: () => ({
|
||||||
|
|
13
src/types.ts
13
src/types.ts
|
@ -217,7 +217,6 @@ export enum TopMatterType {
|
||||||
TAG = 2,
|
TAG = 2,
|
||||||
FACE = 3,
|
FACE = 3,
|
||||||
ALBUM = 4,
|
ALBUM = 4,
|
||||||
LOCATION = 5,
|
|
||||||
}
|
}
|
||||||
export type TopMatterFolder = TopMatter & {
|
export type TopMatterFolder = TopMatter & {
|
||||||
type: TopMatterType.FOLDER;
|
type: TopMatterType.FOLDER;
|
||||||
|
@ -239,15 +238,3 @@ export type ISelectionAction = {
|
||||||
/** Allow for public routes (default false) */
|
/** Allow for public routes (default false) */
|
||||||
allowPublic?: boolean;
|
allowPublic?: boolean;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type IMapBoundary = {
|
|
||||||
minLat: number;
|
|
||||||
maxLat: number;
|
|
||||||
minLon: number;
|
|
||||||
maxLon: number;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type IMarkerCluster = {
|
|
||||||
center: [number, number];
|
|
||||||
count: number;
|
|
||||||
};
|
|
||||||
|
|
Loading…
Reference in New Issue