Skip to content

Commit

Permalink
Merge branch 'main' into fix/prev-esc
Browse files Browse the repository at this point in the history
  • Loading branch information
DonKoko authored Jan 17, 2025
2 parents c4a199c + c621012 commit 3a11c84
Show file tree
Hide file tree
Showing 17 changed files with 318 additions and 119 deletions.
15 changes: 14 additions & 1 deletion app/components/assets/actions-dropdown.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,20 @@ const ConditionalActionsDropdown = () => {
}}
disabled={assetIsCheckedOut || assetIsPartOfUnavailableKit}
>
<DeleteAsset asset={asset} />
<DeleteAsset
asset={asset}
trigger={
<Button
variant="link"
data-test-id="deleteAssetButton"
icon="trash"
className="justify-start rounded-sm px-4 py-3 text-sm font-semibold text-gray-700 outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-slate-100 hover:text-gray-700"
width="full"
>
Delete
</Button>
}
/>
</DropdownMenuItem>
<DropdownMenuItem className="border-t p-4 md:hidden md:p-0">
<Button
Expand Down
10 changes: 9 additions & 1 deletion app/components/assets/assets-index/advanced-asset-columns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,8 @@ import { resolveTeamMemberName } from "~/utils/user";
import { freezeColumnClassNames } from "./freeze-column-classes";
import { AssetImage } from "../asset-image";
import { AssetStatusBadge } from "../asset-status-badge";
import QrPreviewDialog from "../qr-preview-dialog";
import { QrPreviewDialog } from "../qr-preview-dialog";
import AssetQuickActions from "./asset-quick-actions";

export function AdvancedIndexColumn({
column,
Expand Down Expand Up @@ -240,6 +241,13 @@ export function AdvancedIndexColumn({

case "availableToBook":
return <TextColumn value={item.availableToBook ? "Yes" : "No"} />;

case "actions":
return (
<Td>
<AssetQuickActions asset={item} />
</Td>
);
}
}

Expand Down
15 changes: 14 additions & 1 deletion app/components/assets/assets-index/advanced-filters/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { CustomField } from "@prisma/client";
import type { SerializeFrom } from "@remix-run/node";
import { useSearchParams } from "~/hooks/search-params";
import type { Column } from "~/modules/asset-index-settings/helpers";
import type {
Column,
ColumnLabelKey,
} from "~/modules/asset-index-settings/helpers";
import type { Filter, FilterFieldType, FilterOperator } from "./schema";
import type { Sort } from "../advanced-asset-index-filters-and-sorting";

Expand Down Expand Up @@ -165,6 +168,8 @@ export function getDefaultValueForFieldType(
}
}

export const COLUMNS_WITHOUT_FILTER: ColumnLabelKey[] = ["actions"];

/**
* Determines what columns are available based on already used columns and operation type
* @param columns - All available columns
Expand Down Expand Up @@ -194,6 +199,14 @@ export function getAvailableColumns(
// Common exclusions for both operations
if (!column.visible) return false;

/**
* Some columns like `actions` does not support filtering,
* so we have to skip them to be availableColumns.
*/
if (COLUMNS_WITHOUT_FILTER.includes(column.name)) {
return false;
}

if (operation === "sort") {
// Columns that can't be sorted
const unsortableColumns = ["tags"];
Expand Down
39 changes: 22 additions & 17 deletions app/components/assets/assets-index/asset-index-pagination.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -160,23 +160,28 @@ export const SwitchToAdvancedMode = ({
</span>
</div>
<AlertDialogTitle>Advanced Mode (Beta)</AlertDialogTitle>
<AlertDialogDescription className="space-y-2 text-center text-gray-500 md:text-left">
<p>
You are about to switch to Advanced Mode. This feature is
currently in beta and includes:
</p>
<ul className="list-inside list-disc text-left">
<li>Advanced filtering capabilities</li>
<li>Custom column management</li>
<li>Enhanced sorting options</li>
<li>Custom field support</li>
</ul>
<p>
While we've thoroughly tested this feature, you may encounter
occasional issues. Your feedback helps us improve! If you face any
issues, please report them to our support team so we can resolve
them asap.
</p>
<AlertDialogDescription
className="space-y-2 text-center text-gray-500 md:text-left"
asChild
>
<div>
<p>
You are about to switch to Advanced Mode. This feature is
currently in beta and includes:
</p>
<ul className="list-inside list-disc text-left">
<li>Advanced filtering capabilities</li>
<li>Custom column management</li>
<li>Enhanced sorting options</li>
<li>Custom field support</li>
</ul>
<p>
While we've thoroughly tested this feature, you may encounter
occasional issues. Your feedback helps us improve! If you face
any issues, please report them to our support team so we can
resolve them asap.
</p>
</div>
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
Expand Down
100 changes: 100 additions & 0 deletions app/components/assets/assets-index/asset-quick-actions.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import { CopyIcon, PencilIcon, QrCodeIcon, Trash2Icon } from "lucide-react";
import { Button } from "~/components/shared/button";
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "~/components/shared/tooltip";
import type { AssetsFromViewItem } from "~/modules/asset/types";
import { tw } from "~/utils/tw";
import { DeleteAsset } from "../delete-asset";
import { QrPreviewDialog } from "../qr-preview-dialog";

type AssetQuickActionsProps = {
className?: string;
style?: React.CSSProperties;
asset: Pick<AssetsFromViewItem, "id" | "title" | "mainImage"> & {
qrId: string;
};
};

export default function AssetQuickActions({
className,
style,
asset,
}: AssetQuickActionsProps) {
return (
<div className={tw("flex items-center gap-2", className)} style={style}>
<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
className={"p-2"}
to={`/assets/${asset.id}/edit`}
>
<PencilIcon className="size-4" />
</Button>
</TooltipTrigger>

<TooltipContent align="center" side="top">
Edit asset information
</TooltipContent>
</Tooltip>

<Tooltip>
<QrPreviewDialog
asset={{
id: asset.id,
title: asset.title,
qrId: asset.qrId,
}}
trigger={
<TooltipTrigger asChild>
<Button size="sm" variant="secondary" className={"p-2"}>
<QrCodeIcon className="size-4" />
</Button>
</TooltipTrigger>
}
/>

<TooltipContent align="center" side="top">
Show asset label
</TooltipContent>
</Tooltip>

<Tooltip>
<TooltipTrigger asChild>
<Button
size="sm"
variant="secondary"
className={"p-2"}
to={`/assets/${asset.id}/overview/duplicate`}
>
<CopyIcon className="size-4" />
</Button>
</TooltipTrigger>

<TooltipContent align="center" side="top">
Duplicate asset
</TooltipContent>
</Tooltip>
<Tooltip>
<DeleteAsset
asset={asset}
trigger={
<TooltipTrigger asChild>
<Button size="sm" variant="secondary" className={"p-2"}>
<Trash2Icon className="size-4" />
</Button>
</TooltipTrigger>
}
/>

<TooltipContent align="center" side="top">
Delete asset
</TooltipContent>
</Tooltip>
</div>
);
}
119 changes: 64 additions & 55 deletions app/components/assets/delete-asset.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import { cloneElement, forwardRef } from "react";
import type { Asset } from "@prisma/client";
import { useNavigation } from "@remix-run/react";
import { Button } from "~/components/shared/button";

import {
Expand All @@ -11,68 +13,75 @@ import {
AlertDialogTitle,
AlertDialogTrigger,
} from "~/components/shared/modal";
import { isFormProcessing } from "~/utils/form";
import { Form } from "../custom-form";
import { TrashIcon } from "../icons/library";

export const DeleteAsset = ({
asset,
}: {
type DeleteAssetProps = {
asset: {
id: Asset["id"];
title: Asset["title"];
mainImage: Asset["mainImage"];
};
}) => (
<AlertDialog>
<AlertDialogTrigger asChild>
<Button
variant="link"
data-test-id="deleteAssetButton"
icon="trash"
className="justify-start rounded-sm px-4 py-3 text-sm font-semibold text-gray-700 outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 hover:bg-slate-100 hover:text-gray-700"
width="full"
>
Delete
</Button>
</AlertDialogTrigger>
trigger: React.ReactElement;
};

<AlertDialogContent>
<AlertDialogHeader>
<div className="mx-auto md:m-0">
<span className="flex size-12 items-center justify-center rounded-full bg-error-50 p-2 text-error-600">
<TrashIcon />
</span>
</div>
<AlertDialogTitle>Delete {asset.title}</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this asset? This action cannot be
undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<div className="flex justify-center gap-2">
<AlertDialogCancel asChild>
<Button variant="secondary">Cancel</Button>
</AlertDialogCancel>
export const DeleteAsset = forwardRef<HTMLButtonElement, DeleteAssetProps>(
function ({ asset, trigger }, ref) {
const navigation = useNavigation();
const disabled = isFormProcessing(navigation.state);

<Form method="delete">
{asset.mainImage && (
<input
type="hidden"
value={asset.mainImage}
name="mainImageUrl"
/>
)}
<input type="hidden" value="delete" name="intent" />
<Button
className="border-error-600 bg-error-600 hover:border-error-800 hover:bg-error-800"
type="submit"
data-test-id="confirmdeleteAssetButton"
>
Delete
</Button>
</Form>
</div>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
return (
<AlertDialog>
<AlertDialogTrigger ref={ref} asChild>
{cloneElement(trigger)}
</AlertDialogTrigger>

<AlertDialogContent>
<AlertDialogHeader>
<div className="mx-auto md:m-0">
<span className="flex size-12 items-center justify-center rounded-full bg-error-50 p-2 text-error-600">
<TrashIcon />
</span>
</div>
<AlertDialogTitle>Delete {asset.title}</AlertDialogTitle>
<AlertDialogDescription>
Are you sure you want to delete this asset? This action cannot be
undone.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<div className="flex justify-center gap-2">
<AlertDialogCancel asChild>
<Button variant="secondary" disabled={disabled}>
Cancel
</Button>
</AlertDialogCancel>

<Form method="delete" action={`/assets/${asset.id}`}>
{asset.mainImage && (
<input
type="hidden"
value={asset.mainImage}
name="mainImageUrl"
/>
)}
<input type="hidden" value="delete" name="intent" />
<Button
className="border-error-600 bg-error-600 hover:border-error-800 hover:!bg-error-800"
type="submit"
data-test-id="confirmdeleteAssetButton"
disabled={disabled}
>
Delete
</Button>
</Form>
</div>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
);
}
);

DeleteAsset.displayName = "DeleteAsset";
Loading

0 comments on commit 3a11c84

Please sign in to comment.