feat: option to delete assets from missing locations page
Signed-off-by: Varun Raj <varun@skcript.com>
This commit is contained in:
1 parent
29f80b8cd9
commit
098701b828
7 files changed
+56
-10
No files matched your search
+1
-1
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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[];
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in new issue
Block a user