Fix cubic review

Signed-off-by: Émile Ré <nemile.re@gmail.com>
This commit is contained in:
Émile Ré
2025-12-01 15:54:33 +04:00
parent 8f68f7116a
commit d0cefdee2f
6 changed files with 43 additions and 38 deletions

View File

@@ -54,6 +54,7 @@ function VendorBadge({
<button <button
onClick={() => onRemove(vendor)} onClick={() => onRemove(vendor)}
className="size-4 hover:text-txt-primary cursor-pointer" className="size-4 hover:text-txt-primary cursor-pointer"
type="button"
> >
<IconCrossLargeX size={14} /> <IconCrossLargeX size={14} />
</button> </button>

View File

@@ -121,17 +121,13 @@ export const deleteAssetMutation = graphql`
`; `;
export const useDeleteAsset = ( export const useDeleteAsset = (
asset?: { id?: string; name?: string }, asset: { id?: string; name?: string },
connectionId?: string, connectionId: string,
) => { ) => {
const [mutate] = useMutation(deleteAssetMutation); const [mutate] = useMutation(deleteAssetMutation);
const confirm = useConfirm(); const confirm = useConfirm();
const { __ } = useTranslate(); const { __ } = useTranslate();
if (!asset) {
return () => {};
}
return () => { return () => {
if (!asset.id || !asset.name) { if (!asset.id || !asset.name) {
return alert(__("Failed to delete asset: missing id or name")); return alert(__("Failed to delete asset: missing id or name"));
@@ -141,7 +137,7 @@ export const useDeleteAsset = (
promisifyMutation(mutate)({ promisifyMutation(mutate)({
variables: { variables: {
input: { input: {
assetId: asset.id!, assetId: asset.id,
}, },
connections: [connectionId], connections: [connectionId],
}, },

View File

@@ -1,13 +1,5 @@
import { import { getAssetTypeVariant, validateSnapshotConsistency } from "@probo/helpers";
ConnectionHandler, import { useTranslate } from "@probo/i18n";
usePreloadedQuery,
type PreloadedQuery,
} from "react-relay";
import {
assetNodeQuery,
useDeleteAsset,
useUpdateAsset,
} from "../../../hooks/graph/AssetGraph";
import { import {
ActionDropdown, ActionDropdown,
Badge, Badge,
@@ -18,16 +10,25 @@ import {
IconTrashCan, IconTrashCan,
Option, Option,
} from "@probo/ui"; } from "@probo/ui";
import { useTranslate } from "@probo/i18n"; import {
import { useOrganizationId } from "/hooks/useOrganizationId"; ConnectionHandler,
usePreloadedQuery,
type PreloadedQuery,
} from "react-relay";
import { useParams } from "react-router"; import { useParams } from "react-router";
import z from "zod";
import {
assetNodeQuery,
useDeleteAsset,
useUpdateAsset,
} from "../../../hooks/graph/AssetGraph";
import { SnapshotBanner } from "/components/SnapshotBanner";
import { ControlledField } from "/components/form/ControlledField"; import { ControlledField } from "/components/form/ControlledField";
import { PeopleSelectField } from "/components/form/PeopleSelectField"; import { PeopleSelectField } from "/components/form/PeopleSelectField";
import { VendorsMultiSelectField } from "/components/form/VendorsMultiSelectField"; import { VendorsMultiSelectField } from "/components/form/VendorsMultiSelectField";
import type { AssetGraphNodeQuery } from "/hooks/graph/__generated__/AssetGraphNodeQuery.graphql";
import { useFormWithSchema } from "/hooks/useFormWithSchema"; import { useFormWithSchema } from "/hooks/useFormWithSchema";
import z from "zod"; import { useOrganizationId } from "/hooks/useOrganizationId";
import { getAssetTypeVariant, validateSnapshotConsistency } from "@probo/helpers";
import { SnapshotBanner } from "/components/SnapshotBanner";
import { Authorized } from "/permissions"; import { Authorized } from "/permissions";
const updateAssetSchema = z.object({ const updateAssetSchema = z.object({
@@ -40,18 +41,18 @@ const updateAssetSchema = z.object({
}); });
type Props = { type Props = {
queryRef: PreloadedQuery<any>; queryRef: PreloadedQuery<AssetGraphNodeQuery>;
}; };
export default function AssetDetailsPage(props: Props) { export default function AssetDetailsPage(props: Props) {
const asset = usePreloadedQuery(assetNodeQuery, props.queryRef); const asset = usePreloadedQuery<AssetGraphNodeQuery>(assetNodeQuery, props.queryRef);
const assetEntry = asset.node; const assetEntry = asset.node;
const { __ } = useTranslate(); const { __ } = useTranslate();
const organizationId = useOrganizationId(); const organizationId = useOrganizationId();
const { snapshotId } = useParams<{ snapshotId?: string }>(); const { snapshotId } = useParams<{ snapshotId?: string }>();
const isSnapshotMode = Boolean(snapshotId); const isSnapshotMode = Boolean(snapshotId);
if (!assetEntry) { if (!assetEntry || !assetEntry.id) {
return <div>{__("Asset not found")}</div>; return <div>{__("Asset not found")}</div>;
} }
@@ -64,16 +65,16 @@ export default function AssetDetailsPage(props: Props) {
); );
const deleteAsset = useDeleteAsset(assetEntry, connectionId); const deleteAsset = useDeleteAsset(assetEntry, connectionId);
const vendors = assetEntry?.vendors?.edges.map((edge: any) => edge.node) ?? []; const vendors = assetEntry.vendors?.edges.map((edge: any) => edge.node) ?? [];
const vendorIds = vendors.map((vendor: any) => vendor.id); const vendorIds = vendors.map((vendor: any) => vendor.id);
const { control, formState, handleSubmit, register, reset } = useFormWithSchema(updateAssetSchema, { const { control, formState, handleSubmit, register, reset } = useFormWithSchema(updateAssetSchema, {
defaultValues: { defaultValues: {
name: assetEntry?.name || "", name: assetEntry.name || "",
amount: assetEntry?.amount || 0, amount: assetEntry.amount || 0,
assetType: assetEntry?.assetType || "VIRTUAL", assetType: assetEntry.assetType || "VIRTUAL",
dataTypesStored: assetEntry?.dataTypesStored || "", dataTypesStored: assetEntry.dataTypesStored || "",
ownerId: assetEntry?.owner?.id || "", ownerId: assetEntry.owner?.id || "",
vendorIds: vendorIds, vendorIds: vendorIds,
}, },
}); });
@@ -82,7 +83,7 @@ export default function AssetDetailsPage(props: Props) {
const onSubmit = handleSubmit(async (formData) => { const onSubmit = handleSubmit(async (formData) => {
await updateAsset({ await updateAsset({
id: assetEntry?.id, id: assetEntry.id!,
...formData, ...formData,
}); });
reset(formData); reset(formData);
@@ -110,7 +111,7 @@ export default function AssetDetailsPage(props: Props) {
<div className="flex justify-between items-start"> <div className="flex justify-between items-start">
<div className="flex items-center gap-4"> <div className="flex items-center gap-4">
<div className="text-2xl">{assetEntry?.name}</div> <div className="text-2xl">{assetEntry?.name}</div>
<Badge variant={getAssetTypeVariant(assetEntry?.assetType)}> <Badge variant={getAssetTypeVariant(assetEntry?.assetType ?? "VIRTUAL")}>
{assetEntry?.assetType === "PHYSICAL" ? __("Physical") : __("Virtual")} {assetEntry?.assetType === "PHYSICAL" ? __("Physical") : __("Virtual")}
</Badge> </Badge>
</div> </div>

View File

@@ -97,7 +97,11 @@ export function RowButton({
"py-2 bg-highlight hover:bg-highlight-hover active:bg-highlight-pressed cursor-pointer w-full flex gap-2 items-center justify-center text-sm text-txt-secondary", "py-2 bg-highlight hover:bg-highlight-hover active:bg-highlight-pressed cursor-pointer w-full flex gap-2 items-center justify-center text-sm text-txt-secondary",
props.className, props.className,
)} )}
style={{ gridColumnEnd: -1, gridColumnStart: 1 }} style={{
gridColumnEnd: -1,
gridColumnStart: 1,
...props.style,
}}
> >
<IconComponent size={16} /> <IconComponent size={16} />
{children} {children}

View File

@@ -146,12 +146,13 @@ export function Select<T>({
<Content <Content
position="popper" position="popper"
sideOffset={5} sideOffset={5}
{...dropdownProps}
style={{ style={{
minWidth: "var(--radix-select-trigger-width)", minWidth: "var(--radix-select-trigger-width)",
maxHeight: maxHeight:
"var(--radix-select-content-available-height)", "var(--radix-select-content-available-height)",
...dropdownProps?.style,
}} }}
{...dropdownProps}
className={content({ className: dropdownProps?.className })} className={content({ className: dropdownProps?.className })}
> >
{onSearch && ( {onSearch && (

View File

@@ -24,8 +24,10 @@ export function TextCell(props: Props) {
if (props.required && inputValue === "") { if (props.required && inputValue === "") {
return; return;
} }
setValue(inputValue); if (inputValue !== props.defaultValue) {
onUpdate(props.name, inputValue); setValue(inputValue);
onUpdate(props.name, inputValue);
}
}; };
return ( return (