feat(server): reverse geocoding endpoint (#11430)

* feat(server): reverse geocoding endpoint

* chore: rename error message
This commit is contained in:
Jason Rasmussen
2024-07-29 18:17:26 -04:00
committed by GitHub
parent a70cd368af
commit ebc71e428d
12 changed files with 443 additions and 42 deletions

View File

@@ -1,7 +1,12 @@
import { Controller, Get, Query } from '@nestjs/common';
import { Controller, Get, HttpCode, HttpStatus, Query } from '@nestjs/common';
import { ApiTags } from '@nestjs/swagger';
import { AuthDto } from 'src/dtos/auth.dto';
import { MapMarkerDto, MapMarkerResponseDto } from 'src/dtos/search.dto';
import {
MapMarkerDto,
MapMarkerResponseDto,
MapReverseGeocodeDto,
MapReverseGeocodeResponseDto,
} from 'src/dtos/map.dto';
import { MapThemeDto } from 'src/dtos/system-config.dto';
import { Auth, Authenticated } from 'src/middleware/auth.guard';
import { MapService } from 'src/services/map.service';
@@ -22,4 +27,11 @@ export class MapController {
getMapStyle(@Query() dto: MapThemeDto) {
return this.service.getMapStyle(dto.theme);
}
@Authenticated()
@Get('reverse-geocode')
@HttpCode(HttpStatus.OK)
reverseGeocode(@Query() dto: MapReverseGeocodeDto): Promise<MapReverseGeocodeResponseDto[]> {
return this.service.reverseGeocode(dto);
}
}

View File

@@ -0,0 +1,67 @@
import { ApiProperty } from '@nestjs/swagger';
import { Type } from 'class-transformer';
import { IsLatitude, IsLongitude } from 'class-validator';
import { ValidateBoolean, ValidateDate } from 'src/validation';
export class MapReverseGeocodeDto {
@ApiProperty({ format: 'double' })
@Type(() => Number)
@IsLatitude({ message: ({ property }) => `${property} must be a number between -90 and 90` })
lat!: number;
@ApiProperty({ format: 'double' })
@Type(() => Number)
@IsLongitude({ message: ({ property }) => `${property} must be a number between -180 and 180` })
lon!: number;
}
export class MapReverseGeocodeResponseDto {
@ApiProperty()
city!: string | null;
@ApiProperty()
state!: string | null;
@ApiProperty()
country!: string | null;
}
export class MapMarkerDto {
@ValidateBoolean({ optional: true })
isArchived?: boolean;
@ValidateBoolean({ optional: true })
isFavorite?: boolean;
@ValidateDate({ optional: true })
fileCreatedAfter?: Date;
@ValidateDate({ optional: true })
fileCreatedBefore?: Date;
@ValidateBoolean({ optional: true })
withPartners?: boolean;
@ValidateBoolean({ optional: true })
withSharedAlbums?: boolean;
}
export class MapMarkerResponseDto {
@ApiProperty()
id!: string;
@ApiProperty({ format: 'double' })
lat!: number;
@ApiProperty({ format: 'double' })
lon!: number;
@ApiProperty()
city!: string | null;
@ApiProperty()
state!: string | null;
@ApiProperty()
country!: string | null;
}

View File

@@ -289,26 +289,6 @@ export class SearchExploreResponseDto {
items!: SearchExploreItem[];
}
export class MapMarkerDto {
@ValidateBoolean({ optional: true })
isArchived?: boolean;
@ValidateBoolean({ optional: true })
isFavorite?: boolean;
@ValidateDate({ optional: true })
fileCreatedAfter?: Date;
@ValidateDate({ optional: true })
fileCreatedBefore?: Date;
@ValidateBoolean({ optional: true })
withPartners?: boolean;
@ValidateBoolean({ optional: true })
withSharedAlbums?: boolean;
}
export class MemoryLaneDto {
@IsInt()
@Type(() => Number)
@@ -324,22 +304,3 @@ export class MemoryLaneDto {
@ApiProperty({ type: 'integer' })
month!: number;
}
export class MapMarkerResponseDto {
@ApiProperty()
id!: string;
@ApiProperty({ format: 'double' })
lat!: number;
@ApiProperty({ format: 'double' })
lon!: number;
@ApiProperty()
city!: string | null;
@ApiProperty()
state!: string | null;
@ApiProperty()
country!: string | null;
}

View File

@@ -1,7 +1,7 @@
import { Inject } from '@nestjs/common';
import { SystemConfigCore } from 'src/cores/system-config.core';
import { AuthDto } from 'src/dtos/auth.dto';
import { MapMarkerDto, MapMarkerResponseDto } from 'src/dtos/search.dto';
import { MapMarkerDto, MapMarkerResponseDto, MapReverseGeocodeDto } from 'src/dtos/map.dto';
import { IAlbumRepository } from 'src/interfaces/album.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { IMapRepository } from 'src/interfaces/map.interface';
@@ -53,4 +53,11 @@ export class MapService {
return JSON.parse(await this.systemMetadataRepository.readFile(`./resources/style-${theme}.json`));
}
async reverseGeocode(dto: MapReverseGeocodeDto) {
const { lat: latitude, lon: longitude } = dto;
// eventually this should probably return an array of results
const result = await this.mapRepository.reverseGeocode({ latitude, longitude });
return result ? [result] : [];
}
}