mirror of
https://github.com/immich-app/immich.git
synced 2025-02-15 19:36:04 +02:00
fix(server): album statistics endpoint (#11924)
This commit is contained in:
parent
cde0458dc8
commit
ef9a06be5c
@ -344,16 +344,16 @@ describe('/albums', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GET /albums/count', () => {
|
describe('GET /albums/statistics', () => {
|
||||||
it('should require authentication', async () => {
|
it('should require authentication', async () => {
|
||||||
const { status, body } = await request(app).get('/albums/count');
|
const { status, body } = await request(app).get('/albums/statistics');
|
||||||
expect(status).toBe(401);
|
expect(status).toBe(401);
|
||||||
expect(body).toEqual(errorDto.unauthorized);
|
expect(body).toEqual(errorDto.unauthorized);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should return total count of albums the user has access to', async () => {
|
it('should return total count of albums the user has access to', async () => {
|
||||||
const { status, body } = await request(app)
|
const { status, body } = await request(app)
|
||||||
.get('/albums/count')
|
.get('/albums/statistics')
|
||||||
.set('Authorization', `Bearer ${user1.accessToken}`);
|
.set('Authorization', `Bearer ${user1.accessToken}`);
|
||||||
|
|
||||||
expect(status).toBe(200);
|
expect(status).toBe(200);
|
||||||
|
4
mobile/openapi/README.md
generated
4
mobile/openapi/README.md
generated
@ -86,8 +86,8 @@ Class | Method | HTTP request | Description
|
|||||||
*AlbumsApi* | [**addUsersToAlbum**](doc//AlbumsApi.md#adduserstoalbum) | **PUT** /albums/{id}/users |
|
*AlbumsApi* | [**addUsersToAlbum**](doc//AlbumsApi.md#adduserstoalbum) | **PUT** /albums/{id}/users |
|
||||||
*AlbumsApi* | [**createAlbum**](doc//AlbumsApi.md#createalbum) | **POST** /albums |
|
*AlbumsApi* | [**createAlbum**](doc//AlbumsApi.md#createalbum) | **POST** /albums |
|
||||||
*AlbumsApi* | [**deleteAlbum**](doc//AlbumsApi.md#deletealbum) | **DELETE** /albums/{id} |
|
*AlbumsApi* | [**deleteAlbum**](doc//AlbumsApi.md#deletealbum) | **DELETE** /albums/{id} |
|
||||||
*AlbumsApi* | [**getAlbumCount**](doc//AlbumsApi.md#getalbumcount) | **GET** /albums/count |
|
|
||||||
*AlbumsApi* | [**getAlbumInfo**](doc//AlbumsApi.md#getalbuminfo) | **GET** /albums/{id} |
|
*AlbumsApi* | [**getAlbumInfo**](doc//AlbumsApi.md#getalbuminfo) | **GET** /albums/{id} |
|
||||||
|
*AlbumsApi* | [**getAlbumStatistics**](doc//AlbumsApi.md#getalbumstatistics) | **GET** /albums/statistics |
|
||||||
*AlbumsApi* | [**getAllAlbums**](doc//AlbumsApi.md#getallalbums) | **GET** /albums |
|
*AlbumsApi* | [**getAllAlbums**](doc//AlbumsApi.md#getallalbums) | **GET** /albums |
|
||||||
*AlbumsApi* | [**removeAssetFromAlbum**](doc//AlbumsApi.md#removeassetfromalbum) | **DELETE** /albums/{id}/assets |
|
*AlbumsApi* | [**removeAssetFromAlbum**](doc//AlbumsApi.md#removeassetfromalbum) | **DELETE** /albums/{id}/assets |
|
||||||
*AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} |
|
*AlbumsApi* | [**removeUserFromAlbum**](doc//AlbumsApi.md#removeuserfromalbum) | **DELETE** /albums/{id}/user/{userId} |
|
||||||
@ -265,8 +265,8 @@ Class | Method | HTTP request | Description
|
|||||||
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
|
- [ActivityStatisticsResponseDto](doc//ActivityStatisticsResponseDto.md)
|
||||||
- [AddUsersDto](doc//AddUsersDto.md)
|
- [AddUsersDto](doc//AddUsersDto.md)
|
||||||
- [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md)
|
- [AdminOnboardingUpdateDto](doc//AdminOnboardingUpdateDto.md)
|
||||||
- [AlbumCountResponseDto](doc//AlbumCountResponseDto.md)
|
|
||||||
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
- [AlbumResponseDto](doc//AlbumResponseDto.md)
|
||||||
|
- [AlbumStatisticsResponseDto](doc//AlbumStatisticsResponseDto.md)
|
||||||
- [AlbumUserAddDto](doc//AlbumUserAddDto.md)
|
- [AlbumUserAddDto](doc//AlbumUserAddDto.md)
|
||||||
- [AlbumUserCreateDto](doc//AlbumUserCreateDto.md)
|
- [AlbumUserCreateDto](doc//AlbumUserCreateDto.md)
|
||||||
- [AlbumUserResponseDto](doc//AlbumUserResponseDto.md)
|
- [AlbumUserResponseDto](doc//AlbumUserResponseDto.md)
|
||||||
|
2
mobile/openapi/lib/api.dart
generated
2
mobile/openapi/lib/api.dart
generated
@ -73,8 +73,8 @@ part 'model/activity_response_dto.dart';
|
|||||||
part 'model/activity_statistics_response_dto.dart';
|
part 'model/activity_statistics_response_dto.dart';
|
||||||
part 'model/add_users_dto.dart';
|
part 'model/add_users_dto.dart';
|
||||||
part 'model/admin_onboarding_update_dto.dart';
|
part 'model/admin_onboarding_update_dto.dart';
|
||||||
part 'model/album_count_response_dto.dart';
|
|
||||||
part 'model/album_response_dto.dart';
|
part 'model/album_response_dto.dart';
|
||||||
|
part 'model/album_statistics_response_dto.dart';
|
||||||
part 'model/album_user_add_dto.dart';
|
part 'model/album_user_add_dto.dart';
|
||||||
part 'model/album_user_create_dto.dart';
|
part 'model/album_user_create_dto.dart';
|
||||||
part 'model/album_user_response_dto.dart';
|
part 'model/album_user_response_dto.dart';
|
||||||
|
82
mobile/openapi/lib/api/albums_api.dart
generated
82
mobile/openapi/lib/api/albums_api.dart
generated
@ -218,47 +218,6 @@ class AlbumsApi {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /albums/count' operation and returns the [Response].
|
|
||||||
Future<Response> getAlbumCountWithHttpInfo() async {
|
|
||||||
// ignore: prefer_const_declarations
|
|
||||||
final path = r'/albums/count';
|
|
||||||
|
|
||||||
// ignore: prefer_final_locals
|
|
||||||
Object? postBody;
|
|
||||||
|
|
||||||
final queryParams = <QueryParam>[];
|
|
||||||
final headerParams = <String, String>{};
|
|
||||||
final formParams = <String, String>{};
|
|
||||||
|
|
||||||
const contentTypes = <String>[];
|
|
||||||
|
|
||||||
|
|
||||||
return apiClient.invokeAPI(
|
|
||||||
path,
|
|
||||||
'GET',
|
|
||||||
queryParams,
|
|
||||||
postBody,
|
|
||||||
headerParams,
|
|
||||||
formParams,
|
|
||||||
contentTypes.isEmpty ? null : contentTypes.first,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<AlbumCountResponseDto?> getAlbumCount() async {
|
|
||||||
final response = await getAlbumCountWithHttpInfo();
|
|
||||||
if (response.statusCode >= HttpStatus.badRequest) {
|
|
||||||
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
|
||||||
}
|
|
||||||
// When a remote server returns no body with a status of 204, we shall not decode it.
|
|
||||||
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
|
||||||
// FormatException when trying to decode an empty string.
|
|
||||||
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
|
||||||
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AlbumCountResponseDto',) as AlbumCountResponseDto;
|
|
||||||
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /albums/{id}' operation and returns the [Response].
|
/// Performs an HTTP 'GET /albums/{id}' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
@ -322,6 +281,47 @@ class AlbumsApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Performs an HTTP 'GET /albums/statistics' operation and returns the [Response].
|
||||||
|
Future<Response> getAlbumStatisticsWithHttpInfo() async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final path = r'/albums/statistics';
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
path,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<AlbumStatisticsResponseDto?> getAlbumStatistics() async {
|
||||||
|
final response = await getAlbumStatisticsWithHttpInfo();
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
return await apiClient.deserializeAsync(await _decodeBodyBytes(response), 'AlbumStatisticsResponseDto',) as AlbumStatisticsResponseDto;
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Performs an HTTP 'GET /albums' operation and returns the [Response].
|
/// Performs an HTTP 'GET /albums' operation and returns the [Response].
|
||||||
/// Parameters:
|
/// Parameters:
|
||||||
///
|
///
|
||||||
|
4
mobile/openapi/lib/api_client.dart
generated
4
mobile/openapi/lib/api_client.dart
generated
@ -201,10 +201,10 @@ class ApiClient {
|
|||||||
return AddUsersDto.fromJson(value);
|
return AddUsersDto.fromJson(value);
|
||||||
case 'AdminOnboardingUpdateDto':
|
case 'AdminOnboardingUpdateDto':
|
||||||
return AdminOnboardingUpdateDto.fromJson(value);
|
return AdminOnboardingUpdateDto.fromJson(value);
|
||||||
case 'AlbumCountResponseDto':
|
|
||||||
return AlbumCountResponseDto.fromJson(value);
|
|
||||||
case 'AlbumResponseDto':
|
case 'AlbumResponseDto':
|
||||||
return AlbumResponseDto.fromJson(value);
|
return AlbumResponseDto.fromJson(value);
|
||||||
|
case 'AlbumStatisticsResponseDto':
|
||||||
|
return AlbumStatisticsResponseDto.fromJson(value);
|
||||||
case 'AlbumUserAddDto':
|
case 'AlbumUserAddDto':
|
||||||
return AlbumUserAddDto.fromJson(value);
|
return AlbumUserAddDto.fromJson(value);
|
||||||
case 'AlbumUserCreateDto':
|
case 'AlbumUserCreateDto':
|
||||||
|
@ -10,9 +10,9 @@
|
|||||||
|
|
||||||
part of openapi.api;
|
part of openapi.api;
|
||||||
|
|
||||||
class AlbumCountResponseDto {
|
class AlbumStatisticsResponseDto {
|
||||||
/// Returns a new [AlbumCountResponseDto] instance.
|
/// Returns a new [AlbumStatisticsResponseDto] instance.
|
||||||
AlbumCountResponseDto({
|
AlbumStatisticsResponseDto({
|
||||||
required this.notShared,
|
required this.notShared,
|
||||||
required this.owned,
|
required this.owned,
|
||||||
required this.shared,
|
required this.shared,
|
||||||
@ -25,7 +25,7 @@ class AlbumCountResponseDto {
|
|||||||
int shared;
|
int shared;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) => identical(this, other) || other is AlbumCountResponseDto &&
|
bool operator ==(Object other) => identical(this, other) || other is AlbumStatisticsResponseDto &&
|
||||||
other.notShared == notShared &&
|
other.notShared == notShared &&
|
||||||
other.owned == owned &&
|
other.owned == owned &&
|
||||||
other.shared == shared;
|
other.shared == shared;
|
||||||
@ -38,7 +38,7 @@ class AlbumCountResponseDto {
|
|||||||
(shared.hashCode);
|
(shared.hashCode);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() => 'AlbumCountResponseDto[notShared=$notShared, owned=$owned, shared=$shared]';
|
String toString() => 'AlbumStatisticsResponseDto[notShared=$notShared, owned=$owned, shared=$shared]';
|
||||||
|
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
final json = <String, dynamic>{};
|
final json = <String, dynamic>{};
|
||||||
@ -48,14 +48,14 @@ class AlbumCountResponseDto {
|
|||||||
return json;
|
return json;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a new [AlbumCountResponseDto] instance and imports its values from
|
/// Returns a new [AlbumStatisticsResponseDto] instance and imports its values from
|
||||||
/// [value] if it's a [Map], null otherwise.
|
/// [value] if it's a [Map], null otherwise.
|
||||||
// ignore: prefer_constructors_over_static_methods
|
// ignore: prefer_constructors_over_static_methods
|
||||||
static AlbumCountResponseDto? fromJson(dynamic value) {
|
static AlbumStatisticsResponseDto? fromJson(dynamic value) {
|
||||||
if (value is Map) {
|
if (value is Map) {
|
||||||
final json = value.cast<String, dynamic>();
|
final json = value.cast<String, dynamic>();
|
||||||
|
|
||||||
return AlbumCountResponseDto(
|
return AlbumStatisticsResponseDto(
|
||||||
notShared: mapValueOfType<int>(json, r'notShared')!,
|
notShared: mapValueOfType<int>(json, r'notShared')!,
|
||||||
owned: mapValueOfType<int>(json, r'owned')!,
|
owned: mapValueOfType<int>(json, r'owned')!,
|
||||||
shared: mapValueOfType<int>(json, r'shared')!,
|
shared: mapValueOfType<int>(json, r'shared')!,
|
||||||
@ -64,11 +64,11 @@ class AlbumCountResponseDto {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<AlbumCountResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
static List<AlbumStatisticsResponseDto> listFromJson(dynamic json, {bool growable = false,}) {
|
||||||
final result = <AlbumCountResponseDto>[];
|
final result = <AlbumStatisticsResponseDto>[];
|
||||||
if (json is List && json.isNotEmpty) {
|
if (json is List && json.isNotEmpty) {
|
||||||
for (final row in json) {
|
for (final row in json) {
|
||||||
final value = AlbumCountResponseDto.fromJson(row);
|
final value = AlbumStatisticsResponseDto.fromJson(row);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
result.add(value);
|
result.add(value);
|
||||||
}
|
}
|
||||||
@ -77,12 +77,12 @@ class AlbumCountResponseDto {
|
|||||||
return result.toList(growable: growable);
|
return result.toList(growable: growable);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Map<String, AlbumCountResponseDto> mapFromJson(dynamic json) {
|
static Map<String, AlbumStatisticsResponseDto> mapFromJson(dynamic json) {
|
||||||
final map = <String, AlbumCountResponseDto>{};
|
final map = <String, AlbumStatisticsResponseDto>{};
|
||||||
if (json is Map && json.isNotEmpty) {
|
if (json is Map && json.isNotEmpty) {
|
||||||
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
json = json.cast<String, dynamic>(); // ignore: parameter_assignments
|
||||||
for (final entry in json.entries) {
|
for (final entry in json.entries) {
|
||||||
final value = AlbumCountResponseDto.fromJson(entry.value);
|
final value = AlbumStatisticsResponseDto.fromJson(entry.value);
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
map[entry.key] = value;
|
map[entry.key] = value;
|
||||||
}
|
}
|
||||||
@ -91,14 +91,14 @@ class AlbumCountResponseDto {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// maps a json object with a list of AlbumCountResponseDto-objects as value to a dart map
|
// maps a json object with a list of AlbumStatisticsResponseDto-objects as value to a dart map
|
||||||
static Map<String, List<AlbumCountResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
static Map<String, List<AlbumStatisticsResponseDto>> mapListFromJson(dynamic json, {bool growable = false,}) {
|
||||||
final map = <String, List<AlbumCountResponseDto>>{};
|
final map = <String, List<AlbumStatisticsResponseDto>>{};
|
||||||
if (json is Map && json.isNotEmpty) {
|
if (json is Map && json.isNotEmpty) {
|
||||||
// ignore: parameter_assignments
|
// ignore: parameter_assignments
|
||||||
json = json.cast<String, dynamic>();
|
json = json.cast<String, dynamic>();
|
||||||
for (final entry in json.entries) {
|
for (final entry in json.entries) {
|
||||||
map[entry.key] = AlbumCountResponseDto.listFromJson(entry.value, growable: growable,);
|
map[entry.key] = AlbumStatisticsResponseDto.listFromJson(entry.value, growable: growable,);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return map;
|
return map;
|
@ -660,16 +660,16 @@
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/albums/count": {
|
"/albums/statistics": {
|
||||||
"get": {
|
"get": {
|
||||||
"operationId": "getAlbumCount",
|
"operationId": "getAlbumStatistics",
|
||||||
"parameters": [],
|
"parameters": [],
|
||||||
"responses": {
|
"responses": {
|
||||||
"200": {
|
"200": {
|
||||||
"content": {
|
"content": {
|
||||||
"application/json": {
|
"application/json": {
|
||||||
"schema": {
|
"schema": {
|
||||||
"$ref": "#/components/schemas/AlbumCountResponseDto"
|
"$ref": "#/components/schemas/AlbumStatisticsResponseDto"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -7505,25 +7505,6 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"AlbumCountResponseDto": {
|
|
||||||
"properties": {
|
|
||||||
"notShared": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"owned": {
|
|
||||||
"type": "integer"
|
|
||||||
},
|
|
||||||
"shared": {
|
|
||||||
"type": "integer"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"required": [
|
|
||||||
"notShared",
|
|
||||||
"owned",
|
|
||||||
"shared"
|
|
||||||
],
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"AlbumResponseDto": {
|
"AlbumResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"albumName": {
|
"albumName": {
|
||||||
@ -7611,6 +7592,25 @@
|
|||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"AlbumStatisticsResponseDto": {
|
||||||
|
"properties": {
|
||||||
|
"notShared": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"owned": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"shared": {
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": [
|
||||||
|
"notShared",
|
||||||
|
"owned",
|
||||||
|
"shared"
|
||||||
|
],
|
||||||
|
"type": "object"
|
||||||
|
},
|
||||||
"AlbumUserAddDto": {
|
"AlbumUserAddDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"role": {
|
"role": {
|
||||||
|
@ -268,7 +268,7 @@ export type CreateAlbumDto = {
|
|||||||
assetIds?: string[];
|
assetIds?: string[];
|
||||||
description?: string;
|
description?: string;
|
||||||
};
|
};
|
||||||
export type AlbumCountResponseDto = {
|
export type AlbumStatisticsResponseDto = {
|
||||||
notShared: number;
|
notShared: number;
|
||||||
owned: number;
|
owned: number;
|
||||||
shared: number;
|
shared: number;
|
||||||
@ -1369,11 +1369,11 @@ export function createAlbum({ createAlbumDto }: {
|
|||||||
body: createAlbumDto
|
body: createAlbumDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
export function getAlbumCount(opts?: Oazapfts.RequestOpts) {
|
export function getAlbumStatistics(opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
status: 200;
|
status: 200;
|
||||||
data: AlbumCountResponseDto;
|
data: AlbumStatisticsResponseDto;
|
||||||
}>("/albums/count", {
|
}>("/albums/statistics", {
|
||||||
...opts
|
...opts
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@
|
|||||||
import { ApiTags } from '@nestjs/swagger';
|
import { ApiTags } from '@nestjs/swagger';
|
||||||
import {
|
import {
|
||||||
AddUsersDto,
|
AddUsersDto,
|
||||||
AlbumCountResponseDto,
|
|
||||||
AlbumInfoDto,
|
AlbumInfoDto,
|
||||||
AlbumResponseDto,
|
AlbumResponseDto,
|
||||||
|
AlbumStatisticsResponseDto,
|
||||||
CreateAlbumDto,
|
CreateAlbumDto,
|
||||||
GetAlbumsDto,
|
GetAlbumsDto,
|
||||||
UpdateAlbumDto,
|
UpdateAlbumDto,
|
||||||
@ -22,12 +22,6 @@ import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation';
|
|||||||
export class AlbumController {
|
export class AlbumController {
|
||||||
constructor(private service: AlbumService) {}
|
constructor(private service: AlbumService) {}
|
||||||
|
|
||||||
@Get('count')
|
|
||||||
@Authenticated({ permission: Permission.ALBUM_STATISTICS })
|
|
||||||
getAlbumCount(@Auth() auth: AuthDto): Promise<AlbumCountResponseDto> {
|
|
||||||
return this.service.getCount(auth);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Get()
|
@Get()
|
||||||
@Authenticated({ permission: Permission.ALBUM_READ })
|
@Authenticated({ permission: Permission.ALBUM_READ })
|
||||||
getAllAlbums(@Auth() auth: AuthDto, @Query() query: GetAlbumsDto): Promise<AlbumResponseDto[]> {
|
getAllAlbums(@Auth() auth: AuthDto, @Query() query: GetAlbumsDto): Promise<AlbumResponseDto[]> {
|
||||||
@ -40,6 +34,12 @@ export class AlbumController {
|
|||||||
return this.service.create(auth, dto);
|
return this.service.create(auth, dto);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Get('statistics')
|
||||||
|
@Authenticated({ permission: Permission.ALBUM_STATISTICS })
|
||||||
|
getAlbumStatistics(@Auth() auth: AuthDto): Promise<AlbumStatisticsResponseDto> {
|
||||||
|
return this.service.getStatistics(auth);
|
||||||
|
}
|
||||||
|
|
||||||
@Authenticated({ permission: Permission.ALBUM_READ, sharedLink: true })
|
@Authenticated({ permission: Permission.ALBUM_READ, sharedLink: true })
|
||||||
@Get(':id')
|
@Get(':id')
|
||||||
getAlbumInfo(
|
getAlbumInfo(
|
||||||
|
@ -95,7 +95,7 @@ export class GetAlbumsDto {
|
|||||||
assetId?: string;
|
assetId?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class AlbumCountResponseDto {
|
export class AlbumStatisticsResponseDto {
|
||||||
@ApiProperty({ type: 'integer' })
|
@ApiProperty({ type: 'integer' })
|
||||||
owned!: number;
|
owned!: number;
|
||||||
|
|
||||||
|
@ -43,12 +43,12 @@ describe(AlbumService.name, () => {
|
|||||||
expect(sut).toBeDefined();
|
expect(sut).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getCount', () => {
|
describe('getStatistics', () => {
|
||||||
it('should get the album count', async () => {
|
it('should get the album count', async () => {
|
||||||
albumMock.getOwned.mockResolvedValue([]);
|
albumMock.getOwned.mockResolvedValue([]);
|
||||||
albumMock.getShared.mockResolvedValue([]);
|
albumMock.getShared.mockResolvedValue([]);
|
||||||
albumMock.getNotShared.mockResolvedValue([]);
|
albumMock.getNotShared.mockResolvedValue([]);
|
||||||
await expect(sut.getCount(authStub.admin)).resolves.toEqual({
|
await expect(sut.getStatistics(authStub.admin)).resolves.toEqual({
|
||||||
owned: 0,
|
owned: 0,
|
||||||
shared: 0,
|
shared: 0,
|
||||||
notShared: 0,
|
notShared: 0,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||||
import {
|
import {
|
||||||
AddUsersDto,
|
AddUsersDto,
|
||||||
AlbumCountResponseDto,
|
|
||||||
AlbumInfoDto,
|
AlbumInfoDto,
|
||||||
AlbumResponseDto,
|
AlbumResponseDto,
|
||||||
|
AlbumStatisticsResponseDto,
|
||||||
CreateAlbumDto,
|
CreateAlbumDto,
|
||||||
GetAlbumsDto,
|
GetAlbumsDto,
|
||||||
UpdateAlbumDto,
|
UpdateAlbumDto,
|
||||||
@ -37,7 +37,7 @@ export class AlbumService {
|
|||||||
@Inject(IAlbumUserRepository) private albumUserRepository: IAlbumUserRepository,
|
@Inject(IAlbumUserRepository) private albumUserRepository: IAlbumUserRepository,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async getCount(auth: AuthDto): Promise<AlbumCountResponseDto> {
|
async getStatistics(auth: AuthDto): Promise<AlbumStatisticsResponseDto> {
|
||||||
const [owned, shared, notShared] = await Promise.all([
|
const [owned, shared, notShared] = await Promise.all([
|
||||||
this.albumRepository.getOwned(auth.user.id),
|
this.albumRepository.getOwned(auth.user.id),
|
||||||
this.albumRepository.getShared(auth.user.id),
|
this.albumRepository.getShared(auth.user.id),
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { type AlbumCountResponseDto, getAlbumCount } from '@immich/sdk';
|
import { type AlbumStatisticsResponseDto, getAlbumStatistics } from '@immich/sdk';
|
||||||
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
export let albumCountType: keyof AlbumCountResponseDto;
|
export let albumType: keyof AlbumStatisticsResponseDto;
|
||||||
|
|
||||||
const handleAlbumCount = async () => {
|
const handleAlbumCount = async () => {
|
||||||
try {
|
try {
|
||||||
return await getAlbumCount();
|
return await getAlbumStatistics();
|
||||||
} catch {
|
} catch {
|
||||||
return { owned: 0, shared: 0, notShared: 0 };
|
return { owned: 0, shared: 0, notShared: 0 };
|
||||||
}
|
}
|
||||||
@ -18,6 +18,6 @@
|
|||||||
<LoadingSpinner />
|
<LoadingSpinner />
|
||||||
{:then data}
|
{:then data}
|
||||||
<div>
|
<div>
|
||||||
<p>{$t('albums_count', { values: { count: data[albumCountType] } })}</p>
|
<p>{$t('albums_count', { values: { count: data[albumType] } })}</p>
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
{/await}
|
||||||
|
@ -79,7 +79,7 @@
|
|||||||
bind:isSelected={isSharingSelected}
|
bind:isSelected={isSharingSelected}
|
||||||
>
|
>
|
||||||
<svelte:fragment slot="moreInformation">
|
<svelte:fragment slot="moreInformation">
|
||||||
<MoreInformationAlbums albumCountType="shared" />
|
<MoreInformationAlbums albumType="shared" />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</SideBarLink>
|
</SideBarLink>
|
||||||
{/if}
|
{/if}
|
||||||
@ -100,7 +100,7 @@
|
|||||||
</SideBarLink>
|
</SideBarLink>
|
||||||
<SideBarLink title={$t('albums')} routeId="/(user)/albums" icon={mdiImageAlbum} flippedLogo>
|
<SideBarLink title={$t('albums')} routeId="/(user)/albums" icon={mdiImageAlbum} flippedLogo>
|
||||||
<svelte:fragment slot="moreInformation">
|
<svelte:fragment slot="moreInformation">
|
||||||
<MoreInformationAlbums albumCountType="owned" />
|
<MoreInformationAlbums albumType="owned" />
|
||||||
</svelte:fragment>
|
</svelte:fragment>
|
||||||
</SideBarLink>
|
</SideBarLink>
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user