1
0
mirror of https://github.com/immich-app/immich.git synced 2025-04-13 12:00:57 +02:00

feat(server, web): Include partner's photos on map (#7065)

* feat(server): Include partner's photos on map - if included in timeline

* depend on query parameter withPartners

instead of partners.inTimeline

* web: map option to include partners images

* make open-api
This commit is contained in:
Torbjorn Tyridal 2024-02-14 16:07:00 +01:00 committed by GitHub
parent 7d59900662
commit 6adff50f0a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 70 additions and 19 deletions

View File

@ -659,7 +659,7 @@ This endpoint does not need any parameter.
[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
# **getMapMarkers**
> List<MapMarkerResponseDto> getMapMarkers(fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite)
> List<MapMarkerResponseDto> getMapMarkers(fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite, withPartners)
@ -686,9 +686,10 @@ final fileCreatedAfter = 2013-10-20T19:20:30+01:00; // DateTime |
final fileCreatedBefore = 2013-10-20T19:20:30+01:00; // DateTime |
final isArchived = true; // bool |
final isFavorite = true; // bool |
final withPartners = true; // bool |
try {
final result = api_instance.getMapMarkers(fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite);
final result = api_instance.getMapMarkers(fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite, withPartners);
print(result);
} catch (e) {
print('Exception when calling AssetApi->getMapMarkers: $e\n');
@ -703,6 +704,7 @@ Name | Type | Description | Notes
**fileCreatedBefore** | **DateTime**| | [optional]
**isArchived** | **bool**| | [optional]
**isFavorite** | **bool**| | [optional]
**withPartners** | **bool**| | [optional]
### Return type

View File

@ -652,7 +652,9 @@ class AssetApi {
/// * [bool] isArchived:
///
/// * [bool] isFavorite:
Future<Response> getMapMarkersWithHttpInfo({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, }) async {
///
/// * [bool] withPartners:
Future<Response> getMapMarkersWithHttpInfo({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, }) async {
// ignore: prefer_const_declarations
final path = r'/asset/map-marker';
@ -675,6 +677,9 @@ class AssetApi {
if (isFavorite != null) {
queryParams.addAll(_queryParams('', 'isFavorite', isFavorite));
}
if (withPartners != null) {
queryParams.addAll(_queryParams('', 'withPartners', withPartners));
}
const contentTypes = <String>[];
@ -699,8 +704,10 @@ class AssetApi {
/// * [bool] isArchived:
///
/// * [bool] isFavorite:
Future<List<MapMarkerResponseDto>?> getMapMarkers({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, }) async {
final response = await getMapMarkersWithHttpInfo( fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, isArchived: isArchived, isFavorite: isFavorite, );
///
/// * [bool] withPartners:
Future<List<MapMarkerResponseDto>?> getMapMarkers({ DateTime? fileCreatedAfter, DateTime? fileCreatedBefore, bool? isArchived, bool? isFavorite, bool? withPartners, }) async {
final response = await getMapMarkersWithHttpInfo( fileCreatedAfter: fileCreatedAfter, fileCreatedBefore: fileCreatedBefore, isArchived: isArchived, isFavorite: isFavorite, withPartners: withPartners, );
if (response.statusCode >= HttpStatus.badRequest) {
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
}

View File

@ -80,7 +80,7 @@ void main() {
// TODO
});
//Future<List<MapMarkerResponseDto>> getMapMarkers({ DateTime fileCreatedAfter, DateTime fileCreatedBefore, bool isArchived, bool isFavorite }) async
//Future<List<MapMarkerResponseDto>> getMapMarkers({ DateTime fileCreatedAfter, DateTime fileCreatedBefore, bool isArchived, bool isFavorite, bool withPartners }) async
test('test getMapMarkers', () async {
// TODO
});

View File

@ -1397,6 +1397,14 @@
"schema": {
"type": "boolean"
}
},
{
"name": "withPartners",
"required": false,
"in": "query",
"schema": {
"type": "boolean"
}
}
],
"responses": {

View File

@ -7363,10 +7363,11 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
* @param {string} [fileCreatedBefore]
* @param {boolean} [isArchived]
* @param {boolean} [isFavorite]
* @param {boolean} [withPartners]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
getMapMarkers: async (fileCreatedAfter?: string, fileCreatedBefore?: string, isArchived?: boolean, isFavorite?: boolean, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
getMapMarkers: async (fileCreatedAfter?: string, fileCreatedBefore?: string, isArchived?: boolean, isFavorite?: boolean, withPartners?: boolean, options: RawAxiosRequestConfig = {}): Promise<RequestArgs> => {
const localVarPath = `/asset/map-marker`;
// use dummy base URL string because the URL constructor only accepts absolute URLs.
const localVarUrlObj = new URL(localVarPath, DUMMY_BASE_URL);
@ -7408,6 +7409,10 @@ export const AssetApiAxiosParamCreator = function (configuration?: Configuration
localVarQueryParameter['isFavorite'] = isFavorite;
}
if (withPartners !== undefined) {
localVarQueryParameter['withPartners'] = withPartners;
}
setSearchParams(localVarUrlObj, localVarQueryParameter);
@ -8487,11 +8492,12 @@ export const AssetApiFp = function(configuration?: Configuration) {
* @param {string} [fileCreatedBefore]
* @param {boolean} [isArchived]
* @param {boolean} [isFavorite]
* @param {boolean} [withPartners]
* @param {*} [options] Override http request option.
* @throws {RequiredError}
*/
async getMapMarkers(fileCreatedAfter?: string, fileCreatedBefore?: string, isArchived?: boolean, isFavorite?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MapMarkerResponseDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMapMarkers(fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite, options);
async getMapMarkers(fileCreatedAfter?: string, fileCreatedBefore?: string, isArchived?: boolean, isFavorite?: boolean, withPartners?: boolean, options?: RawAxiosRequestConfig): Promise<(axios?: AxiosInstance, basePath?: string) => AxiosPromise<Array<MapMarkerResponseDto>>> {
const localVarAxiosArgs = await localVarAxiosParamCreator.getMapMarkers(fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite, withPartners, options);
const index = configuration?.serverIndex ?? 0;
const operationBasePath = operationServerMap['AssetApi.getMapMarkers']?.[index]?.url;
return (axios, basePath) => createRequestFunction(localVarAxiosArgs, globalAxios, BASE_PATH, configuration)(axios, operationBasePath || basePath);
@ -8821,7 +8827,7 @@ export const AssetApiFactory = function (configuration?: Configuration, basePath
* @throws {RequiredError}
*/
getMapMarkers(requestParameters: AssetApiGetMapMarkersRequest = {}, options?: RawAxiosRequestConfig): AxiosPromise<Array<MapMarkerResponseDto>> {
return localVarFp.getMapMarkers(requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, requestParameters.isArchived, requestParameters.isFavorite, options).then((request) => request(axios, basePath));
return localVarFp.getMapMarkers(requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, requestParameters.isArchived, requestParameters.isFavorite, requestParameters.withPartners, options).then((request) => request(axios, basePath));
},
/**
*
@ -9155,6 +9161,13 @@ export interface AssetApiGetMapMarkersRequest {
* @memberof AssetApiGetMapMarkers
*/
readonly isFavorite?: boolean
/**
*
* @type {boolean}
* @memberof AssetApiGetMapMarkers
*/
readonly withPartners?: boolean
}
/**
@ -9997,7 +10010,7 @@ export class AssetApi extends BaseAPI {
* @memberof AssetApi
*/
public getMapMarkers(requestParameters: AssetApiGetMapMarkersRequest = {}, options?: RawAxiosRequestConfig) {
return AssetApiFp(this.configuration).getMapMarkers(requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, requestParameters.isArchived, requestParameters.isFavorite, options).then((request) => request(this.axios, this.basePath));
return AssetApiFp(this.configuration).getMapMarkers(requestParameters.fileCreatedAfter, requestParameters.fileCreatedBefore, requestParameters.isArchived, requestParameters.isFavorite, requestParameters.withPartners, options).then((request) => request(this.axios, this.basePath));
}
/**

View File

@ -1240,11 +1240,12 @@ export function runAssetJobs({ assetJobsDto }: {
body: assetJobsDto
})));
}
export function getMapMarkers({ fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite }: {
export function getMapMarkers({ fileCreatedAfter, fileCreatedBefore, isArchived, isFavorite, withPartners }: {
fileCreatedAfter?: string;
fileCreatedBefore?: string;
isArchived?: boolean;
isFavorite?: boolean;
withPartners?: boolean;
}, opts?: Oazapfts.RequestOpts) {
return oazapfts.ok(oazapfts.fetchJson<{
status: 200;
@ -1253,7 +1254,8 @@ export function getMapMarkers({ fileCreatedAfter, fileCreatedBefore, isArchived,
fileCreatedAfter,
fileCreatedBefore,
isArchived,
isFavorite
isFavorite,
withPartners
}))}`, {
...opts
}));

View File

@ -286,6 +286,7 @@ describe(AssetService.name, () => {
describe('getMapMarkers', () => {
it('should get geo information of assets', async () => {
partnerMock.getAll.mockResolvedValue([]);
assetMock.getMapMarkers.mockResolvedValue(
[assetStub.withLocation].map((asset) => ({
id: asset.id,

View File

@ -157,8 +157,16 @@ export class AssetService {
return folder;
}
getMapMarkers(auth: AuthDto, options: MapMarkerDto): Promise<MapMarkerResponseDto[]> {
return this.assetRepository.getMapMarkers(auth.user.id, options);
async getMapMarkers(auth: AuthDto, options: MapMarkerDto): Promise<MapMarkerResponseDto[]> {
const userIds: string[] = [auth.user.id];
if (options.withPartners) {
const partners = await this.partnerRepository.getAll(auth.user.id);
const partnersIds = partners
.filter((partner) => partner.sharedBy && partner.sharedWith && partner.sharedById != auth.user.id)
.map((partner) => partner.sharedById);
userIds.push(...partnersIds);
}
return this.assetRepository.getMapMarkers(userIds, options);
}
async getMemoryLane(auth: AuthDto, dto: MemoryLaneDto): Promise<MemoryLaneResponseDto[]> {

View File

@ -25,4 +25,10 @@ export class MapMarkerDto {
@IsDate()
@Type(() => Date)
fileCreatedBefore?: Date;
@ApiProperty()
@Optional()
@IsBoolean()
@Transform(toBoolean)
withPartners?: boolean;
}

View File

@ -140,7 +140,7 @@ export interface IAssetRepository {
softDeleteAll(ids: string[]): Promise<void>;
restoreAll(ids: string[]): Promise<void>;
findLivePhotoMatch(options: LivePhotoSearchOptions): Promise<AssetEntity | null>;
getMapMarkers(ownerId: string, options?: MapMarkerSearchOptions): Promise<MapMarker[]>;
getMapMarkers(ownerIds: string[], options?: MapMarkerSearchOptions): Promise<MapMarker[]>;
getStatistics(ownerId: string, options: AssetStatsOptions): Promise<AssetStats>;
getTimeBuckets(options: TimeBucketOptions): Promise<TimeBucketItem[]>;
getTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]>;

View File

@ -472,7 +472,7 @@ export class AssetRepository implements IAssetRepository {
});
}
async getMapMarkers(ownerId: string, options: MapMarkerSearchOptions = {}): Promise<MapMarker[]> {
async getMapMarkers(ownerIds: string[], options: MapMarkerSearchOptions = {}): Promise<MapMarker[]> {
const { isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore } = options;
const assets = await this.repository.find({
@ -484,7 +484,7 @@ export class AssetRepository implements IAssetRepository {
},
},
where: {
ownerId,
ownerId: In([...ownerIds]),
isVisible: true,
isArchived,
exifInfo: {

View File

@ -33,6 +33,7 @@
<SettingSwitch title="Allow dark mode" bind:checked={settings.allowDarkMode} />
<SettingSwitch title="Only favorites" bind:checked={settings.onlyFavorites} />
<SettingSwitch title="Include archived" bind:checked={settings.includeArchived} />
<SettingSwitch title="Include shared with me" bind:checked={settings.withPartners} />
{#if customDateRange}
<div in:fly={{ y: 10, duration: 200 }} class="flex flex-col gap-4">
<div class="flex items-center justify-between gap-8">

View File

@ -46,6 +46,7 @@ export interface MapSettings {
allowDarkMode: boolean;
includeArchived: boolean;
onlyFavorites: boolean;
withPartners: boolean;
relativeDate: string;
dateAfter: string;
dateBefore: string;
@ -55,6 +56,7 @@ export const mapSettings = persisted<MapSettings>('map-settings', {
allowDarkMode: true,
includeArchived: false,
onlyFavorites: false,
withPartners: false,
relativeDate: '',
dateAfter: '',
dateBefore: '',

View File

@ -46,7 +46,7 @@
}
abortController = new AbortController();
const { includeArchived, onlyFavorites } = $mapSettings;
const { includeArchived, onlyFavorites, withPartners } = $mapSettings;
const { fileCreatedAfter, fileCreatedBefore } = getFileCreatedDates();
return await getMapMarkers(
@ -55,6 +55,7 @@
isFavorite: onlyFavorites || undefined,
fileCreatedAfter: fileCreatedAfter || undefined,
fileCreatedBefore,
withPartners: withPartners || undefined,
},
{
signal: abortController.signal,