feat: option to delete assets from missing locations page

Signed-off-by: Varun Raj <varun@skcript.com>
This commit is contained in:
Varun Raj committed 2025-01-18 14:21:12 +05:30
1 parent 29f80b8cd9
commit 098701b828
7 files changed
+56 -10

No files matched your search

@@ -36,7 +36,7 @@ export default function TagMissingLocationDialog({
return (
<Dialog open={open} onOpenChange={setOpen}>
<DialogTrigger asChild>
<Button size={"sm"}>Tag Missing Location</Button>
<Button size={"sm"}>Tag Location</Button>
</DialogTrigger>
<DialogContent className="!w-[600px] !max-w-[600px]">
<DialogHeader>
+1 -1
View File
@@ -8,7 +8,7 @@ interface FloatingBarProps {
export default function FloatingBar({ children }: FloatingBarProps) {
return (
<div className='absolute bottom-10 left-0 right-0'>
<div className='max-w-lg mx-auto py-2 px-2 rounded-lg flex justify-between items-center bg-white dark:bg-zinc-900 border-t border-zinc-200 dark:border-zinc-800'>
<div className='max-w-xl mx-auto py-2 px-2 rounded-lg flex justify-between items-center bg-white dark:bg-zinc-900 border-t border-zinc-200 dark:border-zinc-800 border'>
{children}
</div>
</div>
-1
View File
@@ -34,7 +34,6 @@ export const LIST_MISSING_LOCATION_DATES_PATH = BASE_API_ENDPOINT + "/assets/mis
export const LIST_MISSING_LOCATION_ALBUMS_PATH = BASE_API_ENDPOINT + "/assets/missing-location-albums";
export const LIST_MISSING_LOCATION_ASSETS_PATH = BASE_API_ENDPOINT + "/assets/missing-location-assets";
export const UPDATE_ASSETS_PATH = BASE_PROXY_ENDPOINT + "/assets";
export const ASSET_THUMBNAIL_PATH = (id: string) => BASE_PROXY_ENDPOINT + "/asset/thumbnail/" + id;
export const ASSET_PREVIEW_PATH = (id: string) => BASE_PROXY_ENDPOINT + "/asset/thumbnail/" + id + "?size=preview";
export const ASSET_VIDEO_PATH = (id: string) => BASE_PROXY_ENDPOINT + "/asset/video/" + id;
+5 -3
View File
@@ -1,8 +1,6 @@
import {
ADD_ASSETS_ALBUMS_PATH,
ASSET_GEO_HEATMAP_PATH,
FIND_ASSETS,
LIST_ALBUMS_PATH,
LIST_MISSING_LOCATION_ALBUMS_PATH,
LIST_MISSING_LOCATION_ASSETS_PATH,
LIST_MISSING_LOCATION_DATES_PATH,
@@ -65,4 +63,8 @@ export const findAssets = async (query: string) => {
export const getAssetGeoHeatmap = async () => {
return API.get(ASSET_GEO_HEATMAP_PATH);
}
}
export const deleteAssets = async (ids: string[]) => {
return API.delete(UPDATE_ASSETS_PATH, { ids });
}
@@ -1,6 +1,7 @@
// Next.js API route support: https://nextjs.org/docs/api-routes/introduction
import { db } from "@/config/db";
import { getCurrentUser } from "@/handlers/serverUtils/user.utils";
import { isFlipped } from "@/helpers/asset.helper";
import { parseDate } from "@/helpers/date.helper";
import { assets, exif } from "@/schema";
import { albumsAssetsAssets } from "@/schema/albumAssetsAssets.schema";
@@ -28,6 +29,7 @@ const getRowsByDates = async (startDateDate: Date, endDateDate: Date, currentUse
exifImageHeight: exif.exifImageHeight,
ownerId: assets.ownerId,
dateTimeOriginal: exif.dateTimeOriginal,
orientation: exif.orientation,
})
.from(assets)
.leftJoin(exif, eq(exif.assetId, assets.id))
@@ -37,6 +39,9 @@ const getRowsByDates = async (startDateDate: Date, endDateDate: Date, currentUse
gte(exif.dateTimeOriginal, startDateDate),
lte(exif.dateTimeOriginal, endDateDate),
eq(assets.ownerId, currentUser.id),
eq(assets.isVisible, true),
eq(assets.isArchived, false),
isNull(assets.deletedAt),
));
}
@@ -57,6 +62,7 @@ const getRowsByAlbums = async (currentUser: IUser, albumId: string) => {
exifImageHeight: exif.exifImageHeight,
ownerId: assets.ownerId,
dateTimeOriginal: exif.dateTimeOriginal,
orientation: exif.orientation,
})
.from(assets)
.leftJoin(exif, eq(exif.assetId, assets.id))
@@ -66,7 +72,10 @@ const getRowsByAlbums = async (currentUser: IUser, albumId: string) => {
isNull(exif.latitude),
isNotNull(assets.createdAt),
eq(assets.ownerId, currentUser.id),
eq(albums.id, albumId)
eq(albums.id, albumId),
eq(assets.isVisible, true),
eq(assets.isArchived, false),
isNull(assets.deletedAt),
));
}
@@ -100,7 +109,13 @@ export default async function handler(
try {
const rows = await getRowsByDates(startDateDate, endDateDate, currentUser);
return res.status(200).json(rows);
const cleanedRows = rows.map((row) => ({
...row,
exifImageWidth: isFlipped(row.orientation) ? row.exifImageHeight : row.exifImageWidth,
exifImageHeight: isFlipped(row.orientation) ? row.exifImageWidth : row.exifImageHeight,
orientation: row.orientation,
}));
return res.status(200).json(cleanedRows);
} catch (error: any) {
return res.status(500).json({
error: error?.message,
@@ -113,6 +128,12 @@ export default async function handler(
});
}
const rows = await getRowsByAlbums(currentUser, albumId);
return res.status(200).json(rows);
const cleanedRows = rows.map((row) => ({
...row,
exifImageWidth: isFlipped(row.orientation) ? row.exifImageHeight : row.exifImageWidth,
exifImageHeight: isFlipped(row.orientation) ? row.exifImageWidth : row.exifImageHeight,
orientation: row.orientation,
}));
return res.status(200).json(cleanedRows);
}
}
@@ -34,6 +34,8 @@ export default async function handler(
isNotNull(exif.dateTimeOriginal),
eq(assets.ownerId, currentUser.id),
eq(assets.isVisible, true),
eq(assets.isArchived, false),
isNull(assets.deletedAt),
))
.groupBy(sql`DATE(${exif.dateTimeOriginal})`)
.orderBy(desc(count(assets.id))) as IMissingLocationDatesResponse[];
+23 -1
View File
@@ -10,13 +10,14 @@ import { useToast } from "@/components/ui/use-toast";
import MissingLocationContext, {
IMissingLocationConfig,
} from "@/contexts/MissingLocationContext";
import { updateAssets } from "@/handlers/api/asset.handler";
import { deleteAssets, updateAssets } from "@/handlers/api/asset.handler";
import { IPlace } from "@/types/common";
import { useRouter } from "next/router";
import React, { useMemo } from "react";
import FloatingBar from "@/components/shared/FloatingBar";
import { Select, SelectValue, SelectTrigger, SelectContent, SelectItem } from "@/components/ui/select";
import { AlertDialog } from "@/components/ui/alert-dialog";
export default function MissingLocations() {
const { query, push } = useRouter();
@@ -42,6 +43,16 @@ export default function MissingLocations() {
})
};
const handleDelete = () => {
return deleteAssets(config.selectedIds).then(() => {
setConfig({
...config,
selectedIds: [],
assets: config.assets.filter((a) => !config.selectedIds.includes(a.id)),
});
})
}
return (
<PageLayout className="!p-0 !mb-0 relative">
<Header
@@ -115,7 +126,18 @@ export default function MissingLocations() {
Select all
</Button>
)}
{/* Seperator */}
<TagMissingLocationDialog onSubmit={handleSubmit} />
<div className="h-[10px] w-[1px] bg-zinc-500 dark:bg-zinc-800"></div>
<AlertDialog
title="Delete the selected assets?"
description="This action will delete the selected assets and cannot be undone."
onConfirm={handleDelete}>
<Button variant={"destructive"} size={"sm"} >
Delete
</Button>
</AlertDialog>
</div>
</div>
</FloatingBar>