mirror of
https://github.com/samsonjs/immich.git
synced 2026-04-27 15:07:45 +00:00
feat: random memories sort order (#20025)
This commit is contained in:
parent
6c6b00067b
commit
d92df63f84
11 changed files with 85 additions and 6 deletions
BIN
mobile/openapi/README.md
generated
BIN
mobile/openapi/README.md
generated
Binary file not shown.
BIN
mobile/openapi/lib/api.dart
generated
BIN
mobile/openapi/lib/api.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/api/memories_api.dart
generated
BIN
mobile/openapi/lib/api/memories_api.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/api_client.dart
generated
BIN
mobile/openapi/lib/api_client.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/api_helper.dart
generated
BIN
mobile/openapi/lib/api_helper.dart
generated
Binary file not shown.
BIN
mobile/openapi/lib/model/memory_search_order.dart
generated
Normal file
BIN
mobile/openapi/lib/model/memory_search_order.dart
generated
Normal file
Binary file not shown.
|
|
@ -4268,6 +4268,24 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "order",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/MemorySearchOrder"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"description": "Number of memories to return",
|
||||||
|
"schema": {
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "type",
|
"name": "type",
|
||||||
"required": false,
|
"required": false,
|
||||||
|
|
@ -4381,6 +4399,24 @@
|
||||||
"type": "boolean"
|
"type": "boolean"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "order",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"$ref": "#/components/schemas/MemorySearchOrder"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "size",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"description": "Number of memories to return",
|
||||||
|
"schema": {
|
||||||
|
"minimum": 1,
|
||||||
|
"type": "integer"
|
||||||
|
}
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "type",
|
"name": "type",
|
||||||
"required": false,
|
"required": false,
|
||||||
|
|
@ -12780,6 +12816,14 @@
|
||||||
],
|
],
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
|
"MemorySearchOrder": {
|
||||||
|
"enum": [
|
||||||
|
"asc",
|
||||||
|
"desc",
|
||||||
|
"random"
|
||||||
|
],
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
"MemoryStatisticsResponseDto": {
|
"MemoryStatisticsResponseDto": {
|
||||||
"properties": {
|
"properties": {
|
||||||
"total": {
|
"total": {
|
||||||
|
|
|
||||||
|
|
@ -2956,10 +2956,12 @@ export function reverseGeocode({ lat, lon }: {
|
||||||
/**
|
/**
|
||||||
* This endpoint requires the `memory.read` permission.
|
* This endpoint requires the `memory.read` permission.
|
||||||
*/
|
*/
|
||||||
export function searchMemories({ $for, isSaved, isTrashed, $type }: {
|
export function searchMemories({ $for, isSaved, isTrashed, order, size, $type }: {
|
||||||
$for?: string;
|
$for?: string;
|
||||||
isSaved?: boolean;
|
isSaved?: boolean;
|
||||||
isTrashed?: boolean;
|
isTrashed?: boolean;
|
||||||
|
order?: MemorySearchOrder;
|
||||||
|
size?: number;
|
||||||
$type?: MemoryType;
|
$type?: MemoryType;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
|
@ -2969,6 +2971,8 @@ export function searchMemories({ $for, isSaved, isTrashed, $type }: {
|
||||||
"for": $for,
|
"for": $for,
|
||||||
isSaved,
|
isSaved,
|
||||||
isTrashed,
|
isTrashed,
|
||||||
|
order,
|
||||||
|
size,
|
||||||
"type": $type
|
"type": $type
|
||||||
}))}`, {
|
}))}`, {
|
||||||
...opts
|
...opts
|
||||||
|
|
@ -2992,10 +2996,12 @@ export function createMemory({ memoryCreateDto }: {
|
||||||
/**
|
/**
|
||||||
* This endpoint requires the `memory.statistics` permission.
|
* This endpoint requires the `memory.statistics` permission.
|
||||||
*/
|
*/
|
||||||
export function memoriesStatistics({ $for, isSaved, isTrashed, $type }: {
|
export function memoriesStatistics({ $for, isSaved, isTrashed, order, size, $type }: {
|
||||||
$for?: string;
|
$for?: string;
|
||||||
isSaved?: boolean;
|
isSaved?: boolean;
|
||||||
isTrashed?: boolean;
|
isTrashed?: boolean;
|
||||||
|
order?: MemorySearchOrder;
|
||||||
|
size?: number;
|
||||||
$type?: MemoryType;
|
$type?: MemoryType;
|
||||||
}, opts?: Oazapfts.RequestOpts) {
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
return oazapfts.ok(oazapfts.fetchJson<{
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
|
@ -3005,6 +3011,8 @@ export function memoriesStatistics({ $for, isSaved, isTrashed, $type }: {
|
||||||
"for": $for,
|
"for": $for,
|
||||||
isSaved,
|
isSaved,
|
||||||
isTrashed,
|
isTrashed,
|
||||||
|
order,
|
||||||
|
size,
|
||||||
"type": $type
|
"type": $type
|
||||||
}))}`, {
|
}))}`, {
|
||||||
...opts
|
...opts
|
||||||
|
|
@ -4991,6 +4999,11 @@ export enum JobCommand {
|
||||||
Empty = "empty",
|
Empty = "empty",
|
||||||
ClearFailed = "clear-failed"
|
ClearFailed = "clear-failed"
|
||||||
}
|
}
|
||||||
|
export enum MemorySearchOrder {
|
||||||
|
Asc = "asc",
|
||||||
|
Desc = "desc",
|
||||||
|
Random = "random"
|
||||||
|
}
|
||||||
export enum MemoryType {
|
export enum MemoryType {
|
||||||
OnThisDay = "on_this_day"
|
OnThisDay = "on_this_day"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ import { IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator';
|
||||||
import { Memory } from 'src/database';
|
import { Memory } from 'src/database';
|
||||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import { MemoryType } from 'src/enum';
|
import { AssetOrderWithRandom, MemoryType } from 'src/enum';
|
||||||
import { ValidateBoolean, ValidateDate, ValidateEnum, ValidateUUID } from 'src/validation';
|
import { ValidateBoolean, ValidateDate, ValidateEnum, ValidateUUID } from 'src/validation';
|
||||||
|
|
||||||
class MemoryBaseDto {
|
class MemoryBaseDto {
|
||||||
|
|
@ -27,6 +27,15 @@ export class MemorySearchDto {
|
||||||
|
|
||||||
@ValidateBoolean({ optional: true })
|
@ValidateBoolean({ optional: true })
|
||||||
isSaved?: boolean;
|
isSaved?: boolean;
|
||||||
|
|
||||||
|
@IsInt()
|
||||||
|
@IsPositive()
|
||||||
|
@Type(() => Number)
|
||||||
|
@ApiProperty({ type: 'integer', description: 'Number of memories to return' })
|
||||||
|
size?: number;
|
||||||
|
|
||||||
|
@ValidateEnum({ enum: AssetOrderWithRandom, name: 'MemorySearchOrder', optional: true })
|
||||||
|
order?: AssetOrderWithRandom;
|
||||||
}
|
}
|
||||||
|
|
||||||
class OnThisDayDto {
|
class OnThisDayDto {
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,14 @@ export enum MemoryType {
|
||||||
OnThisDay = 'on_this_day',
|
OnThisDay = 'on_this_day',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum AssetOrderWithRandom {
|
||||||
|
// Include existing values
|
||||||
|
Asc = AssetOrder.Asc,
|
||||||
|
Desc = AssetOrder.Desc,
|
||||||
|
/** Randomly Ordered */
|
||||||
|
Random = 'random',
|
||||||
|
}
|
||||||
|
|
||||||
export enum Permission {
|
export enum Permission {
|
||||||
All = 'all',
|
All = 'all',
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { Insertable, Kysely, sql, Updateable } from 'kysely';
|
import { Insertable, Kysely, OrderByDirection, sql, Updateable } from 'kysely';
|
||||||
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
import { jsonArrayFrom } from 'kysely/helpers/postgres';
|
||||||
import { DateTime } from 'luxon';
|
import { DateTime } from 'luxon';
|
||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
import { Chunked, ChunkedSet, DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { MemorySearchDto } from 'src/dtos/memory.dto';
|
import { MemorySearchDto } from 'src/dtos/memory.dto';
|
||||||
import { AssetVisibility } from 'src/enum';
|
import { AssetOrderWithRandom, AssetVisibility } from 'src/enum';
|
||||||
import { DB } from 'src/schema';
|
import { DB } from 'src/schema';
|
||||||
import { MemoryTable } from 'src/schema/tables/memory.table';
|
import { MemoryTable } from 'src/schema/tables/memory.table';
|
||||||
import { IBulkAsset } from 'src/types';
|
import { IBulkAsset } from 'src/types';
|
||||||
|
|
@ -72,7 +72,12 @@ export class MemoryRepository implements IBulkAsset {
|
||||||
).as('assets'),
|
).as('assets'),
|
||||||
)
|
)
|
||||||
.selectAll('memory')
|
.selectAll('memory')
|
||||||
.orderBy('memoryAt', 'desc')
|
.$call((qb) =>
|
||||||
|
dto.order === AssetOrderWithRandom.Random
|
||||||
|
? qb.orderBy(sql`RANDOM()`)
|
||||||
|
: qb.orderBy('memoryAt', (dto.order?.toLowerCase() || 'desc') as OrderByDirection),
|
||||||
|
)
|
||||||
|
.$if(dto.size !== undefined, (qb) => qb.limit(dto.size!))
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue