mirror of
https://github.com/KevinMidboe/immich.git
synced 2026-01-19 23:56:57 +00:00
feat (server, web): Implement Archive (#2225)
* feat (server, web): add archive * chore: generate api * feat (web): add empty placeholder for archive page * chore: remove title on favorites page Duplicates sidebar selection. Two pages (Archive and Favorites) are consistent now * refactor (web): create EmptyPlaceholder component for empty pages * fixed menu close button not close: * fix (web): remove not necessary store call * test (web): simplify asset tests code * test (web): simplify asset tests code * chore (server): remove isArchived while uploading * chore (server): remove isArchived from typesense schema * chore: generate api * fix (web): delete asset from archive page * chore: change archive asset count endpoint old endpoint: /asset/archived-count-by-user-id new endpoint: /asset/stat/archive * chore: generate api --------- Co-authored-by: Alex Tran <alex.tran1502@gmail.com>
This commit is contained in:
@@ -19,6 +19,7 @@ export class AssetResponseDto {
|
||||
fileModifiedAt!: string;
|
||||
updatedAt!: string;
|
||||
isFavorite!: boolean;
|
||||
isArchived!: boolean;
|
||||
mimeType!: string | null;
|
||||
duration!: string;
|
||||
webpPath!: string | null;
|
||||
@@ -43,6 +44,7 @@ export function mapAsset(entity: AssetEntity): AssetResponseDto {
|
||||
fileModifiedAt: entity.fileModifiedAt,
|
||||
updatedAt: entity.updatedAt,
|
||||
isFavorite: entity.isFavorite,
|
||||
isArchived: entity.isArchived,
|
||||
mimeType: entity.mimeType,
|
||||
webpPath: entity.webpPath,
|
||||
encodedVideoPath: entity.encodedVideoPath,
|
||||
@@ -68,6 +70,7 @@ export function mapAssetWithoutExif(entity: AssetEntity): AssetResponseDto {
|
||||
fileModifiedAt: entity.fileModifiedAt,
|
||||
updatedAt: entity.updatedAt,
|
||||
isFavorite: entity.isFavorite,
|
||||
isArchived: entity.isArchived,
|
||||
mimeType: entity.mimeType,
|
||||
webpPath: entity.webpPath,
|
||||
encodedVideoPath: entity.encodedVideoPath,
|
||||
|
||||
@@ -28,6 +28,11 @@ export class SearchDto {
|
||||
@Transform(toBoolean)
|
||||
isFavorite?: boolean;
|
||||
|
||||
@IsBoolean()
|
||||
@IsOptional()
|
||||
@Transform(toBoolean)
|
||||
isArchived?: boolean;
|
||||
|
||||
@IsString()
|
||||
@IsNotEmpty()
|
||||
@IsOptional()
|
||||
|
||||
@@ -15,6 +15,7 @@ export interface SearchFilter {
|
||||
userId: string;
|
||||
type?: AssetType;
|
||||
isFavorite?: boolean;
|
||||
isArchived?: boolean;
|
||||
city?: string;
|
||||
state?: string;
|
||||
country?: string;
|
||||
|
||||
@@ -134,6 +134,7 @@ export const assetEntityStub = {
|
||||
updatedAt: '2023-02-23T05:06:29.716Z',
|
||||
mimeType: null,
|
||||
isFavorite: true,
|
||||
isArchived: false,
|
||||
duration: null,
|
||||
isVisible: true,
|
||||
livePhotoVideo: null,
|
||||
@@ -158,6 +159,7 @@ export const assetEntityStub = {
|
||||
updatedAt: '2023-02-23T05:06:29.716Z',
|
||||
mimeType: null,
|
||||
isFavorite: true,
|
||||
isArchived: false,
|
||||
duration: null,
|
||||
isVisible: true,
|
||||
livePhotoVideo: null,
|
||||
@@ -184,6 +186,7 @@ export const assetEntityStub = {
|
||||
updatedAt: '2023-02-23T05:06:29.716Z',
|
||||
mimeType: null,
|
||||
isFavorite: true,
|
||||
isArchived: false,
|
||||
duration: null,
|
||||
isVisible: true,
|
||||
livePhotoVideo: null,
|
||||
@@ -355,6 +358,7 @@ const assetResponse: AssetResponseDto = {
|
||||
fileCreatedAt: today.toISOString(),
|
||||
updatedAt: today.toISOString(),
|
||||
isFavorite: false,
|
||||
isArchived: false,
|
||||
mimeType: 'image/jpeg',
|
||||
smartInfo: {
|
||||
tags: [],
|
||||
@@ -591,6 +595,7 @@ export const sharedLinkStub = {
|
||||
createdAt: today.toISOString(),
|
||||
updatedAt: today.toISOString(),
|
||||
isFavorite: false,
|
||||
isArchived: false,
|
||||
mimeType: 'image/jpeg',
|
||||
smartInfo: {
|
||||
assetId: 'id_1',
|
||||
|
||||
@@ -67,6 +67,9 @@ export class AssetEntity {
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isFavorite!: boolean;
|
||||
|
||||
@Column({ type: 'boolean', default: false })
|
||||
isArchived!: boolean;
|
||||
|
||||
@Column({ type: 'varchar', nullable: true })
|
||||
mimeType!: string | null;
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import { MigrationInterface, QueryRunner } from "typeorm";
|
||||
|
||||
export class AddIsArchivedColumn1680632845740 implements MigrationInterface {
|
||||
name = 'AddIsArchivedColumn1680632845740'
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "assets" ADD "isArchived" boolean NOT NULL DEFAULT false`);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(`ALTER TABLE "assets" DROP COLUMN "isArchived"`);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
import { CollectionCreateSchema } from 'typesense/lib/Typesense/Collections';
|
||||
|
||||
export const assetSchemaVersion = 4;
|
||||
export const assetSchemaVersion = 5;
|
||||
export const assetSchema: CollectionCreateSchema = {
|
||||
name: `assets-v${assetSchemaVersion}`,
|
||||
fields: [
|
||||
@@ -14,8 +14,6 @@ export const assetSchema: CollectionCreateSchema = {
|
||||
{ name: 'fileModifiedAt', type: 'string', facet: false, sort: true },
|
||||
{ name: 'isFavorite', type: 'bool', facet: true },
|
||||
{ name: 'originalFileName', type: 'string', facet: false, optional: true },
|
||||
// { name: 'checksum', type: 'string', facet: true },
|
||||
// { name: 'tags', type: 'string[]', facet: true, optional: true },
|
||||
|
||||
// exif
|
||||
{ name: 'exifInfo.city', type: 'string', facet: true, optional: true },
|
||||
|
||||
Reference in New Issue
Block a user